diff --git a/.github/workflows/stable-release.yml b/.github/workflows/stable-release.yml index e5444d36..0bdd5a3b 100644 --- a/.github/workflows/stable-release.yml +++ b/.github/workflows/stable-release.yml @@ -17,12 +17,12 @@ on: description: 'Python minor version' required: true type: string - default: "11" + default: "12" python_patch: description: 'Python patch version' required: true type: string - default: "9" + default: "7" jobs: diff --git a/.github/workflows/windows_release_dependencies.yml b/.github/workflows/windows_release_dependencies.yml index 8d3a8665..85e6a52f 100644 --- a/.github/workflows/windows_release_dependencies.yml +++ b/.github/workflows/windows_release_dependencies.yml @@ -12,7 +12,7 @@ on: description: 'extra dependencies' required: false type: string - default: "\"numpy<2\"" + default: "" cu: description: 'cuda version' required: true @@ -23,13 +23,13 @@ on: description: 'python minor version' required: true type: string - default: "11" + default: "12" python_patch: description: 'python patch version' required: true type: string - default: "9" + default: "7" # push: # branches: # - master diff --git a/.github/workflows/windows_release_package.yml b/.github/workflows/windows_release_package.yml index 84d99b8a..11e724ba 100644 --- a/.github/workflows/windows_release_package.yml +++ b/.github/workflows/windows_release_package.yml @@ -13,13 +13,13 @@ on: description: 'python minor version' required: true type: string - default: "11" + default: "12" python_patch: description: 'python patch version' required: true type: string - default: "9" + default: "7" # push: # branches: # - master diff --git a/README.md b/README.md index 745cf1a3..8e5cef45 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,8 @@ To run it on services like paperspace, kaggle or colab you can use my [Jupyter N ## Manual Install (Windows, Linux) +Note that some dependencies do not yet support python 3.13 so using 3.12 is recommended. + Git clone this repo. Put your SD checkpoints (the huge ckpt/safetensors files) in: models/checkpoints diff --git a/app/frontend_management.py b/app/frontend_management.py index 9c832e46..6f20e439 100644 --- a/app/frontend_management.py +++ b/app/frontend_management.py @@ -151,6 +151,15 @@ class FrontendManager: return cls.DEFAULT_FRONTEND_PATH repo_owner, repo_name, version = cls.parse_version_string(version_string) + + if version.startswith("v"): + expected_path = str(Path(cls.CUSTOM_FRONTENDS_ROOT) / f"{repo_owner}_{repo_name}" / version.lstrip("v")) + if os.path.exists(expected_path): + logging.info(f"Using existing copy of specific frontend version tag: {repo_owner}/{repo_name}@{version}") + return expected_path + + logging.info(f"Initializing frontend: {repo_owner}/{repo_name}@{version}, requesting version details from GitHub...") + provider = provider or FrontEndProvider(repo_owner, repo_name) release = provider.get_release(version) diff --git a/comfy/controlnet.py b/comfy/controlnet.py index 1d24afa6..d2744e42 100644 --- a/comfy/controlnet.py +++ b/comfy/controlnet.py @@ -60,7 +60,7 @@ class StrengthType(Enum): LINEAR_UP = 2 class ControlBase: - def __init__(self, device=None): + def __init__(self): self.cond_hint_original = None self.cond_hint = None self.strength = 1.0 @@ -72,10 +72,6 @@ class ControlBase: self.compression_ratio = 8 self.upscale_algorithm = 'nearest-exact' self.extra_args = {} - - if device is None: - device = comfy.model_management.get_torch_device() - self.device = device self.previous_controlnet = None self.extra_conds = [] self.strength_type = StrengthType.CONSTANT @@ -185,8 +181,8 @@ class ControlBase: class ControlNet(ControlBase): - def __init__(self, control_model=None, global_average_pooling=False, compression_ratio=8, latent_format=None, device=None, load_device=None, manual_cast_dtype=None, extra_conds=["y"], strength_type=StrengthType.CONSTANT, concat_mask=False): - super().__init__(device) + def __init__(self, control_model=None, global_average_pooling=False, compression_ratio=8, latent_format=None, load_device=None, manual_cast_dtype=None, extra_conds=["y"], strength_type=StrengthType.CONSTANT, concat_mask=False): + super().__init__() self.control_model = control_model self.load_device = load_device if control_model is not None: @@ -242,7 +238,7 @@ class ControlNet(ControlBase): to_concat.append(comfy.utils.repeat_to_batch_size(c, self.cond_hint.shape[0])) self.cond_hint = torch.cat([self.cond_hint] + to_concat, dim=1) - self.cond_hint = self.cond_hint.to(device=self.device, dtype=dtype) + self.cond_hint = self.cond_hint.to(device=x_noisy.device, dtype=dtype) if x_noisy.shape[0] != self.cond_hint.shape[0]: self.cond_hint = broadcast_image_to(self.cond_hint, x_noisy.shape[0], batched_number) @@ -341,8 +337,8 @@ class ControlLoraOps: class ControlLora(ControlNet): - def __init__(self, control_weights, global_average_pooling=False, device=None, model_options={}): #TODO? model_options - ControlBase.__init__(self, device) + def __init__(self, control_weights, global_average_pooling=False, model_options={}): #TODO? model_options + ControlBase.__init__(self) self.control_weights = control_weights self.global_average_pooling = global_average_pooling self.extra_conds += ["y"] @@ -662,12 +658,15 @@ def load_controlnet(ckpt_path, model=None, model_options={}): class T2IAdapter(ControlBase): def __init__(self, t2i_model, channels_in, compression_ratio, upscale_algorithm, device=None): - super().__init__(device) + super().__init__() self.t2i_model = t2i_model self.channels_in = channels_in self.control_input = None self.compression_ratio = compression_ratio self.upscale_algorithm = upscale_algorithm + if device is None: + device = comfy.model_management.get_torch_device() + self.device = device def scale_image_to(self, width, height): unshuffle_amount = self.t2i_model.unshuffle_amount diff --git a/comfy/float.py b/comfy/float.py index 0c8f1d6c..521316fd 100644 --- a/comfy/float.py +++ b/comfy/float.py @@ -41,6 +41,8 @@ def manual_stochastic_round_to_float8(x, dtype, generator=None): (2.0 ** (-EXPONENT_BIAS + 1)) * abs_x ) + inf = torch.finfo(dtype) + torch.clamp(sign, min=inf.min, max=inf.max, out=sign) return sign diff --git a/comfy/k_diffusion/sampling.py b/comfy/k_diffusion/sampling.py index d5fc05cb..605b1092 100644 --- a/comfy/k_diffusion/sampling.py +++ b/comfy/k_diffusion/sampling.py @@ -166,6 +166,8 @@ def sample_euler(model, x, sigmas, extra_args=None, callback=None, disable=None, @torch.no_grad() def sample_euler_ancestral(model, x, sigmas, extra_args=None, callback=None, disable=None, eta=1., s_noise=1., noise_sampler=None): + if isinstance(model.inner_model.inner_model.model_sampling, comfy.model_sampling.CONST): + return sample_euler_ancestral_RF(model, x, sigmas, extra_args, callback, disable, eta, s_noise, noise_sampler) """Ancestral sampling with Euler method steps.""" extra_args = {} if extra_args is None else extra_args noise_sampler = default_noise_sampler(x) if noise_sampler is None else noise_sampler @@ -183,6 +185,29 @@ def sample_euler_ancestral(model, x, sigmas, extra_args=None, callback=None, dis x = x + noise_sampler(sigmas[i], sigmas[i + 1]) * s_noise * sigma_up return x +@torch.no_grad() +def sample_euler_ancestral_RF(model, x, sigmas, extra_args=None, callback=None, disable=None, eta=1.0, s_noise=1., noise_sampler=None): + """Ancestral sampling with Euler method steps.""" + extra_args = {} if extra_args is None else extra_args + noise_sampler = default_noise_sampler(x) if noise_sampler is None else noise_sampler + s_in = x.new_ones([x.shape[0]]) + for i in trange(len(sigmas) - 1, disable=disable): + denoised = model(x, sigmas[i] * s_in, **extra_args) + # sigma_down, sigma_up = get_ancestral_step(sigmas[i], sigmas[i + 1], eta=eta) + downstep_ratio = 1 + (sigmas[i+1]/sigmas[i] - 1) * eta + sigma_down = sigmas[i+1] * downstep_ratio + alpha_ip1 = 1 - sigmas[i+1] + alpha_down = 1 - sigma_down + renoise_coeff = (sigmas[i+1]**2 - sigma_down**2*alpha_ip1**2/alpha_down**2)**0.5 + if callback is not None: + callback({'x': x, 'i': i, 'sigma': sigmas[i], 'sigma_hat': sigmas[i], 'denoised': denoised}) + + # Euler method + sigma_down_i_ratio = sigma_down / sigmas[i] + x = sigma_down_i_ratio * x + (1 - sigma_down_i_ratio) * denoised + if sigmas[i + 1] > 0 and eta > 0: + x = (alpha_ip1/alpha_down) * x + noise_sampler(sigmas[i], sigmas[i + 1]) * s_noise * renoise_coeff + return x @torch.no_grad() def sample_heun(model, x, sigmas, extra_args=None, callback=None, disable=None, s_churn=0., s_tmin=0., s_tmax=float('inf'), s_noise=1.): @@ -1192,7 +1217,6 @@ def sample_euler_cfg_pp(model, x, sigmas, extra_args=None, callback=None, disabl d = to_d(x, sigma_hat, temp[0]) if callback is not None: callback({'x': x, 'i': i, 'sigma': sigmas[i], 'sigma_hat': sigma_hat, 'denoised': denoised}) - dt = sigmas[i + 1] - sigma_hat # Euler method x = denoised + d * sigmas[i + 1] return x @@ -1219,7 +1243,6 @@ def sample_euler_ancestral_cfg_pp(model, x, sigmas, extra_args=None, callback=No callback({'x': x, 'i': i, 'sigma': sigmas[i], 'sigma_hat': sigmas[i], 'denoised': denoised}) d = to_d(x, sigmas[i], temp[0]) # Euler method - dt = sigma_down - sigmas[i] x = denoised + d * sigma_down if sigmas[i + 1] > 0: x = x + noise_sampler(sigmas[i], sigmas[i + 1]) * s_noise * sigma_up @@ -1250,7 +1273,6 @@ def sample_dpmpp_2s_ancestral_cfg_pp(model, x, sigmas, extra_args=None, callback if sigma_down == 0: # Euler method d = to_d(x, sigmas[i], temp[0]) - dt = sigma_down - sigmas[i] x = denoised + d * sigma_down else: # DPM-Solver++(2S) @@ -1298,4 +1320,4 @@ def sample_dpmpp_2m_cfg_pp(model, x, sigmas, extra_args=None, callback=None, dis denoised_mix = -torch.exp(-h) * uncond_denoised - torch.expm1(-h) * (1 / (2 * r)) * (denoised - old_uncond_denoised) x = denoised + denoised_mix + torch.exp(-h) * x old_uncond_denoised = uncond_denoised - return x \ No newline at end of file + return x diff --git a/comfy/latent_formats.py b/comfy/latent_formats.py index 191c7091..a48f60c7 100644 --- a/comfy/latent_formats.py +++ b/comfy/latent_formats.py @@ -175,3 +175,30 @@ class Flux(SD3): def process_out(self, latent): return (latent / self.scale_factor) + self.shift_factor + +class Mochi(LatentFormat): + latent_channels = 12 + + def __init__(self): + self.scale_factor = 1.0 + self.latents_mean = torch.tensor([-0.06730895953510081, -0.038011381506090416, -0.07477820912866141, + -0.05565264470995561, 0.012767231469026969, -0.04703542746246419, + 0.043896967884726704, -0.09346305707025976, -0.09918314763016893, + -0.008729793427399178, -0.011931556316503654, -0.0321993391887285]).view(1, self.latent_channels, 1, 1, 1) + self.latents_std = torch.tensor([0.9263795028493863, 0.9248894543193766, 0.9393059390890617, + 0.959253732819592, 0.8244560132752793, 0.917259975397747, + 0.9294154431013696, 1.3720942357788521, 0.881393668867029, + 0.9168315692124348, 0.9185249279345552, 0.9274757570805041]).view(1, self.latent_channels, 1, 1, 1) + + self.latent_rgb_factors = None #TODO + self.taesd_decoder_name = None #TODO + + def process_in(self, latent): + latents_mean = self.latents_mean.to(latent.device, latent.dtype) + latents_std = self.latents_std.to(latent.device, latent.dtype) + return (latent - latents_mean) * self.scale_factor / latents_std + + def process_out(self, latent): + latents_mean = self.latents_mean.to(latent.device, latent.dtype) + latents_std = self.latents_std.to(latent.device, latent.dtype) + return latent * latents_std / self.scale_factor + latents_mean diff --git a/comfy/ldm/common_dit.py b/comfy/ldm/common_dit.py index 5aebaf9e..cb6b7414 100644 --- a/comfy/ldm/common_dit.py +++ b/comfy/ldm/common_dit.py @@ -13,9 +13,15 @@ try: except: rms_norm_torch = None -def rms_norm(x, weight, eps=1e-6): +def rms_norm(x, weight=None, eps=1e-6): if rms_norm_torch is not None and not (torch.jit.is_tracing() or torch.jit.is_scripting()): - return rms_norm_torch(x, weight.shape, weight=comfy.ops.cast_to(weight, dtype=x.dtype, device=x.device), eps=eps) + if weight is None: + return rms_norm_torch(x, (x.shape[-1],), eps=eps) + else: + return rms_norm_torch(x, weight.shape, weight=comfy.ops.cast_to(weight, dtype=x.dtype, device=x.device), eps=eps) else: - rrms = torch.rsqrt(torch.mean(x**2, dim=-1, keepdim=True) + eps) - return (x * rrms) * comfy.ops.cast_to(weight, dtype=x.dtype, device=x.device) + r = x * torch.rsqrt(torch.mean(x**2, dim=-1, keepdim=True) + eps) + if weight is None: + return r + else: + return r * comfy.ops.cast_to(weight, dtype=x.dtype, device=x.device) diff --git a/comfy/ldm/genmo/joint_model/asymm_models_joint.py b/comfy/ldm/genmo/joint_model/asymm_models_joint.py new file mode 100644 index 00000000..c36a0006 --- /dev/null +++ b/comfy/ldm/genmo/joint_model/asymm_models_joint.py @@ -0,0 +1,541 @@ +#original code from https://github.com/genmoai/models under apache 2.0 license +#adapted to ComfyUI + +from typing import Dict, List, Optional, Tuple + +import torch +import torch.nn as nn +import torch.nn.functional as F +from einops import rearrange +# from flash_attn import flash_attn_varlen_qkvpacked_func +from comfy.ldm.modules.attention import optimized_attention + +from .layers import ( + FeedForward, + PatchEmbed, + RMSNorm, + TimestepEmbedder, +) + +from .rope_mixed import ( + compute_mixed_rotation, + create_position_matrix, +) +from .temporal_rope import apply_rotary_emb_qk_real +from .utils import ( + AttentionPool, + modulate, +) + +import comfy.ldm.common_dit +import comfy.ops + + +def modulated_rmsnorm(x, scale, eps=1e-6): + # Normalize and modulate + x_normed = comfy.ldm.common_dit.rms_norm(x, eps=eps) + x_modulated = x_normed * (1 + scale.unsqueeze(1)) + + return x_modulated + + +def residual_tanh_gated_rmsnorm(x, x_res, gate, eps=1e-6): + # Apply tanh to gate + tanh_gate = torch.tanh(gate).unsqueeze(1) + + # Normalize and apply gated scaling + x_normed = comfy.ldm.common_dit.rms_norm(x_res, eps=eps) * tanh_gate + + # Apply residual connection + output = x + x_normed + + return output + +class AsymmetricAttention(nn.Module): + def __init__( + self, + dim_x: int, + dim_y: int, + num_heads: int = 8, + qkv_bias: bool = True, + qk_norm: bool = False, + attn_drop: float = 0.0, + update_y: bool = True, + out_bias: bool = True, + attend_to_padding: bool = False, + softmax_scale: Optional[float] = None, + device: Optional[torch.device] = None, + dtype=None, + operations=None, + ): + super().__init__() + self.dim_x = dim_x + self.dim_y = dim_y + self.num_heads = num_heads + self.head_dim = dim_x // num_heads + self.attn_drop = attn_drop + self.update_y = update_y + self.attend_to_padding = attend_to_padding + self.softmax_scale = softmax_scale + if dim_x % num_heads != 0: + raise ValueError( + f"dim_x={dim_x} should be divisible by num_heads={num_heads}" + ) + + # Input layers. + self.qkv_bias = qkv_bias + self.qkv_x = operations.Linear(dim_x, 3 * dim_x, bias=qkv_bias, device=device, dtype=dtype) + # Project text features to match visual features (dim_y -> dim_x) + self.qkv_y = operations.Linear(dim_y, 3 * dim_x, bias=qkv_bias, device=device, dtype=dtype) + + # Query and key normalization for stability. + assert qk_norm + self.q_norm_x = RMSNorm(self.head_dim, device=device, dtype=dtype) + self.k_norm_x = RMSNorm(self.head_dim, device=device, dtype=dtype) + self.q_norm_y = RMSNorm(self.head_dim, device=device, dtype=dtype) + self.k_norm_y = RMSNorm(self.head_dim, device=device, dtype=dtype) + + # Output layers. y features go back down from dim_x -> dim_y. + self.proj_x = operations.Linear(dim_x, dim_x, bias=out_bias, device=device, dtype=dtype) + self.proj_y = ( + operations.Linear(dim_x, dim_y, bias=out_bias, device=device, dtype=dtype) + if update_y + else nn.Identity() + ) + + def forward( + self, + x: torch.Tensor, # (B, N, dim_x) + y: torch.Tensor, # (B, L, dim_y) + scale_x: torch.Tensor, # (B, dim_x), modulation for pre-RMSNorm. + scale_y: torch.Tensor, # (B, dim_y), modulation for pre-RMSNorm. + crop_y, + **rope_rotation, + ) -> Tuple[torch.Tensor, torch.Tensor]: + rope_cos = rope_rotation.get("rope_cos") + rope_sin = rope_rotation.get("rope_sin") + # Pre-norm for visual features + x = modulated_rmsnorm(x, scale_x) # (B, M, dim_x) where M = N / cp_group_size + + # Process visual features + # qkv_x = self.qkv_x(x) # (B, M, 3 * dim_x) + # assert qkv_x.dtype == torch.bfloat16 + # qkv_x = all_to_all_collect_tokens( + # qkv_x, self.num_heads + # ) # (3, B, N, local_h, head_dim) + + # Process text features + y = modulated_rmsnorm(y, scale_y) # (B, L, dim_y) + q_y, k_y, v_y = self.qkv_y(y).view(y.shape[0], y.shape[1], 3, self.num_heads, -1).unbind(2) # (B, N, local_h, head_dim) + + q_y = self.q_norm_y(q_y) + k_y = self.k_norm_y(k_y) + + # Split qkv_x into q, k, v + q_x, k_x, v_x = self.qkv_x(x).view(x.shape[0], x.shape[1], 3, self.num_heads, -1).unbind(2) # (B, N, local_h, head_dim) + q_x = self.q_norm_x(q_x) + q_x = apply_rotary_emb_qk_real(q_x, rope_cos, rope_sin) + k_x = self.k_norm_x(k_x) + k_x = apply_rotary_emb_qk_real(k_x, rope_cos, rope_sin) + + q = torch.cat([q_x, q_y[:, :crop_y]], dim=1).transpose(1, 2) + k = torch.cat([k_x, k_y[:, :crop_y]], dim=1).transpose(1, 2) + v = torch.cat([v_x, v_y[:, :crop_y]], dim=1).transpose(1, 2) + + xy = optimized_attention(q, + k, + v, self.num_heads, skip_reshape=True) + + x, y = torch.tensor_split(xy, (q_x.shape[1],), dim=1) + x = self.proj_x(x) + o = torch.zeros(y.shape[0], q_y.shape[1], y.shape[-1], device=y.device, dtype=y.dtype) + o[:, :y.shape[1]] = y + + y = self.proj_y(o) + # print("ox", x) + # print("oy", y) + return x, y + + +class AsymmetricJointBlock(nn.Module): + def __init__( + self, + hidden_size_x: int, + hidden_size_y: int, + num_heads: int, + *, + mlp_ratio_x: float = 8.0, # Ratio of hidden size to d_model for MLP for visual tokens. + mlp_ratio_y: float = 4.0, # Ratio of hidden size to d_model for MLP for text tokens. + update_y: bool = True, # Whether to update text tokens in this block. + device: Optional[torch.device] = None, + dtype=None, + operations=None, + **block_kwargs, + ): + super().__init__() + self.update_y = update_y + self.hidden_size_x = hidden_size_x + self.hidden_size_y = hidden_size_y + self.mod_x = operations.Linear(hidden_size_x, 4 * hidden_size_x, device=device, dtype=dtype) + if self.update_y: + self.mod_y = operations.Linear(hidden_size_x, 4 * hidden_size_y, device=device, dtype=dtype) + else: + self.mod_y = operations.Linear(hidden_size_x, hidden_size_y, device=device, dtype=dtype) + + # Self-attention: + self.attn = AsymmetricAttention( + hidden_size_x, + hidden_size_y, + num_heads=num_heads, + update_y=update_y, + device=device, + dtype=dtype, + operations=operations, + **block_kwargs, + ) + + # MLP. + mlp_hidden_dim_x = int(hidden_size_x * mlp_ratio_x) + assert mlp_hidden_dim_x == int(1536 * 8) + self.mlp_x = FeedForward( + in_features=hidden_size_x, + hidden_size=mlp_hidden_dim_x, + multiple_of=256, + ffn_dim_multiplier=None, + device=device, + dtype=dtype, + operations=operations, + ) + + # MLP for text not needed in last block. + if self.update_y: + mlp_hidden_dim_y = int(hidden_size_y * mlp_ratio_y) + self.mlp_y = FeedForward( + in_features=hidden_size_y, + hidden_size=mlp_hidden_dim_y, + multiple_of=256, + ffn_dim_multiplier=None, + device=device, + dtype=dtype, + operations=operations, + ) + + def forward( + self, + x: torch.Tensor, + c: torch.Tensor, + y: torch.Tensor, + **attn_kwargs, + ): + """Forward pass of a block. + + Args: + x: (B, N, dim) tensor of visual tokens + c: (B, dim) tensor of conditioned features + y: (B, L, dim) tensor of text tokens + num_frames: Number of frames in the video. N = num_frames * num_spatial_tokens + + Returns: + x: (B, N, dim) tensor of visual tokens after block + y: (B, L, dim) tensor of text tokens after block + """ + N = x.size(1) + + c = F.silu(c) + mod_x = self.mod_x(c) + scale_msa_x, gate_msa_x, scale_mlp_x, gate_mlp_x = mod_x.chunk(4, dim=1) + + mod_y = self.mod_y(c) + if self.update_y: + scale_msa_y, gate_msa_y, scale_mlp_y, gate_mlp_y = mod_y.chunk(4, dim=1) + else: + scale_msa_y = mod_y + + # Self-attention block. + x_attn, y_attn = self.attn( + x, + y, + scale_x=scale_msa_x, + scale_y=scale_msa_y, + **attn_kwargs, + ) + + assert x_attn.size(1) == N + x = residual_tanh_gated_rmsnorm(x, x_attn, gate_msa_x) + if self.update_y: + y = residual_tanh_gated_rmsnorm(y, y_attn, gate_msa_y) + + # MLP block. + x = self.ff_block_x(x, scale_mlp_x, gate_mlp_x) + if self.update_y: + y = self.ff_block_y(y, scale_mlp_y, gate_mlp_y) + + return x, y + + def ff_block_x(self, x, scale_x, gate_x): + x_mod = modulated_rmsnorm(x, scale_x) + x_res = self.mlp_x(x_mod) + x = residual_tanh_gated_rmsnorm(x, x_res, gate_x) # Sandwich norm + return x + + def ff_block_y(self, y, scale_y, gate_y): + y_mod = modulated_rmsnorm(y, scale_y) + y_res = self.mlp_y(y_mod) + y = residual_tanh_gated_rmsnorm(y, y_res, gate_y) # Sandwich norm + return y + + +class FinalLayer(nn.Module): + """ + The final layer of DiT. + """ + + def __init__( + self, + hidden_size, + patch_size, + out_channels, + device: Optional[torch.device] = None, + dtype=None, + operations=None, + ): + super().__init__() + self.norm_final = operations.LayerNorm( + hidden_size, elementwise_affine=False, eps=1e-6, device=device, dtype=dtype + ) + self.mod = operations.Linear(hidden_size, 2 * hidden_size, device=device, dtype=dtype) + self.linear = operations.Linear( + hidden_size, patch_size * patch_size * out_channels, device=device, dtype=dtype + ) + + def forward(self, x, c): + c = F.silu(c) + shift, scale = self.mod(c).chunk(2, dim=1) + x = modulate(self.norm_final(x), shift, scale) + x = self.linear(x) + return x + + +class AsymmDiTJoint(nn.Module): + """ + Diffusion model with a Transformer backbone. + + Ingests text embeddings instead of a label. + """ + + def __init__( + self, + *, + patch_size=2, + in_channels=4, + hidden_size_x=1152, + hidden_size_y=1152, + depth=48, + num_heads=16, + mlp_ratio_x=8.0, + mlp_ratio_y=4.0, + use_t5: bool = False, + t5_feat_dim: int = 4096, + t5_token_length: int = 256, + learn_sigma=True, + patch_embed_bias: bool = True, + timestep_mlp_bias: bool = True, + attend_to_padding: bool = False, + timestep_scale: Optional[float] = None, + use_extended_posenc: bool = False, + posenc_preserve_area: bool = False, + rope_theta: float = 10000.0, + image_model=None, + device: Optional[torch.device] = None, + dtype=None, + operations=None, + **block_kwargs, + ): + super().__init__() + + self.dtype = dtype + self.learn_sigma = learn_sigma + self.in_channels = in_channels + self.out_channels = in_channels * 2 if learn_sigma else in_channels + self.patch_size = patch_size + self.num_heads = num_heads + self.hidden_size_x = hidden_size_x + self.hidden_size_y = hidden_size_y + self.head_dim = ( + hidden_size_x // num_heads + ) # Head dimension and count is determined by visual. + self.attend_to_padding = attend_to_padding + self.use_extended_posenc = use_extended_posenc + self.posenc_preserve_area = posenc_preserve_area + self.use_t5 = use_t5 + self.t5_token_length = t5_token_length + self.t5_feat_dim = t5_feat_dim + self.rope_theta = ( + rope_theta # Scaling factor for frequency computation for temporal RoPE. + ) + + self.x_embedder = PatchEmbed( + patch_size=patch_size, + in_chans=in_channels, + embed_dim=hidden_size_x, + bias=patch_embed_bias, + dtype=dtype, + device=device, + operations=operations + ) + # Conditionings + # Timestep + self.t_embedder = TimestepEmbedder( + hidden_size_x, bias=timestep_mlp_bias, timestep_scale=timestep_scale, dtype=dtype, device=device, operations=operations + ) + + if self.use_t5: + # Caption Pooling (T5) + self.t5_y_embedder = AttentionPool( + t5_feat_dim, num_heads=8, output_dim=hidden_size_x, dtype=dtype, device=device, operations=operations + ) + + # Dense Embedding Projection (T5) + self.t5_yproj = operations.Linear( + t5_feat_dim, hidden_size_y, bias=True, dtype=dtype, device=device + ) + + # Initialize pos_frequencies as an empty parameter. + self.pos_frequencies = nn.Parameter( + torch.empty(3, self.num_heads, self.head_dim // 2, dtype=dtype, device=device) + ) + + assert not self.attend_to_padding + + # for depth 48: + # b = 0: AsymmetricJointBlock, update_y=True + # b = 1: AsymmetricJointBlock, update_y=True + # ... + # b = 46: AsymmetricJointBlock, update_y=True + # b = 47: AsymmetricJointBlock, update_y=False. No need to update text features. + blocks = [] + for b in range(depth): + # Joint multi-modal block + update_y = b < depth - 1 + block = AsymmetricJointBlock( + hidden_size_x, + hidden_size_y, + num_heads, + mlp_ratio_x=mlp_ratio_x, + mlp_ratio_y=mlp_ratio_y, + update_y=update_y, + attend_to_padding=attend_to_padding, + device=device, + dtype=dtype, + operations=operations, + **block_kwargs, + ) + + blocks.append(block) + self.blocks = nn.ModuleList(blocks) + + self.final_layer = FinalLayer( + hidden_size_x, patch_size, self.out_channels, dtype=dtype, device=device, operations=operations + ) + + def embed_x(self, x: torch.Tensor) -> torch.Tensor: + """ + Args: + x: (B, C=12, T, H, W) tensor of visual tokens + + Returns: + x: (B, C=3072, N) tensor of visual tokens with positional embedding. + """ + return self.x_embedder(x) # Convert BcTHW to BCN + + def prepare( + self, + x: torch.Tensor, + sigma: torch.Tensor, + t5_feat: torch.Tensor, + t5_mask: torch.Tensor, + ): + """Prepare input and conditioning embeddings.""" + # Visual patch embeddings with positional encoding. + T, H, W = x.shape[-3:] + pH, pW = H // self.patch_size, W // self.patch_size + x = self.embed_x(x) # (B, N, D), where N = T * H * W / patch_size ** 2 + assert x.ndim == 3 + B = x.size(0) + + + pH, pW = H // self.patch_size, W // self.patch_size + N = T * pH * pW + assert x.size(1) == N + pos = create_position_matrix( + T, pH=pH, pW=pW, device=x.device, dtype=torch.float32 + ) # (N, 3) + rope_cos, rope_sin = compute_mixed_rotation( + freqs=comfy.ops.cast_to(self.pos_frequencies, dtype=x.dtype, device=x.device), pos=pos + ) # Each are (N, num_heads, dim // 2) + + c_t = self.t_embedder(1 - sigma, out_dtype=x.dtype) # (B, D) + + t5_y_pool = self.t5_y_embedder(t5_feat, t5_mask) # (B, D) + + c = c_t + t5_y_pool + + y_feat = self.t5_yproj(t5_feat) # (B, L, t5_feat_dim) --> (B, L, D) + + return x, c, y_feat, rope_cos, rope_sin + + def forward( + self, + x: torch.Tensor, + timestep: torch.Tensor, + context: List[torch.Tensor], + attention_mask: List[torch.Tensor], + num_tokens=256, + packed_indices: Dict[str, torch.Tensor] = None, + rope_cos: torch.Tensor = None, + rope_sin: torch.Tensor = None, + control=None, **kwargs + ): + y_feat = context + y_mask = attention_mask + sigma = timestep + """Forward pass of DiT. + + Args: + x: (B, C, T, H, W) tensor of spatial inputs (images or latent representations of images) + sigma: (B,) tensor of noise standard deviations + y_feat: List((B, L, y_feat_dim) tensor of caption token features. For SDXL text encoders: L=77, y_feat_dim=2048) + y_mask: List((B, L) boolean tensor indicating which tokens are not padding) + packed_indices: Dict with keys for Flash Attention. Result of compute_packed_indices. + """ + B, _, T, H, W = x.shape + + x, c, y_feat, rope_cos, rope_sin = self.prepare( + x, sigma, y_feat, y_mask + ) + del y_mask + + for i, block in enumerate(self.blocks): + x, y_feat = block( + x, + c, + y_feat, + rope_cos=rope_cos, + rope_sin=rope_sin, + crop_y=num_tokens, + ) # (B, M, D), (B, L, D) + del y_feat # Final layers don't use dense text features. + + x = self.final_layer(x, c) # (B, M, patch_size ** 2 * out_channels) + x = rearrange( + x, + "B (T hp wp) (p1 p2 c) -> B c T (hp p1) (wp p2)", + T=T, + hp=H // self.patch_size, + wp=W // self.patch_size, + p1=self.patch_size, + p2=self.patch_size, + c=self.out_channels, + ) + + return -x diff --git a/comfy/ldm/genmo/joint_model/layers.py b/comfy/ldm/genmo/joint_model/layers.py new file mode 100644 index 00000000..51d97955 --- /dev/null +++ b/comfy/ldm/genmo/joint_model/layers.py @@ -0,0 +1,164 @@ +#original code from https://github.com/genmoai/models under apache 2.0 license +#adapted to ComfyUI + +import collections.abc +import math +from itertools import repeat +from typing import Callable, Optional + +import torch +import torch.nn as nn +import torch.nn.functional as F +from einops import rearrange +import comfy.ldm.common_dit + + +# From PyTorch internals +def _ntuple(n): + def parse(x): + if isinstance(x, collections.abc.Iterable) and not isinstance(x, str): + return tuple(x) + return tuple(repeat(x, n)) + + return parse + + +to_2tuple = _ntuple(2) + + +class TimestepEmbedder(nn.Module): + def __init__( + self, + hidden_size: int, + frequency_embedding_size: int = 256, + *, + bias: bool = True, + timestep_scale: Optional[float] = None, + dtype=None, + device=None, + operations=None, + ): + super().__init__() + self.mlp = nn.Sequential( + operations.Linear(frequency_embedding_size, hidden_size, bias=bias, dtype=dtype, device=device), + nn.SiLU(), + operations.Linear(hidden_size, hidden_size, bias=bias, dtype=dtype, device=device), + ) + self.frequency_embedding_size = frequency_embedding_size + self.timestep_scale = timestep_scale + + @staticmethod + def timestep_embedding(t, dim, max_period=10000): + half = dim // 2 + freqs = torch.arange(start=0, end=half, dtype=torch.float32, device=t.device) + freqs.mul_(-math.log(max_period) / half).exp_() + args = t[:, None].float() * freqs[None] + embedding = torch.cat([torch.cos(args), torch.sin(args)], dim=-1) + if dim % 2: + embedding = torch.cat( + [embedding, torch.zeros_like(embedding[:, :1])], dim=-1 + ) + return embedding + + def forward(self, t, out_dtype): + if self.timestep_scale is not None: + t = t * self.timestep_scale + t_freq = self.timestep_embedding(t, self.frequency_embedding_size).to(dtype=out_dtype) + t_emb = self.mlp(t_freq) + return t_emb + + +class FeedForward(nn.Module): + def __init__( + self, + in_features: int, + hidden_size: int, + multiple_of: int, + ffn_dim_multiplier: Optional[float], + device: Optional[torch.device] = None, + dtype=None, + operations=None, + ): + super().__init__() + # keep parameter count and computation constant compared to standard FFN + hidden_size = int(2 * hidden_size / 3) + # custom dim factor multiplier + if ffn_dim_multiplier is not None: + hidden_size = int(ffn_dim_multiplier * hidden_size) + hidden_size = multiple_of * ((hidden_size + multiple_of - 1) // multiple_of) + + self.hidden_dim = hidden_size + self.w1 = operations.Linear(in_features, 2 * hidden_size, bias=False, device=device, dtype=dtype) + self.w2 = operations.Linear(hidden_size, in_features, bias=False, device=device, dtype=dtype) + + def forward(self, x): + x, gate = self.w1(x).chunk(2, dim=-1) + x = self.w2(F.silu(x) * gate) + return x + + +class PatchEmbed(nn.Module): + def __init__( + self, + patch_size: int = 16, + in_chans: int = 3, + embed_dim: int = 768, + norm_layer: Optional[Callable] = None, + flatten: bool = True, + bias: bool = True, + dynamic_img_pad: bool = False, + dtype=None, + device=None, + operations=None, + ): + super().__init__() + self.patch_size = to_2tuple(patch_size) + self.flatten = flatten + self.dynamic_img_pad = dynamic_img_pad + + self.proj = operations.Conv2d( + in_chans, + embed_dim, + kernel_size=patch_size, + stride=patch_size, + bias=bias, + device=device, + dtype=dtype, + ) + assert norm_layer is None + self.norm = ( + norm_layer(embed_dim, device=device) if norm_layer else nn.Identity() + ) + + def forward(self, x): + B, _C, T, H, W = x.shape + if not self.dynamic_img_pad: + assert H % self.patch_size[0] == 0, f"Input height ({H}) should be divisible by patch size ({self.patch_size[0]})." + assert W % self.patch_size[1] == 0, f"Input width ({W}) should be divisible by patch size ({self.patch_size[1]})." + else: + pad_h = (self.patch_size[0] - H % self.patch_size[0]) % self.patch_size[0] + pad_w = (self.patch_size[1] - W % self.patch_size[1]) % self.patch_size[1] + x = F.pad(x, (0, pad_w, 0, pad_h)) + + x = rearrange(x, "B C T H W -> (B T) C H W", B=B, T=T) + x = comfy.ldm.common_dit.pad_to_patch_size(x, self.patch_size, padding_mode='circular') + x = self.proj(x) + + # Flatten temporal and spatial dimensions. + if not self.flatten: + raise NotImplementedError("Must flatten output.") + x = rearrange(x, "(B T) C H W -> B (T H W) C", B=B, T=T) + + x = self.norm(x) + return x + + +class RMSNorm(torch.nn.Module): + def __init__(self, hidden_size, eps=1e-5, device=None, dtype=None): + super().__init__() + self.eps = eps + self.weight = torch.nn.Parameter(torch.empty(hidden_size, device=device, dtype=dtype)) + self.register_parameter("bias", None) + + def forward(self, x): + return comfy.ldm.common_dit.rms_norm(x, self.weight, self.eps) diff --git a/comfy/ldm/genmo/joint_model/rope_mixed.py b/comfy/ldm/genmo/joint_model/rope_mixed.py new file mode 100644 index 00000000..dee3fa21 --- /dev/null +++ b/comfy/ldm/genmo/joint_model/rope_mixed.py @@ -0,0 +1,88 @@ +#original code from https://github.com/genmoai/models under apache 2.0 license + +# import functools +import math + +import torch + + +def centers(start: float, stop, num, dtype=None, device=None): + """linspace through bin centers. + + Args: + start (float): Start of the range. + stop (float): End of the range. + num (int): Number of points. + dtype (torch.dtype): Data type of the points. + device (torch.device): Device of the points. + + Returns: + centers (Tensor): Centers of the bins. Shape: (num,). + """ + edges = torch.linspace(start, stop, num + 1, dtype=dtype, device=device) + return (edges[:-1] + edges[1:]) / 2 + + +# @functools.lru_cache(maxsize=1) +def create_position_matrix( + T: int, + pH: int, + pW: int, + device: torch.device, + dtype: torch.dtype, + *, + target_area: float = 36864, +): + """ + Args: + T: int - Temporal dimension + pH: int - Height dimension after patchify + pW: int - Width dimension after patchify + + Returns: + pos: [T * pH * pW, 3] - position matrix + """ + # Create 1D tensors for each dimension + t = torch.arange(T, dtype=dtype) + + # Positionally interpolate to area 36864. + # (3072x3072 frame with 16x16 patches = 192x192 latents). + # This automatically scales rope positions when the resolution changes. + # We use a large target area so the model is more sensitive + # to changes in the learned pos_frequencies matrix. + scale = math.sqrt(target_area / (pW * pH)) + w = centers(-pW * scale / 2, pW * scale / 2, pW) + h = centers(-pH * scale / 2, pH * scale / 2, pH) + + # Use meshgrid to create 3D grids + grid_t, grid_h, grid_w = torch.meshgrid(t, h, w, indexing="ij") + + # Stack and reshape the grids. + pos = torch.stack([grid_t, grid_h, grid_w], dim=-1) # [T, pH, pW, 3] + pos = pos.view(-1, 3) # [T * pH * pW, 3] + pos = pos.to(dtype=dtype, device=device) + + return pos + + +def compute_mixed_rotation( + freqs: torch.Tensor, + pos: torch.Tensor, +): + """ + Project each 3-dim position into per-head, per-head-dim 1D frequencies. + + Args: + freqs: [3, num_heads, num_freqs] - learned rotation frequency (for t, row, col) for each head position + pos: [N, 3] - position of each token + num_heads: int + + Returns: + freqs_cos: [N, num_heads, num_freqs] - cosine components + freqs_sin: [N, num_heads, num_freqs] - sine components + """ + assert freqs.ndim == 3 + freqs_sum = torch.einsum("Nd,dhf->Nhf", pos.to(freqs), freqs) + freqs_cos = torch.cos(freqs_sum) + freqs_sin = torch.sin(freqs_sum) + return freqs_cos, freqs_sin diff --git a/comfy/ldm/genmo/joint_model/temporal_rope.py b/comfy/ldm/genmo/joint_model/temporal_rope.py new file mode 100644 index 00000000..88f5d6d2 --- /dev/null +++ b/comfy/ldm/genmo/joint_model/temporal_rope.py @@ -0,0 +1,34 @@ +#original code from https://github.com/genmoai/models under apache 2.0 license + +# Based on Llama3 Implementation. +import torch + + +def apply_rotary_emb_qk_real( + xqk: torch.Tensor, + freqs_cos: torch.Tensor, + freqs_sin: torch.Tensor, +) -> torch.Tensor: + """ + Apply rotary embeddings to input tensors using the given frequency tensor without complex numbers. + + Args: + xqk (torch.Tensor): Query and/or Key tensors to apply rotary embeddings. Shape: (B, S, *, num_heads, D) + Can be either just query or just key, or both stacked along some batch or * dim. + freqs_cos (torch.Tensor): Precomputed cosine frequency tensor. + freqs_sin (torch.Tensor): Precomputed sine frequency tensor. + + Returns: + torch.Tensor: The input tensor with rotary embeddings applied. + """ + # Split the last dimension into even and odd parts + xqk_even = xqk[..., 0::2] + xqk_odd = xqk[..., 1::2] + + # Apply rotation + cos_part = (xqk_even * freqs_cos - xqk_odd * freqs_sin).type_as(xqk) + sin_part = (xqk_even * freqs_sin + xqk_odd * freqs_cos).type_as(xqk) + + # Interleave the results back into the original shape + out = torch.stack([cos_part, sin_part], dim=-1).flatten(-2) + return out diff --git a/comfy/ldm/genmo/joint_model/utils.py b/comfy/ldm/genmo/joint_model/utils.py new file mode 100644 index 00000000..41190242 --- /dev/null +++ b/comfy/ldm/genmo/joint_model/utils.py @@ -0,0 +1,102 @@ +#original code from https://github.com/genmoai/models under apache 2.0 license +#adapted to ComfyUI + +from typing import Optional, Tuple + +import torch +import torch.nn as nn +import torch.nn.functional as F + + +def modulate(x, shift, scale): + return x * (1 + scale.unsqueeze(1)) + shift.unsqueeze(1) + + +def pool_tokens(x: torch.Tensor, mask: torch.Tensor, *, keepdim=False) -> torch.Tensor: + """ + Pool tokens in x using mask. + + NOTE: We assume x does not require gradients. + + Args: + x: (B, L, D) tensor of tokens. + mask: (B, L) boolean tensor indicating which tokens are not padding. + + Returns: + pooled: (B, D) tensor of pooled tokens. + """ + assert x.size(1) == mask.size(1) # Expected mask to have same length as tokens. + assert x.size(0) == mask.size(0) # Expected mask to have same batch size as tokens. + mask = mask[:, :, None].to(dtype=x.dtype) + mask = mask / mask.sum(dim=1, keepdim=True).clamp(min=1) + pooled = (x * mask).sum(dim=1, keepdim=keepdim) + return pooled + + +class AttentionPool(nn.Module): + def __init__( + self, + embed_dim: int, + num_heads: int, + output_dim: int = None, + device: Optional[torch.device] = None, + dtype=None, + operations=None, + ): + """ + Args: + spatial_dim (int): Number of tokens in sequence length. + embed_dim (int): Dimensionality of input tokens. + num_heads (int): Number of attention heads. + output_dim (int): Dimensionality of output tokens. Defaults to embed_dim. + """ + super().__init__() + self.num_heads = num_heads + self.to_kv = operations.Linear(embed_dim, 2 * embed_dim, device=device, dtype=dtype) + self.to_q = operations.Linear(embed_dim, embed_dim, device=device, dtype=dtype) + self.to_out = operations.Linear(embed_dim, output_dim or embed_dim, device=device, dtype=dtype) + + def forward(self, x, mask): + """ + Args: + x (torch.Tensor): (B, L, D) tensor of input tokens. + mask (torch.Tensor): (B, L) boolean tensor indicating which tokens are not padding. + + NOTE: We assume x does not require gradients. + + Returns: + x (torch.Tensor): (B, D) tensor of pooled tokens. + """ + D = x.size(2) + + # Construct attention mask, shape: (B, 1, num_queries=1, num_keys=1+L). + attn_mask = mask[:, None, None, :].bool() # (B, 1, 1, L). + attn_mask = F.pad(attn_mask, (1, 0), value=True) # (B, 1, 1, 1+L). + + # Average non-padding token features. These will be used as the query. + x_pool = pool_tokens(x, mask, keepdim=True) # (B, 1, D) + + # Concat pooled features to input sequence. + x = torch.cat([x_pool, x], dim=1) # (B, L+1, D) + + # Compute queries, keys, values. Only the mean token is used to create a query. + kv = self.to_kv(x) # (B, L+1, 2 * D) + q = self.to_q(x[:, 0]) # (B, D) + + # Extract heads. + head_dim = D // self.num_heads + kv = kv.unflatten(2, (2, self.num_heads, head_dim)) # (B, 1+L, 2, H, head_dim) + kv = kv.transpose(1, 3) # (B, H, 2, 1+L, head_dim) + k, v = kv.unbind(2) # (B, H, 1+L, head_dim) + q = q.unflatten(1, (self.num_heads, head_dim)) # (B, H, head_dim) + q = q.unsqueeze(2) # (B, H, 1, head_dim) + + # Compute attention. + x = F.scaled_dot_product_attention( + q, k, v, attn_mask=attn_mask, dropout_p=0.0 + ) # (B, H, 1, head_dim) + + # Concatenate heads and run output. + x = x.squeeze(2).flatten(1, 2) # (B, D = H * head_dim) + x = self.to_out(x) + return x diff --git a/comfy/ldm/genmo/vae/model.py b/comfy/ldm/genmo/vae/model.py new file mode 100644 index 00000000..e44c08a4 --- /dev/null +++ b/comfy/ldm/genmo/vae/model.py @@ -0,0 +1,480 @@ +#original code from https://github.com/genmoai/models under apache 2.0 license +#adapted to ComfyUI + +from typing import Callable, List, Optional, Tuple, Union + +import torch +import torch.nn as nn +import torch.nn.functional as F +from einops import rearrange + +import comfy.ops +ops = comfy.ops.disable_weight_init + +# import mochi_preview.dit.joint_model.context_parallel as cp +# from mochi_preview.vae.cp_conv import cp_pass_frames, gather_all_frames + + +def cast_tuple(t, length=1): + return t if isinstance(t, tuple) else ((t,) * length) + + +class GroupNormSpatial(ops.GroupNorm): + """ + GroupNorm applied per-frame. + """ + + def forward(self, x: torch.Tensor, *, chunk_size: int = 8): + B, C, T, H, W = x.shape + x = rearrange(x, "B C T H W -> (B T) C H W") + # Run group norm in chunks. + output = torch.empty_like(x) + for b in range(0, B * T, chunk_size): + output[b : b + chunk_size] = super().forward(x[b : b + chunk_size]) + return rearrange(output, "(B T) C H W -> B C T H W", B=B, T=T) + +class PConv3d(ops.Conv3d): + def __init__( + self, + in_channels, + out_channels, + kernel_size: Union[int, Tuple[int, int, int]], + stride: Union[int, Tuple[int, int, int]], + causal: bool = True, + context_parallel: bool = True, + **kwargs, + ): + self.causal = causal + self.context_parallel = context_parallel + kernel_size = cast_tuple(kernel_size, 3) + stride = cast_tuple(stride, 3) + height_pad = (kernel_size[1] - 1) // 2 + width_pad = (kernel_size[2] - 1) // 2 + + super().__init__( + in_channels=in_channels, + out_channels=out_channels, + kernel_size=kernel_size, + stride=stride, + dilation=(1, 1, 1), + padding=(0, height_pad, width_pad), + **kwargs, + ) + + def forward(self, x: torch.Tensor): + # Compute padding amounts. + context_size = self.kernel_size[0] - 1 + if self.causal: + pad_front = context_size + pad_back = 0 + else: + pad_front = context_size // 2 + pad_back = context_size - pad_front + + # Apply padding. + assert self.padding_mode == "replicate" # DEBUG + mode = "constant" if self.padding_mode == "zeros" else self.padding_mode + x = F.pad(x, (0, 0, 0, 0, pad_front, pad_back), mode=mode) + return super().forward(x) + + +class Conv1x1(ops.Linear): + """*1x1 Conv implemented with a linear layer.""" + + def __init__(self, in_features: int, out_features: int, *args, **kwargs): + super().__init__(in_features, out_features, *args, **kwargs) + + def forward(self, x: torch.Tensor): + """Forward pass. + + Args: + x: Input tensor. Shape: [B, C, *] or [B, *, C]. + + Returns: + x: Output tensor. Shape: [B, C', *] or [B, *, C']. + """ + x = x.movedim(1, -1) + x = super().forward(x) + x = x.movedim(-1, 1) + return x + + +class DepthToSpaceTime(nn.Module): + def __init__( + self, + temporal_expansion: int, + spatial_expansion: int, + ): + super().__init__() + self.temporal_expansion = temporal_expansion + self.spatial_expansion = spatial_expansion + + # When printed, this module should show the temporal and spatial expansion factors. + def extra_repr(self): + return f"texp={self.temporal_expansion}, sexp={self.spatial_expansion}" + + def forward(self, x: torch.Tensor): + """Forward pass. + + Args: + x: Input tensor. Shape: [B, C, T, H, W]. + + Returns: + x: Rearranged tensor. Shape: [B, C/(st*s*s), T*st, H*s, W*s]. + """ + x = rearrange( + x, + "B (C st sh sw) T H W -> B C (T st) (H sh) (W sw)", + st=self.temporal_expansion, + sh=self.spatial_expansion, + sw=self.spatial_expansion, + ) + + # cp_rank, _ = cp.get_cp_rank_size() + if self.temporal_expansion > 1: # and cp_rank == 0: + # Drop the first self.temporal_expansion - 1 frames. + # This is because we always want the 3x3x3 conv filter to only apply + # to the first frame, and the first frame doesn't need to be repeated. + assert all(x.shape) + x = x[:, :, self.temporal_expansion - 1 :] + assert all(x.shape) + + return x + + +def norm_fn( + in_channels: int, + affine: bool = True, +): + return GroupNormSpatial(affine=affine, num_groups=32, num_channels=in_channels) + + +class ResBlock(nn.Module): + """Residual block that preserves the spatial dimensions.""" + + def __init__( + self, + channels: int, + *, + affine: bool = True, + attn_block: Optional[nn.Module] = None, + padding_mode: str = "replicate", + causal: bool = True, + ): + super().__init__() + self.channels = channels + + assert causal + self.stack = nn.Sequential( + norm_fn(channels, affine=affine), + nn.SiLU(inplace=True), + PConv3d( + in_channels=channels, + out_channels=channels, + kernel_size=(3, 3, 3), + stride=(1, 1, 1), + padding_mode=padding_mode, + bias=True, + # causal=causal, + ), + norm_fn(channels, affine=affine), + nn.SiLU(inplace=True), + PConv3d( + in_channels=channels, + out_channels=channels, + kernel_size=(3, 3, 3), + stride=(1, 1, 1), + padding_mode=padding_mode, + bias=True, + # causal=causal, + ), + ) + + self.attn_block = attn_block if attn_block else nn.Identity() + + def forward(self, x: torch.Tensor): + """Forward pass. + + Args: + x: Input tensor. Shape: [B, C, T, H, W]. + """ + residual = x + x = self.stack(x) + x = x + residual + del residual + + return self.attn_block(x) + + +class CausalUpsampleBlock(nn.Module): + def __init__( + self, + in_channels: int, + out_channels: int, + num_res_blocks: int, + *, + temporal_expansion: int = 2, + spatial_expansion: int = 2, + **block_kwargs, + ): + super().__init__() + + blocks = [] + for _ in range(num_res_blocks): + blocks.append(block_fn(in_channels, **block_kwargs)) + self.blocks = nn.Sequential(*blocks) + + self.temporal_expansion = temporal_expansion + self.spatial_expansion = spatial_expansion + + # Change channels in the final convolution layer. + self.proj = Conv1x1( + in_channels, + out_channels * temporal_expansion * (spatial_expansion**2), + ) + + self.d2st = DepthToSpaceTime( + temporal_expansion=temporal_expansion, spatial_expansion=spatial_expansion + ) + + def forward(self, x): + x = self.blocks(x) + x = self.proj(x) + x = self.d2st(x) + return x + + +def block_fn(channels, *, has_attention: bool = False, **block_kwargs): + assert has_attention is False #NOTE: if this is ever true add back the attention code. + + attn_block = None #AttentionBlock(channels) if has_attention else None + + return ResBlock( + channels, affine=True, attn_block=attn_block, **block_kwargs + ) + + +class DownsampleBlock(nn.Module): + def __init__( + self, + in_channels: int, + out_channels: int, + num_res_blocks, + *, + temporal_reduction=2, + spatial_reduction=2, + **block_kwargs, + ): + """ + Downsample block for the VAE encoder. + + Args: + in_channels: Number of input channels. + out_channels: Number of output channels. + num_res_blocks: Number of residual blocks. + temporal_reduction: Temporal reduction factor. + spatial_reduction: Spatial reduction factor. + """ + super().__init__() + layers = [] + + # Change the channel count in the strided convolution. + # This lets the ResBlock have uniform channel count, + # as in ConvNeXt. + assert in_channels != out_channels + layers.append( + PConv3d( + in_channels=in_channels, + out_channels=out_channels, + kernel_size=(temporal_reduction, spatial_reduction, spatial_reduction), + stride=(temporal_reduction, spatial_reduction, spatial_reduction), + padding_mode="replicate", + bias=True, + ) + ) + + for _ in range(num_res_blocks): + layers.append(block_fn(out_channels, **block_kwargs)) + + self.layers = nn.Sequential(*layers) + + def forward(self, x): + return self.layers(x) + + +def add_fourier_features(inputs: torch.Tensor, start=6, stop=8, step=1): + num_freqs = (stop - start) // step + assert inputs.ndim == 5 + C = inputs.size(1) + + # Create Base 2 Fourier features. + freqs = torch.arange(start, stop, step, dtype=inputs.dtype, device=inputs.device) + assert num_freqs == len(freqs) + w = torch.pow(2.0, freqs) * (2 * torch.pi) # [num_freqs] + C = inputs.shape[1] + w = w.repeat(C)[None, :, None, None, None] # [1, C * num_freqs, 1, 1, 1] + + # Interleaved repeat of input channels to match w. + h = inputs.repeat_interleave(num_freqs, dim=1) # [B, C * num_freqs, T, H, W] + # Scale channels by frequency. + h = w * h + + return torch.cat( + [ + inputs, + torch.sin(h), + torch.cos(h), + ], + dim=1, + ) + + +class FourierFeatures(nn.Module): + def __init__(self, start: int = 6, stop: int = 8, step: int = 1): + super().__init__() + self.start = start + self.stop = stop + self.step = step + + def forward(self, inputs): + """Add Fourier features to inputs. + + Args: + inputs: Input tensor. Shape: [B, C, T, H, W] + + Returns: + h: Output tensor. Shape: [B, (1 + 2 * num_freqs) * C, T, H, W] + """ + return add_fourier_features(inputs, self.start, self.stop, self.step) + + +class Decoder(nn.Module): + def __init__( + self, + *, + out_channels: int = 3, + latent_dim: int, + base_channels: int, + channel_multipliers: List[int], + num_res_blocks: List[int], + temporal_expansions: Optional[List[int]] = None, + spatial_expansions: Optional[List[int]] = None, + has_attention: List[bool], + output_norm: bool = True, + nonlinearity: str = "silu", + output_nonlinearity: str = "silu", + causal: bool = True, + **block_kwargs, + ): + super().__init__() + self.input_channels = latent_dim + self.base_channels = base_channels + self.channel_multipliers = channel_multipliers + self.num_res_blocks = num_res_blocks + self.output_nonlinearity = output_nonlinearity + assert nonlinearity == "silu" + assert causal + + ch = [mult * base_channels for mult in channel_multipliers] + self.num_up_blocks = len(ch) - 1 + assert len(num_res_blocks) == self.num_up_blocks + 2 + + blocks = [] + + first_block = [ + nn.Conv3d(latent_dim, ch[-1], kernel_size=(1, 1, 1)) + ] # Input layer. + # First set of blocks preserve channel count. + for _ in range(num_res_blocks[-1]): + first_block.append( + block_fn( + ch[-1], + has_attention=has_attention[-1], + causal=causal, + **block_kwargs, + ) + ) + blocks.append(nn.Sequential(*first_block)) + + assert len(temporal_expansions) == len(spatial_expansions) == self.num_up_blocks + assert len(num_res_blocks) == len(has_attention) == self.num_up_blocks + 2 + + upsample_block_fn = CausalUpsampleBlock + + for i in range(self.num_up_blocks): + block = upsample_block_fn( + ch[-i - 1], + ch[-i - 2], + num_res_blocks=num_res_blocks[-i - 2], + has_attention=has_attention[-i - 2], + temporal_expansion=temporal_expansions[-i - 1], + spatial_expansion=spatial_expansions[-i - 1], + causal=causal, + **block_kwargs, + ) + blocks.append(block) + + assert not output_norm + + # Last block. Preserve channel count. + last_block = [] + for _ in range(num_res_blocks[0]): + last_block.append( + block_fn( + ch[0], has_attention=has_attention[0], causal=causal, **block_kwargs + ) + ) + blocks.append(nn.Sequential(*last_block)) + + self.blocks = nn.ModuleList(blocks) + self.output_proj = Conv1x1(ch[0], out_channels) + + def forward(self, x): + """Forward pass. + + Args: + x: Latent tensor. Shape: [B, input_channels, t, h, w]. Scaled [-1, 1]. + + Returns: + x: Reconstructed video tensor. Shape: [B, C, T, H, W]. Scaled to [-1, 1]. + T + 1 = (t - 1) * 4. + H = h * 16, W = w * 16. + """ + for block in self.blocks: + x = block(x) + + if self.output_nonlinearity == "silu": + x = F.silu(x, inplace=not self.training) + else: + assert ( + not self.output_nonlinearity + ) # StyleGAN3 omits the to-RGB nonlinearity. + + return self.output_proj(x).contiguous() + + +class VideoVAE(nn.Module): + def __init__(self): + super().__init__() + self.encoder = None #TODO once the model releases + self.decoder = Decoder( + out_channels=3, + base_channels=128, + channel_multipliers=[1, 2, 4, 6], + temporal_expansions=[1, 2, 3], + spatial_expansions=[2, 2, 2], + num_res_blocks=[3, 3, 4, 6, 3], + latent_dim=12, + has_attention=[False, False, False, False, False], + padding_mode="replicate", + output_norm=False, + nonlinearity="silu", + output_nonlinearity="silu", + causal=True, + ) + + def encode(self, x): + return self.encoder(x) + + def decode(self, x): + return self.decoder(x) diff --git a/comfy/ldm/modules/diffusionmodules/mmdit.py b/comfy/ldm/modules/diffusionmodules/mmdit.py index 759788a9..6f8f506c 100644 --- a/comfy/ldm/modules/diffusionmodules/mmdit.py +++ b/comfy/ldm/modules/diffusionmodules/mmdit.py @@ -1,11 +1,11 @@ import logging import math -from typing import Dict, Optional +from typing import Dict, Optional, List import numpy as np import torch import torch.nn as nn -from .. import attention +from ..attention import optimized_attention from einops import rearrange, repeat from .util import timestep_embedding import comfy.ops @@ -97,7 +97,7 @@ class PatchEmbed(nn.Module): self.norm = norm_layer(embed_dim) if norm_layer else nn.Identity() def forward(self, x): - B, C, H, W = x.shape + # B, C, H, W = x.shape # if self.img_size is not None: # if self.strict_img_size: # _assert(H == self.img_size[0], f"Input height ({H}) doesn't match model ({self.img_size[0]}).") @@ -266,8 +266,6 @@ def split_qkv(qkv, head_dim): qkv = qkv.reshape(qkv.shape[0], qkv.shape[1], 3, -1, head_dim).movedim(2, 0) return qkv[0], qkv[1], qkv[2] -def optimized_attention(qkv, num_heads): - return attention.optimized_attention(qkv[0], qkv[1], qkv[2], num_heads) class SelfAttention(nn.Module): ATTENTION_MODES = ("xformers", "torch", "torch-hb", "math", "debug") @@ -326,9 +324,9 @@ class SelfAttention(nn.Module): return x def forward(self, x: torch.Tensor) -> torch.Tensor: - qkv = self.pre_attention(x) + q, k, v = self.pre_attention(x) x = optimized_attention( - qkv, num_heads=self.num_heads + q, k, v, heads=self.num_heads ) x = self.post_attention(x) return x @@ -417,6 +415,7 @@ class DismantledBlock(nn.Module): scale_mod_only: bool = False, swiglu: bool = False, qk_norm: Optional[str] = None, + x_block_self_attn: bool = False, dtype=None, device=None, operations=None, @@ -440,6 +439,24 @@ class DismantledBlock(nn.Module): device=device, operations=operations ) + if x_block_self_attn: + assert not pre_only + assert not scale_mod_only + self.x_block_self_attn = True + self.attn2 = SelfAttention( + dim=hidden_size, + num_heads=num_heads, + qkv_bias=qkv_bias, + attn_mode=attn_mode, + pre_only=False, + qk_norm=qk_norm, + rmsnorm=rmsnorm, + dtype=dtype, + device=device, + operations=operations + ) + else: + self.x_block_self_attn = False if not pre_only: if not rmsnorm: self.norm2 = operations.LayerNorm( @@ -466,7 +483,11 @@ class DismantledBlock(nn.Module): multiple_of=256, ) self.scale_mod_only = scale_mod_only - if not scale_mod_only: + if x_block_self_attn: + assert not pre_only + assert not scale_mod_only + n_mods = 9 + elif not scale_mod_only: n_mods = 6 if not pre_only else 2 else: n_mods = 4 if not pre_only else 1 @@ -527,14 +548,64 @@ class DismantledBlock(nn.Module): ) return x + def pre_attention_x(self, x: torch.Tensor, c: torch.Tensor) -> torch.Tensor: + assert self.x_block_self_attn + ( + shift_msa, + scale_msa, + gate_msa, + shift_mlp, + scale_mlp, + gate_mlp, + shift_msa2, + scale_msa2, + gate_msa2, + ) = self.adaLN_modulation(c).chunk(9, dim=1) + x_norm = self.norm1(x) + qkv = self.attn.pre_attention(modulate(x_norm, shift_msa, scale_msa)) + qkv2 = self.attn2.pre_attention(modulate(x_norm, shift_msa2, scale_msa2)) + return qkv, qkv2, ( + x, + gate_msa, + shift_mlp, + scale_mlp, + gate_mlp, + gate_msa2, + ) + + def post_attention_x(self, attn, attn2, x, gate_msa, shift_mlp, scale_mlp, gate_mlp, gate_msa2): + assert not self.pre_only + attn1 = self.attn.post_attention(attn) + attn2 = self.attn2.post_attention(attn2) + out1 = gate_msa.unsqueeze(1) * attn1 + out2 = gate_msa2.unsqueeze(1) * attn2 + x = x + out1 + x = x + out2 + x = x + gate_mlp.unsqueeze(1) * self.mlp( + modulate(self.norm2(x), shift_mlp, scale_mlp) + ) + return x + def forward(self, x: torch.Tensor, c: torch.Tensor) -> torch.Tensor: assert not self.pre_only - qkv, intermediates = self.pre_attention(x, c) - attn = optimized_attention( - qkv, - num_heads=self.attn.num_heads, - ) - return self.post_attention(attn, *intermediates) + if self.x_block_self_attn: + qkv, qkv2, intermediates = self.pre_attention_x(x, c) + attn, _ = optimized_attention( + qkv[0], qkv[1], qkv[2], + num_heads=self.attn.num_heads, + ) + attn2, _ = optimized_attention( + qkv2[0], qkv2[1], qkv2[2], + num_heads=self.attn2.num_heads, + ) + return self.post_attention_x(attn, attn2, *intermediates) + else: + qkv, intermediates = self.pre_attention(x, c) + attn = optimized_attention( + qkv[0], qkv[1], qkv[2], + heads=self.attn.num_heads, + ) + return self.post_attention(attn, *intermediates) def block_mixing(*args, use_checkpoint=True, **kwargs): @@ -549,7 +620,10 @@ def block_mixing(*args, use_checkpoint=True, **kwargs): def _block_mixing(context, x, context_block, x_block, c): context_qkv, context_intermediates = context_block.pre_attention(context, c) - x_qkv, x_intermediates = x_block.pre_attention(x, c) + if x_block.x_block_self_attn: + x_qkv, x_qkv2, x_intermediates = x_block.pre_attention_x(x, c) + else: + x_qkv, x_intermediates = x_block.pre_attention(x, c) o = [] for t in range(3): @@ -557,8 +631,8 @@ def _block_mixing(context, x, context_block, x_block, c): qkv = tuple(o) attn = optimized_attention( - qkv, - num_heads=x_block.attn.num_heads, + qkv[0], qkv[1], qkv[2], + heads=x_block.attn.num_heads, ) context_attn, x_attn = ( attn[:, : context_qkv[0].shape[1]], @@ -570,7 +644,14 @@ def _block_mixing(context, x, context_block, x_block, c): else: context = None - x = x_block.post_attention(x_attn, *x_intermediates) + if x_block.x_block_self_attn: + attn2 = optimized_attention( + x_qkv2[0], x_qkv2[1], x_qkv2[2], + heads=x_block.attn2.num_heads, + ) + x = x_block.post_attention_x(x_attn, attn2, *x_intermediates) + else: + x = x_block.post_attention(x_attn, *x_intermediates) return context, x @@ -585,8 +666,13 @@ class JointBlock(nn.Module): super().__init__() pre_only = kwargs.pop("pre_only") qk_norm = kwargs.pop("qk_norm", None) + x_block_self_attn = kwargs.pop("x_block_self_attn", False) self.context_block = DismantledBlock(*args, pre_only=pre_only, qk_norm=qk_norm, **kwargs) - self.x_block = DismantledBlock(*args, pre_only=False, qk_norm=qk_norm, **kwargs) + self.x_block = DismantledBlock(*args, + pre_only=False, + qk_norm=qk_norm, + x_block_self_attn=x_block_self_attn, + **kwargs) def forward(self, *args, **kwargs): return block_mixing( @@ -642,7 +728,7 @@ class SelfAttentionContext(nn.Module): def forward(self, x): qkv = self.qkv(x) q, k, v = split_qkv(qkv, self.dim_head) - x = optimized_attention((q.reshape(q.shape[0], q.shape[1], -1), k, v), self.heads) + x = optimized_attention(q.reshape(q.shape[0], q.shape[1], -1), k, v, heads=self.heads) return self.proj(x) class ContextProcessorBlock(nn.Module): @@ -701,9 +787,12 @@ class MMDiT(nn.Module): qk_norm: Optional[str] = None, qkv_bias: bool = True, context_processor_layers = None, + x_block_self_attn: bool = False, + x_block_self_attn_layers: Optional[List[int]] = [], context_size = 4096, num_blocks = None, final_layer = True, + skip_blocks = False, dtype = None, #TODO device = None, operations = None, @@ -718,6 +807,7 @@ class MMDiT(nn.Module): self.pos_embed_scaling_factor = pos_embed_scaling_factor self.pos_embed_offset = pos_embed_offset self.pos_embed_max_size = pos_embed_max_size + self.x_block_self_attn_layers = x_block_self_attn_layers # hidden_size = default(hidden_size, 64 * depth) # num_heads = default(num_heads, hidden_size // 64) @@ -775,26 +865,28 @@ class MMDiT(nn.Module): self.pos_embed = None self.use_checkpoint = use_checkpoint - self.joint_blocks = nn.ModuleList( - [ - JointBlock( - self.hidden_size, - num_heads, - mlp_ratio=mlp_ratio, - qkv_bias=qkv_bias, - attn_mode=attn_mode, - pre_only=(i == num_blocks - 1) and final_layer, - rmsnorm=rmsnorm, - scale_mod_only=scale_mod_only, - swiglu=swiglu, - qk_norm=qk_norm, - dtype=dtype, - device=device, - operations=operations - ) - for i in range(num_blocks) - ] - ) + if not skip_blocks: + self.joint_blocks = nn.ModuleList( + [ + JointBlock( + self.hidden_size, + num_heads, + mlp_ratio=mlp_ratio, + qkv_bias=qkv_bias, + attn_mode=attn_mode, + pre_only=(i == num_blocks - 1) and final_layer, + rmsnorm=rmsnorm, + scale_mod_only=scale_mod_only, + swiglu=swiglu, + qk_norm=qk_norm, + x_block_self_attn=(i in self.x_block_self_attn_layers) or x_block_self_attn, + dtype=dtype, + device=device, + operations=operations, + ) + for i in range(num_blocks) + ] + ) if final_layer: self.final_layer = FinalLayer(self.hidden_size, patch_size, self.out_channels, dtype=dtype, device=device, operations=operations) @@ -857,7 +949,9 @@ class MMDiT(nn.Module): c_mod: torch.Tensor, context: Optional[torch.Tensor] = None, control = None, + transformer_options = {}, ) -> torch.Tensor: + patches_replace = transformer_options.get("patches_replace", {}) if self.register_length > 0: context = torch.cat( ( @@ -869,14 +963,25 @@ class MMDiT(nn.Module): # context is B, L', D # x is B, L, D + blocks_replace = patches_replace.get("dit", {}) blocks = len(self.joint_blocks) for i in range(blocks): - context, x = self.joint_blocks[i]( - context, - x, - c=c_mod, - use_checkpoint=self.use_checkpoint, - ) + if ("double_block", i) in blocks_replace: + def block_wrap(args): + out = {} + out["txt"], out["img"] = self.joint_blocks[i](args["txt"], args["img"], c=args["vec"]) + return out + + out = blocks_replace[("double_block", i)]({"img": x, "txt": context, "vec": c_mod}, {"original_block": block_wrap}) + context = out["txt"] + x = out["img"] + else: + context, x = self.joint_blocks[i]( + context, + x, + c=c_mod, + use_checkpoint=self.use_checkpoint, + ) if control is not None: control_o = control.get("output") if i < len(control_o): @@ -894,6 +999,7 @@ class MMDiT(nn.Module): y: Optional[torch.Tensor] = None, context: Optional[torch.Tensor] = None, control = None, + transformer_options = {}, ) -> torch.Tensor: """ Forward pass of DiT. @@ -915,7 +1021,7 @@ class MMDiT(nn.Module): if context is not None: context = self.context_embedder(context) - x = self.forward_core_with_concat(x, c, context, control) + x = self.forward_core_with_concat(x, c, context, control, transformer_options) x = self.unpatchify(x, hw=hw) # (N, out_channels, H, W) return x[:,:,:hw[-2],:hw[-1]] @@ -929,7 +1035,8 @@ class OpenAISignatureMMDITWrapper(MMDiT): context: Optional[torch.Tensor] = None, y: Optional[torch.Tensor] = None, control = None, + transformer_options = {}, **kwargs, ) -> torch.Tensor: - return super().forward(x, timesteps, context=context, y=y, control=control) + return super().forward(x, timesteps, context=context, y=y, control=control, transformer_options=transformer_options) diff --git a/comfy/lora.py b/comfy/lora.py index 80057cdd..b745ca4d 100644 --- a/comfy/lora.py +++ b/comfy/lora.py @@ -317,6 +317,10 @@ def model_lora_keys_unet(model, key_map={}): key_lora = "lora_transformer_{}".format(k[:-len(".weight")].replace(".", "_")) #OneTrainer lora key_map[key_lora] = to + key_lora = "lycoris_{}".format(k[:-len(".weight")].replace(".", "_")) #simpletuner lycoris format + key_map[key_lora] = to + + if isinstance(model, comfy.model_base.AuraFlow): #Diffusers lora AuraFlow diffusers_keys = comfy.utils.auraflow_to_diffusers(model.model_config.unet_config, output_prefix="diffusion_model.") for k in diffusers_keys: @@ -415,7 +419,7 @@ def calculate_weight(patches, weight, key, intermediate_dtype=torch.float32): weight *= strength_model if isinstance(v, list): - v = (calculate_weight(v[1:], comfy.model_management.cast_to_device(v[0], weight.device, intermediate_dtype, copy=True), key, intermediate_dtype=intermediate_dtype), ) + v = (calculate_weight(v[1:], v[0][1](comfy.model_management.cast_to_device(v[0][0], weight.device, intermediate_dtype, copy=True), inplace=True), key, intermediate_dtype=intermediate_dtype), ) if len(v) == 1: patch_type = "diff" diff --git a/comfy/model_base.py b/comfy/model_base.py index a98fee1d..f2833168 100644 --- a/comfy/model_base.py +++ b/comfy/model_base.py @@ -24,6 +24,7 @@ from comfy.ldm.cascade.stage_b import StageB from comfy.ldm.modules.encoders.noise_aug_modules import CLIPEmbeddingNoiseAugmentation from comfy.ldm.modules.diffusionmodules.upscaling import ImageConcatWithNoiseAugmentation from comfy.ldm.modules.diffusionmodules.mmdit import OpenAISignatureMMDITWrapper +import comfy.ldm.genmo.joint_model.asymm_models_joint import comfy.ldm.aura.mmdit import comfy.ldm.hydit.models import comfy.ldm.audio.dit @@ -96,7 +97,8 @@ class BaseModel(torch.nn.Module): if not unet_config.get("disable_unet_model_creation", False): if model_config.custom_operations is None: - operations = comfy.ops.pick_operations(unet_config.get("dtype", None), self.manual_cast_dtype, fp8_optimizations=model_config.optimizations.get("fp8", False)) + fp8 = model_config.optimizations.get("fp8", model_config.scaled_fp8 is not None) + operations = comfy.ops.pick_operations(unet_config.get("dtype", None), self.manual_cast_dtype, fp8_optimizations=fp8, scaled_fp8=model_config.scaled_fp8) else: operations = model_config.custom_operations self.diffusion_model = unet_model(**unet_config, device=device, operations=operations) @@ -244,6 +246,10 @@ class BaseModel(torch.nn.Module): extra_sds.append(self.model_config.process_clip_vision_state_dict_for_saving(clip_vision_state_dict)) unet_state_dict = self.diffusion_model.state_dict() + + if self.model_config.scaled_fp8 is not None: + unet_state_dict["scaled_fp8"] = torch.tensor([], dtype=self.model_config.scaled_fp8) + unet_state_dict = self.model_config.process_unet_state_dict_for_saving(unet_state_dict) if self.model_type == ModelType.V_PREDICTION: @@ -713,3 +719,18 @@ class Flux(BaseModel): out['c_crossattn'] = comfy.conds.CONDRegular(cross_attn) out['guidance'] = comfy.conds.CONDRegular(torch.FloatTensor([kwargs.get("guidance", 3.5)])) return out + +class GenmoMochi(BaseModel): + def __init__(self, model_config, model_type=ModelType.FLOW, device=None): + super().__init__(model_config, model_type, device=device, unet_model=comfy.ldm.genmo.joint_model.asymm_models_joint.AsymmDiTJoint) + + def extra_conds(self, **kwargs): + out = super().extra_conds(**kwargs) + attention_mask = kwargs.get("attention_mask", None) + if attention_mask is not None: + out['attention_mask'] = comfy.conds.CONDRegular(attention_mask) + out['num_tokens'] = comfy.conds.CONDConstant(max(1, torch.sum(attention_mask).item())) + cross_attn = kwargs.get("cross_attn", None) + if cross_attn is not None: + out['c_crossattn'] = comfy.conds.CONDRegular(cross_attn) + return out diff --git a/comfy/model_detection.py b/comfy/model_detection.py index 1edbcda4..8435de3e 100644 --- a/comfy/model_detection.py +++ b/comfy/model_detection.py @@ -70,6 +70,11 @@ def detect_unet_config(state_dict, key_prefix): context_processor = '{}context_processor.layers.0.attn.qkv.weight'.format(key_prefix) if context_processor in state_dict_keys: unet_config["context_processor_layers"] = count_blocks(state_dict_keys, '{}context_processor.layers.'.format(key_prefix) + '{}.') + unet_config["x_block_self_attn_layers"] = [] + for key in state_dict_keys: + if key.startswith('{}joint_blocks.'.format(key_prefix)) and key.endswith('.x_block.attn2.qkv.weight'): + layer = key[len('{}joint_blocks.'.format(key_prefix)):-len('.x_block.attn2.qkv.weight')] + unet_config["x_block_self_attn_layers"].append(int(layer)) return unet_config if '{}clf.1.weight'.format(key_prefix) in state_dict_keys: #stable cascade @@ -145,6 +150,34 @@ def detect_unet_config(state_dict, key_prefix): dit_config["guidance_embed"] = "{}guidance_in.in_layer.weight".format(key_prefix) in state_dict_keys return dit_config + if '{}t5_yproj.weight'.format(key_prefix) in state_dict_keys: #Genmo mochi preview + dit_config = {} + dit_config["image_model"] = "mochi_preview" + dit_config["depth"] = 48 + dit_config["patch_size"] = 2 + dit_config["num_heads"] = 24 + dit_config["hidden_size_x"] = 3072 + dit_config["hidden_size_y"] = 1536 + dit_config["mlp_ratio_x"] = 4.0 + dit_config["mlp_ratio_y"] = 4.0 + dit_config["learn_sigma"] = False + dit_config["in_channels"] = 12 + dit_config["qk_norm"] = True + dit_config["qkv_bias"] = False + dit_config["out_bias"] = True + dit_config["attn_drop"] = 0.0 + dit_config["patch_embed_bias"] = True + dit_config["posenc_preserve_area"] = True + dit_config["timestep_mlp_bias"] = True + dit_config["attend_to_padding"] = False + dit_config["timestep_scale"] = 1000.0 + dit_config["use_t5"] = True + dit_config["t5_feat_dim"] = 4096 + dit_config["t5_token_length"] = 256 + dit_config["rope_theta"] = 10000.0 + return dit_config + + if '{}input_blocks.0.0.weight'.format(key_prefix) not in state_dict_keys: return None @@ -286,9 +319,15 @@ def model_config_from_unet(state_dict, unet_key_prefix, use_base_if_no_match=Fal return None model_config = model_config_from_unet_config(unet_config, state_dict) if model_config is None and use_base_if_no_match: - return comfy.supported_models_base.BASE(unet_config) - else: - return model_config + model_config = comfy.supported_models_base.BASE(unet_config) + + scaled_fp8_weight = state_dict.get("{}scaled_fp8".format(unet_key_prefix), None) + if scaled_fp8_weight is not None: + model_config.scaled_fp8 = scaled_fp8_weight.dtype + if model_config.scaled_fp8 == torch.float32: + model_config.scaled_fp8 = torch.float8_e4m3fn + + return model_config def unet_prefix_from_state_dict(state_dict): candidates = ["model.diffusion_model.", #ldm/sgm models diff --git a/comfy/model_management.py b/comfy/model_management.py index 2346d4ac..855e8911 100644 --- a/comfy/model_management.py +++ b/comfy/model_management.py @@ -647,6 +647,9 @@ def unet_dtype(device=None, model_params=0, supported_dtypes=[torch.float16, tor pass if fp8_dtype is not None: + if supports_fp8_compute(device): #if fp8 compute is supported the casting is most likely not expensive + return fp8_dtype + free_model_memory = maximum_vram_for_weights(device) if model_params * 2 > free_model_memory: return fp8_dtype @@ -840,27 +843,21 @@ def force_channels_last(): #TODO return False +def cast_to(weight, dtype=None, device=None, non_blocking=False, copy=False): + if device is None or weight.device == device: + if not copy: + if dtype is None or weight.dtype == dtype: + return weight + return weight.to(dtype=dtype, copy=copy) + + r = torch.empty_like(weight, dtype=dtype, device=device) + r.copy_(weight, non_blocking=non_blocking) + return r + def cast_to_device(tensor, device, dtype, copy=False): - device_supports_cast = False - if tensor.dtype == torch.float32 or tensor.dtype == torch.float16: - device_supports_cast = True - elif tensor.dtype == torch.bfloat16: - if hasattr(device, 'type') and device.type.startswith("cuda"): - device_supports_cast = True - elif is_intel_xpu(): - device_supports_cast = True + non_blocking = device_supports_non_blocking(device) + return cast_to(tensor, dtype=dtype, device=device, non_blocking=non_blocking, copy=copy) - non_blocking = device_should_use_non_blocking(device) - - if device_supports_cast: - if copy: - if tensor.device == device: - return tensor.to(dtype, copy=copy, non_blocking=non_blocking) - return tensor.to(device, copy=copy, non_blocking=non_blocking).to(dtype, non_blocking=non_blocking) - else: - return tensor.to(device, non_blocking=non_blocking).to(dtype, non_blocking=non_blocking) - else: - return tensor.to(device, dtype, copy=copy, non_blocking=non_blocking) def xformers_enabled(): global directml_enabled diff --git a/comfy/model_patcher.py b/comfy/model_patcher.py index 2ba30633..3bba217a 100644 --- a/comfy/model_patcher.py +++ b/comfy/model_patcher.py @@ -94,6 +94,31 @@ class LowVramPatch: return comfy.float.stochastic_rounding(comfy.lora.calculate_weight(self.patches[self.key], weight.to(intermediate_dtype), self.key, intermediate_dtype=intermediate_dtype), weight.dtype, seed=string_to_seed(self.key)) return comfy.lora.calculate_weight(self.patches[self.key], weight, self.key, intermediate_dtype=intermediate_dtype) + +def get_key_weight(model, key): + set_func = None + convert_func = None + op_keys = key.rsplit('.', 1) + if len(op_keys) < 2: + weight = comfy.utils.get_attr(model, key) + else: + op = comfy.utils.get_attr(model, op_keys[0]) + try: + set_func = getattr(op, "set_{}".format(op_keys[1])) + except AttributeError: + pass + + try: + convert_func = getattr(op, "convert_{}".format(op_keys[1])) + except AttributeError: + pass + + weight = getattr(op, op_keys[1]) + if convert_func is not None: + weight = comfy.utils.get_attr(model, key) + + return weight, set_func, convert_func + class ModelPatcher: def __init__(self, model, load_device, offload_device, size=0, weight_inplace_update=False): self.size = size @@ -294,14 +319,16 @@ class ModelPatcher: if not k.startswith(filter_prefix): continue bk = self.backup.get(k, None) + weight, set_func, convert_func = get_key_weight(self.model, k) if bk is not None: weight = bk.weight - else: - weight = model_sd[k] + if convert_func is None: + convert_func = lambda a, **kwargs: a + if k in self.patches: - p[k] = [weight] + self.patches[k] + p[k] = [(weight, convert_func)] + self.patches[k] else: - p[k] = (weight,) + p[k] = [(weight, convert_func)] return p def model_state_dict(self, filter_prefix=None): @@ -317,8 +344,7 @@ class ModelPatcher: if key not in self.patches: return - weight = comfy.utils.get_attr(self.model, key) - + weight, set_func, convert_func = get_key_weight(self.model, key) inplace_update = self.weight_inplace_update or inplace_update if key not in self.backup: @@ -328,12 +354,18 @@ class ModelPatcher: temp_weight = comfy.model_management.cast_to_device(weight, device_to, torch.float32, copy=True) else: temp_weight = weight.to(torch.float32, copy=True) + if convert_func is not None: + temp_weight = convert_func(temp_weight, inplace=True) + out_weight = comfy.lora.calculate_weight(self.patches[key], temp_weight, key) - out_weight = comfy.float.stochastic_rounding(out_weight, weight.dtype, seed=string_to_seed(key)) - if inplace_update: - comfy.utils.copy_to_param(self.model, key, out_weight) + if set_func is None: + out_weight = comfy.float.stochastic_rounding(out_weight, weight.dtype, seed=string_to_seed(key)) + if inplace_update: + comfy.utils.copy_to_param(self.model, key, out_weight) + else: + comfy.utils.set_attr_param(self.model, key, out_weight) else: - comfy.utils.set_attr_param(self.model, key, out_weight) + set_func(out_weight, inplace_update=inplace_update, seed=string_to_seed(key)) def load(self, device_to=None, lowvram_model_memory=0, force_patch_weights=False, full_load=False): mem_counter = 0 diff --git a/comfy/ops.py b/comfy/ops.py index c90e25ea..3c5ba012 100644 --- a/comfy/ops.py +++ b/comfy/ops.py @@ -19,20 +19,12 @@ import torch import comfy.model_management from comfy.cli_args import args +import comfy.float -def cast_to(weight, dtype=None, device=None, non_blocking=False, copy=False): - if device is None or weight.device == device: - if not copy: - if dtype is None or weight.dtype == dtype: - return weight - return weight.to(dtype=dtype, copy=copy) - - r = torch.empty_like(weight, dtype=dtype, device=device) - r.copy_(weight, non_blocking=non_blocking) - return r +cast_to = comfy.model_management.cast_to #TODO: remove once no more references def cast_to_input(weight, input, non_blocking=False, copy=True): - return cast_to(weight, input.dtype, input.device, non_blocking=non_blocking, copy=copy) + return comfy.model_management.cast_to(weight, input.dtype, input.device, non_blocking=non_blocking, copy=copy) def cast_bias_weight(s, input=None, dtype=None, device=None, bias_dtype=None): if input is not None: @@ -47,12 +39,12 @@ def cast_bias_weight(s, input=None, dtype=None, device=None, bias_dtype=None): non_blocking = comfy.model_management.device_supports_non_blocking(device) if s.bias is not None: has_function = s.bias_function is not None - bias = cast_to(s.bias, bias_dtype, device, non_blocking=non_blocking, copy=has_function) + bias = comfy.model_management.cast_to(s.bias, bias_dtype, device, non_blocking=non_blocking, copy=has_function) if has_function: bias = s.bias_function(bias) has_function = s.weight_function is not None - weight = cast_to(s.weight, dtype, device, non_blocking=non_blocking, copy=has_function) + weight = comfy.model_management.cast_to(s.weight, dtype, device, non_blocking=non_blocking, copy=has_function) if has_function: weight = s.weight_function(weight) return weight, bias @@ -258,19 +250,29 @@ def fp8_linear(self, input): if dtype not in [torch.float8_e4m3fn]: return None + tensor_2d = False + if len(input.shape) == 2: + tensor_2d = True + input = input.unsqueeze(1) + + if len(input.shape) == 3: - inn = input.reshape(-1, input.shape[2]).to(dtype) w, bias = cast_bias_weight(self, input, dtype=dtype, bias_dtype=input.dtype) w = w.t() scale_weight = self.scale_weight scale_input = self.scale_input if scale_weight is None: - scale_weight = torch.ones((1), device=input.device, dtype=torch.float32) - if scale_input is None: - scale_input = scale_weight + scale_weight = torch.ones((), device=input.device, dtype=torch.float32) + else: + scale_weight = scale_weight.to(input.device) + if scale_input is None: - scale_input = torch.ones((1), device=input.device, dtype=torch.float32) + scale_input = torch.ones((), device=input.device, dtype=torch.float32) + inn = input.reshape(-1, input.shape[2]).to(dtype) + else: + scale_input = scale_input.to(input.device) + inn = (input * (1.0 / scale_input).to(input.dtype)).reshape(-1, input.shape[2]).to(dtype) if bias is not None: o = torch._scaled_mm(inn, w, out_dtype=input.dtype, bias=bias, scale_a=scale_input, scale_b=scale_weight) @@ -280,7 +282,11 @@ def fp8_linear(self, input): if isinstance(o, tuple): o = o[0] + if tensor_2d: + return o.reshape(input.shape[0], -1) + return o.reshape((-1, input.shape[1], self.weight.shape[0])) + return None class fp8_ops(manual_cast): @@ -298,15 +304,63 @@ class fp8_ops(manual_cast): weight, bias = cast_bias_weight(self, input) return torch.nn.functional.linear(input, weight, bias) +def scaled_fp8_ops(fp8_matrix_mult=False, scale_input=False, override_dtype=None): + class scaled_fp8_op(manual_cast): + class Linear(manual_cast.Linear): + def __init__(self, *args, **kwargs): + if override_dtype is not None: + kwargs['dtype'] = override_dtype + super().__init__(*args, **kwargs) -def pick_operations(weight_dtype, compute_dtype, load_device=None, disable_fast_fp8=False, fp8_optimizations=False): - if comfy.model_management.supports_fp8_compute(load_device): - if (fp8_optimizations or args.fast) and not disable_fast_fp8: - return fp8_ops + def reset_parameters(self): + if not hasattr(self, 'scale_weight'): + self.scale_weight = torch.nn.parameter.Parameter(data=torch.ones((), device=self.weight.device, dtype=torch.float32), requires_grad=False) + + if not scale_input: + self.scale_input = None + + if not hasattr(self, 'scale_input'): + self.scale_input = torch.nn.parameter.Parameter(data=torch.ones((), device=self.weight.device, dtype=torch.float32), requires_grad=False) + return None + + def forward_comfy_cast_weights(self, input): + if fp8_matrix_mult: + out = fp8_linear(self, input) + if out is not None: + return out + + weight, bias = cast_bias_weight(self, input) + + if weight.numel() < input.numel(): #TODO: optimize + return torch.nn.functional.linear(input, weight * self.scale_weight.to(device=weight.device, dtype=weight.dtype), bias) + else: + return torch.nn.functional.linear(input * self.scale_weight.to(device=weight.device, dtype=weight.dtype), weight, bias) + + def convert_weight(self, weight, inplace=False, **kwargs): + if inplace: + weight *= self.scale_weight.to(device=weight.device, dtype=weight.dtype) + return weight + else: + return weight * self.scale_weight.to(device=weight.device, dtype=weight.dtype) + + def set_weight(self, weight, inplace_update=False, seed=None, **kwargs): + weight = comfy.float.stochastic_rounding(weight / self.scale_weight.to(device=weight.device, dtype=weight.dtype), self.weight.dtype, seed=seed) + if inplace_update: + self.weight.data.copy_(weight) + else: + self.weight = torch.nn.Parameter(weight, requires_grad=False) + + return scaled_fp8_op + +def pick_operations(weight_dtype, compute_dtype, load_device=None, disable_fast_fp8=False, fp8_optimizations=False, scaled_fp8=None): + fp8_compute = comfy.model_management.supports_fp8_compute(load_device) + if scaled_fp8 is not None: + return scaled_fp8_ops(fp8_matrix_mult=fp8_compute, scale_input=True, override_dtype=scaled_fp8) + + if fp8_compute and (fp8_optimizations or args.fast) and not disable_fast_fp8: + return fp8_ops if compute_dtype is None or weight_dtype == compute_dtype: return disable_weight_init - if args.fast and not disable_fast_fp8: - if comfy.model_management.supports_fp8_compute(load_device): - return fp8_ops + return manual_cast diff --git a/comfy/samplers.py b/comfy/samplers.py index 4a975af7..eb520862 100644 --- a/comfy/samplers.py +++ b/comfy/samplers.py @@ -358,11 +358,35 @@ def beta_scheduler(model_sampling, steps, alpha=0.6, beta=0.6): ts = numpy.rint(scipy.stats.beta.ppf(ts, alpha, beta) * total_timesteps) sigs = [] + last_t = -1 for t in ts: - sigs += [float(model_sampling.sigmas[int(t)])] + if t != last_t: + sigs += [float(model_sampling.sigmas[int(t)])] + last_t = t sigs += [0.0] return torch.FloatTensor(sigs) +# from: https://github.com/genmoai/models/blob/main/src/mochi_preview/infer.py#L41 +def linear_quadratic_schedule(model_sampling, steps, threshold_noise=0.025, linear_steps=None): + if steps == 1: + sigma_schedule = [1.0, 0.0] + else: + if linear_steps is None: + linear_steps = steps // 2 + linear_sigma_schedule = [i * threshold_noise / linear_steps for i in range(linear_steps)] + threshold_noise_step_diff = linear_steps - threshold_noise * steps + quadratic_steps = steps - linear_steps + quadratic_coef = threshold_noise_step_diff / (linear_steps * quadratic_steps ** 2) + linear_coef = threshold_noise / linear_steps - 2 * threshold_noise_step_diff / (quadratic_steps ** 2) + const = quadratic_coef * (linear_steps ** 2) + quadratic_sigma_schedule = [ + quadratic_coef * (i ** 2) + linear_coef * i + const + for i in range(linear_steps, steps) + ] + sigma_schedule = linear_sigma_schedule + quadratic_sigma_schedule + [1.0] + sigma_schedule = [1.0 - x for x in sigma_schedule] + return torch.FloatTensor(sigma_schedule) * model_sampling.sigma_max.cpu() + def get_mask_aabb(masks): if masks.numel() == 0: return torch.zeros((0, 4), device=masks.device, dtype=torch.int) @@ -729,7 +753,7 @@ def sample(model, noise, positive, negative, cfg, device, sampler, sigmas, model return cfg_guider.sample(noise, latent_image, sampler, sigmas, denoise_mask, callback, disable_pbar, seed) -SCHEDULER_NAMES = ["normal", "karras", "exponential", "sgm_uniform", "simple", "ddim_uniform", "beta"] +SCHEDULER_NAMES = ["normal", "karras", "exponential", "sgm_uniform", "simple", "ddim_uniform", "beta", "linear_quadratic"] SAMPLER_NAMES = KSAMPLER_NAMES + ["ddim", "uni_pc", "uni_pc_bh2"] def calculate_sigmas(model_sampling, scheduler_name, steps): @@ -747,6 +771,8 @@ def calculate_sigmas(model_sampling, scheduler_name, steps): sigmas = normal_scheduler(model_sampling, steps, sgm=True) elif scheduler_name == "beta": sigmas = beta_scheduler(model_sampling, steps) + elif scheduler_name == "linear_quadratic": + sigmas = linear_quadratic_schedule(model_sampling, steps) else: logging.error("error invalid scheduler {}".format(scheduler_name)) return sigmas diff --git a/comfy/sd.py b/comfy/sd.py index 67b4ff0c..e9a3579c 100644 --- a/comfy/sd.py +++ b/comfy/sd.py @@ -7,6 +7,7 @@ from .ldm.models.autoencoder import AutoencoderKL, AutoencodingEngine from .ldm.cascade.stage_a import StageA from .ldm.cascade.stage_c_coder import StageC_coder from .ldm.audio.autoencoder import AudioOobleckVAE +import comfy.ldm.genmo.vae.model import yaml import comfy.utils @@ -25,6 +26,7 @@ import comfy.text_encoders.aura_t5 import comfy.text_encoders.hydit import comfy.text_encoders.flux import comfy.text_encoders.long_clipl +import comfy.text_encoders.genmo import comfy.model_patcher import comfy.lora @@ -241,6 +243,13 @@ class VAE: self.process_output = lambda audio: audio self.process_input = lambda audio: audio self.working_dtypes = [torch.float16, torch.bfloat16, torch.float32] + elif "blocks.2.blocks.3.stack.5.weight" in sd or "decoder.blocks.2.blocks.3.stack.5.weight" in sd: #genmo mochi vae + if "blocks.2.blocks.3.stack.5.weight" in sd: + sd = comfy.utils.state_dict_prefix_replace(sd, {"": "decoder."}) + self.first_stage_model = comfy.ldm.genmo.vae.model.VideoVAE() + self.latent_channels = 12 + self.memory_used_decode = lambda shape, dtype: (1000 * shape[2] * shape[3] * shape[4] * (6 * 8 * 8)) * model_management.dtype_size(dtype) + self.upscale_ratio = (lambda a: max(0, a * 6 - 5), 8, 8) else: logging.warning("WARNING: No VAE weights detected, VAE not initalized.") self.first_stage_model = None @@ -296,6 +305,10 @@ class VAE: decode_fn = lambda a: self.first_stage_model.decode(a.to(self.vae_dtype).to(self.device)).float() return comfy.utils.tiled_scale_multidim(samples, decode_fn, tile=(tile_x,), overlap=overlap, upscale_amount=self.upscale_ratio, out_channels=self.output_channels, output_device=self.output_device) + def decode_tiled_3d(self, samples, tile_t=999, tile_x=32, tile_y=32, overlap=(1, 8, 8)): + decode_fn = lambda a: self.first_stage_model.decode(a.to(self.vae_dtype).to(self.device)).float() + return self.process_output(comfy.utils.tiled_scale_multidim(samples, decode_fn, tile=(tile_t, tile_x, tile_y), overlap=overlap, upscale_amount=self.upscale_ratio, out_channels=self.output_channels, output_device=self.output_device)) + def encode_tiled_(self, pixel_samples, tile_x=512, tile_y=512, overlap = 64): steps = pixel_samples.shape[0] * comfy.utils.get_tiled_scale_steps(pixel_samples.shape[3], pixel_samples.shape[2], tile_x, tile_y, overlap) steps += pixel_samples.shape[0] * comfy.utils.get_tiled_scale_steps(pixel_samples.shape[3], pixel_samples.shape[2], tile_x // 2, tile_y * 2, overlap) @@ -314,6 +327,7 @@ class VAE: return comfy.utils.tiled_scale_multidim(samples, encode_fn, tile=(tile_x,), overlap=overlap, upscale_amount=(1/self.downscale_ratio), out_channels=self.latent_channels, output_device=self.output_device) def decode(self, samples_in): + pixel_samples = None try: memory_used = self.memory_used_decode(samples_in.shape, self.vae_dtype) model_management.load_models_gpu([self.patcher], memory_required=memory_used) @@ -321,16 +335,21 @@ class VAE: batch_number = int(free_memory / memory_used) batch_number = max(1, batch_number) - pixel_samples = torch.empty((samples_in.shape[0], self.output_channels) + tuple(map(lambda a: a * self.upscale_ratio, samples_in.shape[2:])), device=self.output_device) for x in range(0, samples_in.shape[0], batch_number): samples = samples_in[x:x+batch_number].to(self.vae_dtype).to(self.device) - pixel_samples[x:x+batch_number] = self.process_output(self.first_stage_model.decode(samples).to(self.output_device).float()) + out = self.process_output(self.first_stage_model.decode(samples).to(self.output_device).float()) + if pixel_samples is None: + pixel_samples = torch.empty((samples_in.shape[0],) + tuple(out.shape[1:]), device=self.output_device) + pixel_samples[x:x+batch_number] = out except model_management.OOM_EXCEPTION as e: logging.warning("Warning: Ran out of memory when regular VAE decoding, retrying with tiled VAE decoding.") - if len(samples_in.shape) == 3: + dims = samples_in.ndim - 2 + if dims == 1: pixel_samples = self.decode_tiled_1d(samples_in) - else: + elif dims == 2: pixel_samples = self.decode_tiled_(samples_in) + elif dims == 3: + pixel_samples = self.decode_tiled_3d(samples_in) pixel_samples = pixel_samples.to(self.output_device).movedim(1,-1) return pixel_samples @@ -398,6 +417,7 @@ class CLIPType(Enum): STABLE_AUDIO = 4 HUNYUAN_DIT = 5 FLUX = 6 + MOCHI = 7 def load_clip(ckpt_paths, embedding_directory=None, clip_type=CLIPType.STABLE_DIFFUSION, model_options={}): clip_data = [] @@ -432,16 +452,14 @@ def detect_te_model(sd): return None -def t5xxl_weight_dtype(clip_data): +def t5xxl_detect(clip_data): weight_name = "encoder.block.23.layer.1.DenseReluDense.wi_1.weight" - dtype_t5 = None for sd in clip_data: - weight = sd.get(weight_name, None) - if weight is not None: - dtype_t5 = weight.dtype - break - return dtype_t5 + if weight_name in sd: + return comfy.text_encoders.sd3_clip.t5_xxl_detect(sd) + + return {} def load_text_encoder_state_dicts(state_dicts=[], embedding_directory=None, clip_type=CLIPType.STABLE_DIFFUSION, model_options={}): @@ -475,8 +493,12 @@ def load_text_encoder_state_dicts(state_dicts=[], embedding_directory=None, clip clip_target.clip = comfy.text_encoders.sd2_clip.SD2ClipModel clip_target.tokenizer = comfy.text_encoders.sd2_clip.SD2Tokenizer elif te_model == TEModel.T5_XXL: - clip_target.clip = comfy.text_encoders.sd3_clip.sd3_clip(clip_l=False, clip_g=False, t5=True, dtype_t5=t5xxl_weight_dtype(clip_data)) - clip_target.tokenizer = comfy.text_encoders.sd3_clip.SD3Tokenizer + if clip_type == CLIPType.SD3: + clip_target.clip = comfy.text_encoders.sd3_clip.sd3_clip(clip_l=False, clip_g=False, t5=True, **t5xxl_detect(clip_data)) + clip_target.tokenizer = comfy.text_encoders.sd3_clip.SD3Tokenizer + else: #CLIPType.MOCHI + clip_target.clip = comfy.text_encoders.genmo.mochi_te(**t5xxl_detect(clip_data)) + clip_target.tokenizer = comfy.text_encoders.genmo.MochiT5Tokenizer elif te_model == TEModel.T5_XL: clip_target.clip = comfy.text_encoders.aura_t5.AuraT5Model clip_target.tokenizer = comfy.text_encoders.aura_t5.AuraT5Tokenizer @@ -493,19 +515,19 @@ def load_text_encoder_state_dicts(state_dicts=[], embedding_directory=None, clip elif len(clip_data) == 2: if clip_type == CLIPType.SD3: te_models = [detect_te_model(clip_data[0]), detect_te_model(clip_data[1])] - clip_target.clip = comfy.text_encoders.sd3_clip.sd3_clip(clip_l=TEModel.CLIP_L in te_models, clip_g=TEModel.CLIP_G in te_models, t5=TEModel.T5_XXL in te_models, dtype_t5=t5xxl_weight_dtype(clip_data)) + clip_target.clip = comfy.text_encoders.sd3_clip.sd3_clip(clip_l=TEModel.CLIP_L in te_models, clip_g=TEModel.CLIP_G in te_models, t5=TEModel.T5_XXL in te_models, **t5xxl_detect(clip_data)) clip_target.tokenizer = comfy.text_encoders.sd3_clip.SD3Tokenizer elif clip_type == CLIPType.HUNYUAN_DIT: clip_target.clip = comfy.text_encoders.hydit.HyditModel clip_target.tokenizer = comfy.text_encoders.hydit.HyditTokenizer elif clip_type == CLIPType.FLUX: - clip_target.clip = comfy.text_encoders.flux.flux_clip(dtype_t5=t5xxl_weight_dtype(clip_data)) + clip_target.clip = comfy.text_encoders.flux.flux_clip(**t5xxl_detect(clip_data)) clip_target.tokenizer = comfy.text_encoders.flux.FluxTokenizer else: clip_target.clip = sdxl_clip.SDXLClipModel clip_target.tokenizer = sdxl_clip.SDXLTokenizer elif len(clip_data) == 3: - clip_target.clip = comfy.text_encoders.sd3_clip.sd3_clip(dtype_t5=t5xxl_weight_dtype(clip_data)) + clip_target.clip = comfy.text_encoders.sd3_clip.sd3_clip(**t5xxl_detect(clip_data)) clip_target.tokenizer = comfy.text_encoders.sd3_clip.SD3Tokenizer parameters = 0 @@ -580,7 +602,7 @@ def load_state_dict_guess_config(sd, output_vae=True, output_clip=True, output_c return None unet_weight_dtype = list(model_config.supported_inference_dtypes) - if weight_dtype is not None: + if weight_dtype is not None and model_config.scaled_fp8 is None: unet_weight_dtype.append(weight_dtype) model_config.custom_operations = model_options.get("custom_operations", None) @@ -649,6 +671,8 @@ def load_diffusion_model_state_dict(sd, model_options={}): #load unet in diffuse sd = temp_sd parameters = comfy.utils.calculate_parameters(sd) + weight_dtype = comfy.utils.weight_dtype(sd) + load_device = model_management.get_torch_device() model_config = model_detection.model_config_from_unet(sd, "") @@ -675,8 +699,12 @@ def load_diffusion_model_state_dict(sd, model_options={}): #load unet in diffuse logging.warning("{} {}".format(diffusers_keys[k], k)) offload_device = model_management.unet_offload_device() + unet_weight_dtype = list(model_config.supported_inference_dtypes) + if weight_dtype is not None and model_config.scaled_fp8 is None: + unet_weight_dtype.append(weight_dtype) + if dtype is None: - unet_dtype = model_management.unet_dtype(model_params=parameters, supported_dtypes=model_config.supported_inference_dtypes) + unet_dtype = model_management.unet_dtype(model_params=parameters, supported_dtypes=unet_weight_dtype) else: unet_dtype = dtype diff --git a/comfy/sd1_clip.py b/comfy/sd1_clip.py index bb240526..a454f3bb 100644 --- a/comfy/sd1_clip.py +++ b/comfy/sd1_clip.py @@ -94,11 +94,20 @@ class SDClipModel(torch.nn.Module, ClipTokenWeightEncoder): config = json.load(f) operations = model_options.get("custom_operations", None) + scaled_fp8 = None + if operations is None: - operations = comfy.ops.manual_cast + scaled_fp8 = model_options.get("scaled_fp8", None) + if scaled_fp8 is not None: + operations = comfy.ops.scaled_fp8_ops(fp8_matrix_mult=False, override_dtype=scaled_fp8) + else: + operations = comfy.ops.manual_cast self.operations = operations self.transformer = model_class(config, dtype, device, self.operations) + if scaled_fp8 is not None: + self.transformer.scaled_fp8 = torch.nn.Parameter(torch.tensor([], dtype=scaled_fp8)) + self.num_layers = self.transformer.num_layers self.max_length = max_length diff --git a/comfy/supported_models.py b/comfy/supported_models.py index 3603313f..9931f4c5 100644 --- a/comfy/supported_models.py +++ b/comfy/supported_models.py @@ -10,6 +10,7 @@ import comfy.text_encoders.sa_t5 import comfy.text_encoders.aura_t5 import comfy.text_encoders.hydit import comfy.text_encoders.flux +import comfy.text_encoders.genmo from . import supported_models_base from . import latent_formats @@ -529,12 +530,11 @@ class SD3(supported_models_base.BASE): clip_l = True if "{}clip_g.transformer.text_model.final_layer_norm.weight".format(pref) in state_dict: clip_g = True - t5_key = "{}t5xxl.transformer.encoder.final_layer_norm.weight".format(pref) - if t5_key in state_dict: + t5_detect = comfy.text_encoders.sd3_clip.t5_xxl_detect(state_dict, "{}t5xxl.transformer.".format(pref)) + if "dtype_t5" in t5_detect: t5 = True - dtype_t5 = state_dict[t5_key].dtype - return supported_models_base.ClipTarget(comfy.text_encoders.sd3_clip.SD3Tokenizer, comfy.text_encoders.sd3_clip.sd3_clip(clip_l=clip_l, clip_g=clip_g, t5=t5, dtype_t5=dtype_t5)) + return supported_models_base.ClipTarget(comfy.text_encoders.sd3_clip.SD3Tokenizer, comfy.text_encoders.sd3_clip.sd3_clip(clip_l=clip_l, clip_g=clip_g, t5=t5, **t5_detect)) class StableAudio(supported_models_base.BASE): unet_config = { @@ -653,11 +653,8 @@ class Flux(supported_models_base.BASE): def clip_target(self, state_dict={}): pref = self.text_encoder_key_prefix[0] - t5_key = "{}t5xxl.transformer.encoder.final_layer_norm.weight".format(pref) - dtype_t5 = None - if t5_key in state_dict: - dtype_t5 = state_dict[t5_key].dtype - return supported_models_base.ClipTarget(comfy.text_encoders.flux.FluxTokenizer, comfy.text_encoders.flux.flux_clip(dtype_t5=dtype_t5)) + t5_detect = comfy.text_encoders.sd3_clip.t5_xxl_detect(state_dict, "{}t5xxl.transformer.".format(pref)) + return supported_models_base.ClipTarget(comfy.text_encoders.flux.FluxTokenizer, comfy.text_encoders.flux.flux_clip(**t5_detect)) class FluxSchnell(Flux): unet_config = { @@ -674,7 +671,36 @@ class FluxSchnell(Flux): out = model_base.Flux(self, model_type=model_base.ModelType.FLOW, device=device) return out +class GenmoMochi(supported_models_base.BASE): + unet_config = { + "image_model": "mochi_preview", + } -models = [Stable_Zero123, SD15_instructpix2pix, SD15, SD20, SD21UnclipL, SD21UnclipH, SDXL_instructpix2pix, SDXLRefiner, SDXL, SSD1B, KOALA_700M, KOALA_1B, Segmind_Vega, SD_X4Upscaler, Stable_Cascade_C, Stable_Cascade_B, SV3D_u, SV3D_p, SD3, StableAudio, AuraFlow, HunyuanDiT, HunyuanDiT1, Flux, FluxSchnell] + sampling_settings = { + "multiplier": 1.0, + "shift": 6.0, + } + + unet_extra_config = {} + latent_format = latent_formats.Mochi + + memory_usage_factor = 2.0 #TODO + + supported_inference_dtypes = [torch.bfloat16, torch.float32] + + vae_key_prefix = ["vae."] + text_encoder_key_prefix = ["text_encoders."] + + def get_model(self, state_dict, prefix="", device=None): + out = model_base.GenmoMochi(self, device=device) + return out + + def clip_target(self, state_dict={}): + pref = self.text_encoder_key_prefix[0] + t5_detect = comfy.text_encoders.sd3_clip.t5_xxl_detect(state_dict, "{}t5xxl.transformer.".format(pref)) + return supported_models_base.ClipTarget(comfy.text_encoders.genmo.MochiT5Tokenizer, comfy.text_encoders.genmo.mochi_te(**t5_detect)) + + +models = [Stable_Zero123, SD15_instructpix2pix, SD15, SD20, SD21UnclipL, SD21UnclipH, SDXL_instructpix2pix, SDXLRefiner, SDXL, SSD1B, KOALA_700M, KOALA_1B, Segmind_Vega, SD_X4Upscaler, Stable_Cascade_C, Stable_Cascade_B, SV3D_u, SV3D_p, SD3, StableAudio, AuraFlow, HunyuanDiT, HunyuanDiT1, Flux, FluxSchnell, GenmoMochi] models += [SVD_img2vid] diff --git a/comfy/supported_models_base.py b/comfy/supported_models_base.py index e2b70e69..54573abb 100644 --- a/comfy/supported_models_base.py +++ b/comfy/supported_models_base.py @@ -49,6 +49,7 @@ class BASE: manual_cast_dtype = None custom_operations = None + scaled_fp8 = None optimizations = {"fp8": False} @classmethod diff --git a/comfy/text_encoders/flux.py b/comfy/text_encoders/flux.py index b13fa5b4..b945b1aa 100644 --- a/comfy/text_encoders/flux.py +++ b/comfy/text_encoders/flux.py @@ -1,15 +1,11 @@ from comfy import sd1_clip import comfy.text_encoders.t5 +import comfy.text_encoders.sd3_clip import comfy.model_management from transformers import T5TokenizerFast import torch import os -class T5XXLModel(sd1_clip.SDClipModel): - def __init__(self, device="cpu", layer="last", layer_idx=None, dtype=None, model_options={}): - textmodel_json_config = os.path.join(os.path.dirname(os.path.realpath(__file__)), "t5_config_xxl.json") - super().__init__(device=device, layer=layer, layer_idx=layer_idx, textmodel_json_config=textmodel_json_config, dtype=dtype, special_tokens={"end": 1, "pad": 0}, model_class=comfy.text_encoders.t5.T5, model_options=model_options) - class T5XXLTokenizer(sd1_clip.SDTokenizer): def __init__(self, embedding_directory=None, tokenizer_data={}): tokenizer_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "t5_tokenizer") @@ -41,7 +37,7 @@ class FluxClipModel(torch.nn.Module): dtype_t5 = comfy.model_management.pick_weight_dtype(dtype_t5, dtype, device) clip_l_class = model_options.get("clip_l_class", sd1_clip.SDClipModel) self.clip_l = clip_l_class(device=device, dtype=dtype, return_projected_pooled=False, model_options=model_options) - self.t5xxl = T5XXLModel(device=device, dtype=dtype_t5, model_options=model_options) + self.t5xxl = comfy.text_encoders.sd3_clip.T5XXLModel(device=device, dtype=dtype_t5, model_options=model_options) self.dtypes = set([dtype, dtype_t5]) def set_clip_options(self, options): @@ -66,8 +62,11 @@ class FluxClipModel(torch.nn.Module): else: return self.t5xxl.load_sd(sd) -def flux_clip(dtype_t5=None): +def flux_clip(dtype_t5=None, t5xxl_scaled_fp8=None): class FluxClipModel_(FluxClipModel): def __init__(self, device="cpu", dtype=None, model_options={}): + if t5xxl_scaled_fp8 is not None and "t5xxl_scaled_fp8" not in model_options: + model_options = model_options.copy() + model_options["t5xxl_scaled_fp8"] = t5xxl_scaled_fp8 super().__init__(dtype_t5=dtype_t5, device=device, dtype=dtype, model_options=model_options) return FluxClipModel_ diff --git a/comfy/text_encoders/genmo.py b/comfy/text_encoders/genmo.py new file mode 100644 index 00000000..5e96cea6 --- /dev/null +++ b/comfy/text_encoders/genmo.py @@ -0,0 +1,38 @@ +from comfy import sd1_clip +import comfy.text_encoders.sd3_clip +import os +from transformers import T5TokenizerFast + + +class T5XXLModel(comfy.text_encoders.sd3_clip.T5XXLModel): + def __init__(self, **kwargs): + kwargs["attention_mask"] = True + super().__init__(**kwargs) + + +class MochiT5XXL(sd1_clip.SD1ClipModel): + def __init__(self, device="cpu", dtype=None, model_options={}): + super().__init__(device=device, dtype=dtype, clip_name="t5xxl", clip_model=T5XXLModel, model_options=model_options) + + +class T5XXLTokenizer(sd1_clip.SDTokenizer): + def __init__(self, embedding_directory=None, tokenizer_data={}): + tokenizer_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "t5_tokenizer") + super().__init__(tokenizer_path, embedding_directory=embedding_directory, pad_with_end=False, embedding_size=4096, embedding_key='t5xxl', tokenizer_class=T5TokenizerFast, has_start_token=False, pad_to_max_length=False, max_length=99999999, min_length=256) + + +class MochiT5Tokenizer(sd1_clip.SD1Tokenizer): + def __init__(self, embedding_directory=None, tokenizer_data={}): + super().__init__(embedding_directory=embedding_directory, tokenizer_data=tokenizer_data, clip_name="t5xxl", tokenizer=T5XXLTokenizer) + + +def mochi_te(dtype_t5=None, t5xxl_scaled_fp8=None): + class MochiTEModel_(MochiT5XXL): + def __init__(self, device="cpu", dtype=None, model_options={}): + if t5xxl_scaled_fp8 is not None and "t5xxl_scaled_fp8" not in model_options: + model_options = model_options.copy() + model_options["t5xxl_scaled_fp8"] = t5xxl_scaled_fp8 + if dtype is None: + dtype = dtype_t5 + super().__init__(device=device, dtype=dtype, model_options=model_options) + return MochiTEModel_ diff --git a/comfy/text_encoders/sd3_clip.py b/comfy/text_encoders/sd3_clip.py index 0340e65b..00d7e31a 100644 --- a/comfy/text_encoders/sd3_clip.py +++ b/comfy/text_encoders/sd3_clip.py @@ -10,8 +10,26 @@ import logging class T5XXLModel(sd1_clip.SDClipModel): def __init__(self, device="cpu", layer="last", layer_idx=None, dtype=None, attention_mask=False, model_options={}): textmodel_json_config = os.path.join(os.path.dirname(os.path.realpath(__file__)), "t5_config_xxl.json") + t5xxl_scaled_fp8 = model_options.get("t5xxl_scaled_fp8", None) + if t5xxl_scaled_fp8 is not None: + model_options = model_options.copy() + model_options["scaled_fp8"] = t5xxl_scaled_fp8 + super().__init__(device=device, layer=layer, layer_idx=layer_idx, textmodel_json_config=textmodel_json_config, dtype=dtype, special_tokens={"end": 1, "pad": 0}, model_class=comfy.text_encoders.t5.T5, enable_attention_masks=attention_mask, return_attention_masks=attention_mask, model_options=model_options) + +def t5_xxl_detect(state_dict, prefix=""): + out = {} + t5_key = "{}encoder.final_layer_norm.weight".format(prefix) + if t5_key in state_dict: + out["dtype_t5"] = state_dict[t5_key].dtype + + scaled_fp8_key = "{}scaled_fp8".format(prefix) + if scaled_fp8_key in state_dict: + out["t5xxl_scaled_fp8"] = state_dict[scaled_fp8_key].dtype + + return out + class T5XXLTokenizer(sd1_clip.SDTokenizer): def __init__(self, embedding_directory=None, tokenizer_data={}): tokenizer_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), "t5_tokenizer") @@ -139,8 +157,11 @@ class SD3ClipModel(torch.nn.Module): else: return self.t5xxl.load_sd(sd) -def sd3_clip(clip_l=True, clip_g=True, t5=True, dtype_t5=None, t5_attention_mask=False): +def sd3_clip(clip_l=True, clip_g=True, t5=True, dtype_t5=None, t5xxl_scaled_fp8=None, t5_attention_mask=False): class SD3ClipModel_(SD3ClipModel): def __init__(self, device="cpu", dtype=None, model_options={}): + if t5xxl_scaled_fp8 is not None and "t5xxl_scaled_fp8" not in model_options: + model_options = model_options.copy() + model_options["t5xxl_scaled_fp8"] = t5xxl_scaled_fp8 super().__init__(clip_l=clip_l, clip_g=clip_g, t5=t5, dtype_t5=dtype_t5, t5_attention_mask=t5_attention_mask, device=device, dtype=dtype, model_options=model_options) return SD3ClipModel_ diff --git a/comfy/utils.py b/comfy/utils.py index 78f8314f..06c81107 100644 --- a/comfy/utils.py +++ b/comfy/utils.py @@ -68,7 +68,7 @@ def weight_dtype(sd, prefix=""): for k in sd.keys(): if k.startswith(prefix): w = sd[k] - dtypes[w.dtype] = dtypes.get(w.dtype, 0) + 1 + dtypes[w.dtype] = dtypes.get(w.dtype, 0) + w.numel() if len(dtypes) == 0: return None @@ -690,9 +690,14 @@ def lanczos(samples, width, height): return result.to(samples.device, samples.dtype) def common_upscale(samples, width, height, upscale_method, crop): + orig_shape = tuple(samples.shape) + if len(orig_shape) > 4: + samples = samples.reshape(samples.shape[0], samples.shape[1], -1, samples.shape[-2], samples.shape[-1]) + samples = samples.movedim(2, 1) + samples = samples.reshape(-1, orig_shape[1], orig_shape[-2], orig_shape[-1]) if crop == "center": - old_width = samples.shape[3] - old_height = samples.shape[2] + old_width = samples.shape[-1] + old_height = samples.shape[-2] old_aspect = old_width / old_height new_aspect = width / height x = 0 @@ -701,16 +706,22 @@ def common_upscale(samples, width, height, upscale_method, crop): x = round((old_width - old_width * (new_aspect / old_aspect)) / 2) elif old_aspect < new_aspect: y = round((old_height - old_height * (old_aspect / new_aspect)) / 2) - s = samples[:,:,y:old_height-y,x:old_width-x] + s = samples.narrow(-2, y, old_height - y * 2).narrow(-1, x, old_width - x * 2) else: s = samples if upscale_method == "bislerp": - return bislerp(s, width, height) + out = bislerp(s, width, height) elif upscale_method == "lanczos": - return lanczos(s, width, height) + out = lanczos(s, width, height) else: - return torch.nn.functional.interpolate(s, size=(height, width), mode=upscale_method) + out = torch.nn.functional.interpolate(s, size=(height, width), mode=upscale_method) + + if len(orig_shape) == 4: + return out + + out = out.reshape((orig_shape[0], -1, orig_shape[1]) + (height, width)) + return out.movedim(2, 1).reshape(orig_shape[:-2] + (height, width)) def get_tiled_scale_steps(width, height, tile_x, tile_y, overlap): rows = 1 if height <= tile_y else math.ceil((height - overlap) / (tile_y - overlap)) @@ -720,7 +731,27 @@ def get_tiled_scale_steps(width, height, tile_x, tile_y, overlap): @torch.inference_mode() def tiled_scale_multidim(samples, function, tile=(64, 64), overlap = 8, upscale_amount = 4, out_channels = 3, output_device="cpu", pbar = None): dims = len(tile) - output = torch.empty([samples.shape[0], out_channels] + list(map(lambda a: round(a * upscale_amount), samples.shape[2:])), device=output_device) + + if not (isinstance(upscale_amount, (tuple, list))): + upscale_amount = [upscale_amount] * dims + + if not (isinstance(overlap, (tuple, list))): + overlap = [overlap] * dims + + def get_upscale(dim, val): + up = upscale_amount[dim] + if callable(up): + return up(val) + else: + return up * val + + def mult_list_upscale(a): + out = [] + for i in range(len(a)): + out.append(round(get_upscale(i, a[i]))) + return out + + output = torch.empty([samples.shape[0], out_channels] + mult_list_upscale(samples.shape[2:]), device=output_device) for b in range(samples.shape[0]): s = samples[b:b+1] @@ -732,27 +763,27 @@ def tiled_scale_multidim(samples, function, tile=(64, 64), overlap = 8, upscale_ pbar.update(1) continue - out = torch.zeros([s.shape[0], out_channels] + list(map(lambda a: round(a * upscale_amount), s.shape[2:])), device=output_device) - out_div = torch.zeros([s.shape[0], out_channels] + list(map(lambda a: round(a * upscale_amount), s.shape[2:])), device=output_device) + out = torch.zeros([s.shape[0], out_channels] + mult_list_upscale(s.shape[2:]), device=output_device) + out_div = torch.zeros([s.shape[0], out_channels] + mult_list_upscale(s.shape[2:]), device=output_device) - positions = [range(0, s.shape[d+2], tile[d] - overlap) if s.shape[d+2] > tile[d] else [0] for d in range(dims)] + positions = [range(0, s.shape[d+2], tile[d] - overlap[d]) if s.shape[d+2] > tile[d] else [0] for d in range(dims)] for it in itertools.product(*positions): s_in = s upscaled = [] for d in range(dims): - pos = max(0, min(s.shape[d + 2] - overlap, it[d])) + pos = max(0, min(s.shape[d + 2] - (overlap[d] + 1), it[d])) l = min(tile[d], s.shape[d + 2] - pos) s_in = s_in.narrow(d + 2, pos, l) - upscaled.append(round(pos * upscale_amount)) + upscaled.append(round(get_upscale(d, pos))) ps = function(s_in).to(output_device) mask = torch.ones_like(ps) - feather = round(overlap * upscale_amount) - for t in range(feather): - for d in range(2, dims + 2): + for d in range(2, dims + 2): + feather = round(get_upscale(d - 2, overlap[d - 2])) + for t in range(feather): a = (t + 1) / feather mask.narrow(d, t, 1).mul_(a) mask.narrow(d, mask.shape[d] - 1 - t, 1).mul_(a) diff --git a/comfy_extras/nodes_latent.py b/comfy_extras/nodes_latent.py index eabae088..af273681 100644 --- a/comfy_extras/nodes_latent.py +++ b/comfy_extras/nodes_latent.py @@ -1,4 +1,5 @@ import comfy.utils +import comfy_extras.nodes_post_processing import torch def reshape_latent_to(target_shape, latent): @@ -145,6 +146,131 @@ class LatentBatchSeedBehavior: return (samples_out,) +class LatentApplyOperation: + @classmethod + def INPUT_TYPES(s): + return {"required": { "samples": ("LATENT",), + "operation": ("LATENT_OPERATION",), + }} + + RETURN_TYPES = ("LATENT",) + FUNCTION = "op" + + CATEGORY = "latent/advanced/operations" + EXPERIMENTAL = True + + def op(self, samples, operation): + samples_out = samples.copy() + + s1 = samples["samples"] + samples_out["samples"] = operation(latent=s1) + return (samples_out,) + +class LatentApplyOperationCFG: + @classmethod + def INPUT_TYPES(s): + return {"required": { "model": ("MODEL",), + "operation": ("LATENT_OPERATION",), + }} + RETURN_TYPES = ("MODEL",) + FUNCTION = "patch" + + CATEGORY = "latent/advanced/operations" + EXPERIMENTAL = True + + def patch(self, model, operation): + m = model.clone() + + def pre_cfg_function(args): + conds_out = args["conds_out"] + if len(conds_out) == 2: + conds_out[0] = operation(latent=(conds_out[0] - conds_out[1])) + conds_out[1] + else: + conds_out[0] = operation(latent=conds_out[0]) + return conds_out + + m.set_model_sampler_pre_cfg_function(pre_cfg_function) + return (m, ) + +class LatentOperationTonemapReinhard: + @classmethod + def INPUT_TYPES(s): + return {"required": { "multiplier": ("FLOAT", {"default": 1.0, "min": 0.0, "max": 100.0, "step": 0.01}), + }} + + RETURN_TYPES = ("LATENT_OPERATION",) + FUNCTION = "op" + + CATEGORY = "latent/advanced/operations" + EXPERIMENTAL = True + + def op(self, multiplier): + def tonemap_reinhard(latent, **kwargs): + latent_vector_magnitude = (torch.linalg.vector_norm(latent, dim=(1)) + 0.0000000001)[:,None] + normalized_latent = latent / latent_vector_magnitude + + mean = torch.mean(latent_vector_magnitude, dim=(1,2,3), keepdim=True) + std = torch.std(latent_vector_magnitude, dim=(1,2,3), keepdim=True) + + top = (std * 5 + mean) * multiplier + + #reinhard + latent_vector_magnitude *= (1.0 / top) + new_magnitude = latent_vector_magnitude / (latent_vector_magnitude + 1.0) + new_magnitude *= top + + return normalized_latent * new_magnitude + return (tonemap_reinhard,) + +class LatentOperationSharpen: + @classmethod + def INPUT_TYPES(s): + return {"required": { + "sharpen_radius": ("INT", { + "default": 9, + "min": 1, + "max": 31, + "step": 1 + }), + "sigma": ("FLOAT", { + "default": 1.0, + "min": 0.1, + "max": 10.0, + "step": 0.1 + }), + "alpha": ("FLOAT", { + "default": 0.1, + "min": 0.0, + "max": 5.0, + "step": 0.01 + }), + }} + + RETURN_TYPES = ("LATENT_OPERATION",) + FUNCTION = "op" + + CATEGORY = "latent/advanced/operations" + EXPERIMENTAL = True + + def op(self, sharpen_radius, sigma, alpha): + def sharpen(latent, **kwargs): + luminance = (torch.linalg.vector_norm(latent, dim=(1)) + 1e-6)[:,None] + normalized_latent = latent / luminance + channels = latent.shape[1] + + kernel_size = sharpen_radius * 2 + 1 + kernel = comfy_extras.nodes_post_processing.gaussian_kernel(kernel_size, sigma, device=luminance.device) + center = kernel_size // 2 + + kernel *= alpha * -10 + kernel[center, center] = kernel[center, center] - kernel.sum() + 1.0 + + padded_image = torch.nn.functional.pad(normalized_latent, (sharpen_radius,sharpen_radius,sharpen_radius,sharpen_radius), 'reflect') + sharpened = torch.nn.functional.conv2d(padded_image, kernel.repeat(channels, 1, 1).unsqueeze(1), padding=kernel_size // 2, groups=channels)[:,:,sharpen_radius:-sharpen_radius, sharpen_radius:-sharpen_radius] + + return luminance * sharpened + return (sharpen,) + NODE_CLASS_MAPPINGS = { "LatentAdd": LatentAdd, "LatentSubtract": LatentSubtract, @@ -152,4 +278,8 @@ NODE_CLASS_MAPPINGS = { "LatentInterpolate": LatentInterpolate, "LatentBatch": LatentBatch, "LatentBatchSeedBehavior": LatentBatchSeedBehavior, + "LatentApplyOperation": LatentApplyOperation, + "LatentApplyOperationCFG": LatentApplyOperationCFG, + "LatentOperationTonemapReinhard": LatentOperationTonemapReinhard, + "LatentOperationSharpen": LatentOperationSharpen, } diff --git a/comfy_extras/nodes_lora_extract.py b/comfy_extras/nodes_lora_extract.py index 3c2f179d..dfd4fe9f 100644 --- a/comfy_extras/nodes_lora_extract.py +++ b/comfy_extras/nodes_lora_extract.py @@ -82,8 +82,8 @@ class LoraSave: "lora_type": (tuple(LORA_TYPES.keys()),), "bias_diff": ("BOOLEAN", {"default": True}), }, - "optional": {"model_diff": ("MODEL",), - "text_encoder_diff": ("CLIP",)}, + "optional": {"model_diff": ("MODEL", {"tooltip": "The ModelSubtract output to be converted to a lora."}), + "text_encoder_diff": ("CLIP", {"tooltip": "The CLIPSubtract output to be converted to a lora."})}, } RETURN_TYPES = () FUNCTION = "save" @@ -113,3 +113,7 @@ class LoraSave: NODE_CLASS_MAPPINGS = { "LoraSave": LoraSave } + +NODE_DISPLAY_NAME_MAPPINGS = { + "LoraSave": "Extract and Save Lora" +} diff --git a/comfy_extras/nodes_mochi.py b/comfy_extras/nodes_mochi.py new file mode 100644 index 00000000..4cbbea09 --- /dev/null +++ b/comfy_extras/nodes_mochi.py @@ -0,0 +1,26 @@ +import nodes +import torch +import comfy.model_management + +class EmptyMochiLatentVideo: + def __init__(self): + self.device = comfy.model_management.intermediate_device() + + @classmethod + def INPUT_TYPES(s): + return {"required": { "width": ("INT", {"default": 848, "min": 16, "max": nodes.MAX_RESOLUTION, "step": 16}), + "height": ("INT", {"default": 480, "min": 16, "max": nodes.MAX_RESOLUTION, "step": 16}), + "length": ("INT", {"default": 25, "min": 7, "max": nodes.MAX_RESOLUTION, "step": 6}), + "batch_size": ("INT", {"default": 1, "min": 1, "max": 4096})}} + RETURN_TYPES = ("LATENT",) + FUNCTION = "generate" + + CATEGORY = "latent/mochi" + + def generate(self, width, height, length, batch_size=1): + latent = torch.zeros([batch_size, 12, ((length - 1) // 6) + 1, height // 8, width // 8], device=self.device) + return ({"samples":latent}, ) + +NODE_CLASS_MAPPINGS = { + "EmptyMochiLatentVideo": EmptyMochiLatentVideo, +} diff --git a/comfy_extras/nodes_model_merging_model_specific.py b/comfy_extras/nodes_model_merging_model_specific.py index 9557d9b1..0e847192 100644 --- a/comfy_extras/nodes_model_merging_model_specific.py +++ b/comfy_extras/nodes_model_merging_model_specific.py @@ -101,10 +101,34 @@ class ModelMergeFlux1(comfy_extras.nodes_model_merging.ModelMergeBlocks): return {"required": arg_dict} +class ModelMergeSD35_Large(comfy_extras.nodes_model_merging.ModelMergeBlocks): + CATEGORY = "advanced/model_merging/model_specific" + + @classmethod + def INPUT_TYPES(s): + arg_dict = { "model1": ("MODEL",), + "model2": ("MODEL",)} + + argument = ("FLOAT", {"default": 1.0, "min": 0.0, "max": 1.0, "step": 0.01}) + + arg_dict["pos_embed."] = argument + arg_dict["x_embedder."] = argument + arg_dict["context_embedder."] = argument + arg_dict["y_embedder."] = argument + arg_dict["t_embedder."] = argument + + for i in range(38): + arg_dict["joint_blocks.{}.".format(i)] = argument + + arg_dict["final_layer."] = argument + + return {"required": arg_dict} + NODE_CLASS_MAPPINGS = { "ModelMergeSD1": ModelMergeSD1, "ModelMergeSD2": ModelMergeSD1, #SD1 and SD2 have the same blocks "ModelMergeSDXL": ModelMergeSDXL, "ModelMergeSD3_2B": ModelMergeSD3_2B, "ModelMergeFlux1": ModelMergeFlux1, + "ModelMergeSD35_Large": ModelMergeSD35_Large, } diff --git a/comfy_extras/nodes_sd3.py b/comfy_extras/nodes_sd3.py index ddf538de..4d664093 100644 --- a/comfy_extras/nodes_sd3.py +++ b/comfy_extras/nodes_sd3.py @@ -3,7 +3,7 @@ import comfy.sd import comfy.model_management import nodes import torch - +import re class TripleCLIPLoader: @classmethod def INPUT_TYPES(s): @@ -95,11 +95,70 @@ class ControlNetApplySD3(nodes.ControlNetApplyAdvanced): CATEGORY = "conditioning/controlnet" DEPRECATED = True +class SkipLayerGuidanceSD3: + ''' + Enhance guidance towards detailed dtructure by having another set of CFG negative with skipped layers. + Inspired by Perturbed Attention Guidance (https://arxiv.org/abs/2403.17377) + Experimental implementation by Dango233@StabilityAI. + ''' + @classmethod + def INPUT_TYPES(s): + return {"required": {"model": ("MODEL", ), + "layers": ("STRING", {"default": "7, 8, 9", "multiline": False}), + "scale": ("FLOAT", {"default": 3.0, "min": 0.0, "max": 10.0, "step": 0.1}), + "start_percent": ("FLOAT", {"default": 0.01, "min": 0.0, "max": 1.0, "step": 0.001}), + "end_percent": ("FLOAT", {"default": 0.15, "min": 0.0, "max": 1.0, "step": 0.001}) + }} + RETURN_TYPES = ("MODEL",) + FUNCTION = "skip_guidance" + + CATEGORY = "advanced/guidance" + + + def skip_guidance(self, model, layers, scale, start_percent, end_percent): + if layers == "" or layers == None: + return (model, ) + # check if layer is comma separated integers + def skip(args, extra_args): + return args + + model_sampling = model.get_model_object("model_sampling") + sigma_start = model_sampling.percent_to_sigma(start_percent) + sigma_end = model_sampling.percent_to_sigma(end_percent) + + def post_cfg_function(args): + model = args["model"] + cond_pred = args["cond_denoised"] + cond = args["cond"] + cfg_result = args["denoised"] + sigma = args["sigma"] + x = args["input"] + model_options = args["model_options"].copy() + + for layer in layers: + model_options = comfy.model_patcher.set_model_options_patch_replace(model_options, skip, "dit", "double_block", layer) + model_sampling.percent_to_sigma(start_percent) + + sigma_ = sigma[0].item() + if scale > 0 and sigma_ >= sigma_end and sigma_ <= sigma_start: + (slg,) = comfy.samplers.calc_cond_batch(model, [cond], x, sigma, model_options) + cfg_result = cfg_result + (cond_pred - slg) * scale + return cfg_result + + layers = re.findall(r'\d+', layers) + layers = [int(i) for i in layers] + m = model.clone() + m.set_model_sampler_post_cfg_function(post_cfg_function) + + return (m, ) + + NODE_CLASS_MAPPINGS = { "TripleCLIPLoader": TripleCLIPLoader, "EmptySD3LatentImage": EmptySD3LatentImage, "CLIPTextEncodeSD3": CLIPTextEncodeSD3, "ControlNetApplySD3": ControlNetApplySD3, + "SkipLayerGuidanceSD3": SkipLayerGuidanceSD3, } NODE_DISPLAY_NAME_MAPPINGS = { diff --git a/nodes.py b/nodes.py index 15a78352..c81a0af1 100644 --- a/nodes.py +++ b/nodes.py @@ -281,7 +281,10 @@ class VAEDecode: DESCRIPTION = "Decodes latent images back into pixel space images." def decode(self, vae, samples): - return (vae.decode(samples["samples"]), ) + images = vae.decode(samples["samples"]) + if len(images.shape) == 5: #Combine batches + images = images.reshape(-1, images.shape[-3], images.shape[-2], images.shape[-1]) + return (images, ) class VAEDecodeTiled: @classmethod @@ -886,7 +889,7 @@ class CLIPLoader: @classmethod def INPUT_TYPES(s): return {"required": { "clip_name": (folder_paths.get_filename_list("clip"), ), - "type": (["stable_diffusion", "stable_cascade", "sd3", "stable_audio"], ), + "type": (["stable_diffusion", "stable_cascade", "sd3", "stable_audio", "mochi"], ), }} RETURN_TYPES = ("CLIP",) FUNCTION = "load_clip" @@ -900,6 +903,8 @@ class CLIPLoader: clip_type = comfy.sd.CLIPType.SD3 elif type == "stable_audio": clip_type = comfy.sd.CLIPType.STABLE_AUDIO + elif type == "mochi": + clip_type = comfy.sd.CLIPType.MOCHI else: clip_type = comfy.sd.CLIPType.STABLE_DIFFUSION @@ -1179,10 +1184,10 @@ class LatentUpscale: if width == 0: height = max(64, height) - width = max(64, round(samples["samples"].shape[3] * height / samples["samples"].shape[2])) + width = max(64, round(samples["samples"].shape[-1] * height / samples["samples"].shape[-2])) elif height == 0: width = max(64, width) - height = max(64, round(samples["samples"].shape[2] * width / samples["samples"].shape[3])) + height = max(64, round(samples["samples"].shape[-2] * width / samples["samples"].shape[-1])) else: width = max(64, width) height = max(64, height) @@ -1204,8 +1209,8 @@ class LatentUpscaleBy: def upscale(self, samples, upscale_method, scale_by): s = samples.copy() - width = round(samples["samples"].shape[3] * scale_by) - height = round(samples["samples"].shape[2] * scale_by) + width = round(samples["samples"].shape[-1] * scale_by) + height = round(samples["samples"].shape[-2] * scale_by) s["samples"] = comfy.utils.common_upscale(samples["samples"], width, height, upscale_method, "disabled") return (s,) @@ -2111,6 +2116,7 @@ def init_builtin_extra_nodes(): "nodes_flux.py", "nodes_lora_extract.py", "nodes_torch_compile.py", + "nodes_mochi.py", ] import_failed = [] diff --git a/server.py b/server.py index c7bf6622..ada6d90c 100644 --- a/server.py +++ b/server.py @@ -40,7 +40,7 @@ class BinaryEventTypes: async def send_socket_catch_exception(function, message): try: await function(message) - except (aiohttp.ClientError, aiohttp.ClientPayloadError, ConnectionResetError) as err: + except (aiohttp.ClientError, aiohttp.ClientPayloadError, ConnectionResetError, BrokenPipeError, ConnectionError) as err: logging.warning("send error: {}".format(err)) def get_comfyui_version(): diff --git a/web/assets/ExtensionPanel-DZLYjWBj.js b/web/assets/ExtensionPanel-DZLYjWBj.js new file mode 100644 index 00000000..36e944c3 --- /dev/null +++ b/web/assets/ExtensionPanel-DZLYjWBj.js @@ -0,0 +1,103 @@ +var __defProp = Object.defineProperty; +var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); +import { d as defineComponent, bK as useExtensionStore, u as useSettingStore, r as ref, o as onMounted, q as computed, g as openBlock, h as createElementBlock, i as createVNode, y as withCtx, z as unref, bL as script$1, A as createBaseVNode, x as createBlock, M as Fragment, N as renderList, am as toDisplayString, ap as createTextVNode, j as createCommentVNode, D as script$4 } from "./index-CgU1oKZt.js"; +import { s as script, a as script$2, b as script$3 } from "./index-DBWDcZsl.js"; +import "./index-DYEEBf64.js"; +const _hoisted_1 = { class: "extension-panel" }; +const _hoisted_2 = { class: "mt-4" }; +const _sfc_main = /* @__PURE__ */ defineComponent({ + __name: "ExtensionPanel", + setup(__props) { + const extensionStore = useExtensionStore(); + const settingStore = useSettingStore(); + const editingEnabledExtensions = ref({}); + onMounted(() => { + extensionStore.extensions.forEach((ext) => { + editingEnabledExtensions.value[ext.name] = extensionStore.isExtensionEnabled(ext.name); + }); + }); + const changedExtensions = computed(() => { + return extensionStore.extensions.filter( + (ext) => editingEnabledExtensions.value[ext.name] !== extensionStore.isExtensionEnabled(ext.name) + ); + }); + const hasChanges = computed(() => { + return changedExtensions.value.length > 0; + }); + const updateExtensionStatus = /* @__PURE__ */ __name(() => { + const editingDisabledExtensionNames = Object.entries( + editingEnabledExtensions.value + ).filter(([_, enabled]) => !enabled).map(([name]) => name); + settingStore.set("Comfy.Extension.Disabled", [ + ...extensionStore.inactiveDisabledExtensionNames, + ...editingDisabledExtensionNames + ]); + }, "updateExtensionStatus"); + const applyChanges = /* @__PURE__ */ __name(() => { + window.location.reload(); + }, "applyChanges"); + return (_ctx, _cache) => { + return openBlock(), createElementBlock("div", _hoisted_1, [ + createVNode(unref(script$2), { + value: unref(extensionStore).extensions, + stripedRows: "", + size: "small" + }, { + default: withCtx(() => [ + createVNode(unref(script), { + field: "name", + header: _ctx.$t("extensionName"), + sortable: "" + }, null, 8, ["header"]), + createVNode(unref(script), { pt: { + bodyCell: "flex items-center justify-end" + } }, { + body: withCtx((slotProps) => [ + createVNode(unref(script$1), { + modelValue: editingEnabledExtensions.value[slotProps.data.name], + "onUpdate:modelValue": /* @__PURE__ */ __name(($event) => editingEnabledExtensions.value[slotProps.data.name] = $event, "onUpdate:modelValue"), + onChange: updateExtensionStatus + }, null, 8, ["modelValue", "onUpdate:modelValue"]) + ]), + _: 1 + }) + ]), + _: 1 + }, 8, ["value"]), + createBaseVNode("div", _hoisted_2, [ + hasChanges.value ? (openBlock(), createBlock(unref(script$3), { + key: 0, + severity: "info" + }, { + default: withCtx(() => [ + createBaseVNode("ul", null, [ + (openBlock(true), createElementBlock(Fragment, null, renderList(changedExtensions.value, (ext) => { + return openBlock(), createElementBlock("li", { + key: ext.name + }, [ + createBaseVNode("span", null, toDisplayString(unref(extensionStore).isExtensionEnabled(ext.name) ? "[-]" : "[+]"), 1), + createTextVNode(" " + toDisplayString(ext.name), 1) + ]); + }), 128)) + ]) + ]), + _: 1 + })) : createCommentVNode("", true), + createVNode(unref(script$4), { + label: _ctx.$t("reloadToApplyChanges"), + icon: "pi pi-refresh", + onClick: applyChanges, + disabled: !hasChanges.value, + text: "", + fluid: "", + severity: "danger" + }, null, 8, ["label", "disabled"]) + ]) + ]); + }; + } +}); +export { + _sfc_main as default +}; +//# sourceMappingURL=ExtensionPanel-DZLYjWBj.js.map diff --git a/web/assets/ExtensionPanel-DZLYjWBj.js.map b/web/assets/ExtensionPanel-DZLYjWBj.js.map new file mode 100644 index 00000000..eabe9cba --- /dev/null +++ b/web/assets/ExtensionPanel-DZLYjWBj.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ExtensionPanel-DZLYjWBj.js","sources":["../../src/components/dialog/content/setting/ExtensionPanel.vue"],"sourcesContent":["\n\n\n"],"names":[],"mappings":";;;;;;;;;;AAmDA,UAAM,iBAAiB;AACvB,UAAM,eAAe;AAEf,UAAA,2BAA2B,IAA6B,CAAA,CAAE;AAEhE,cAAU,MAAM;AACC,qBAAA,WAAW,QAAQ,CAAC,QAAQ;AACzC,iCAAyB,MAAM,IAAI,IAAI,IACrC,eAAe,mBAAmB,IAAI,IAAI;AAAA,MAAA,CAC7C;AAAA,IAAA,CACF;AAEK,UAAA,oBAAoB,SAAS,MAAM;AACvC,aAAO,eAAe,WAAW;AAAA,QAC/B,CAAC,QACC,yBAAyB,MAAM,IAAI,IAAI,MACvC,eAAe,mBAAmB,IAAI,IAAI;AAAA,MAAA;AAAA,IAC9C,CACD;AAEK,UAAA,aAAa,SAAS,MAAM;AACzB,aAAA,kBAAkB,MAAM,SAAS;AAAA,IAAA,CACzC;AAED,UAAM,wBAAwB,6BAAM;AAClC,YAAM,gCAAgC,OAAO;AAAA,QAC3C,yBAAyB;AAAA,MAExB,EAAA,OAAO,CAAC,CAAC,GAAG,OAAO,MAAM,CAAC,OAAO,EACjC,IAAI,CAAC,CAAC,IAAI,MAAM,IAAI;AAEvB,mBAAa,IAAI,4BAA4B;AAAA,QAC3C,GAAG,eAAe;AAAA,QAClB,GAAG;AAAA,MAAA,CACJ;AAAA,IAAA,GAV2B;AAa9B,UAAM,eAAe,6BAAM;AAEzB,aAAO,SAAS;IAAO,GAFJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"} \ No newline at end of file diff --git a/web/assets/GraphView-BGt8GmeB.css b/web/assets/GraphView-BGt8GmeB.css deleted file mode 100644 index bae07e60..00000000 --- a/web/assets/GraphView-BGt8GmeB.css +++ /dev/null @@ -1,792 +0,0 @@ - -.editable-text[data-v-54da6fc9] { - display: inline; -} -.editable-text input[data-v-54da6fc9] { - width: 100%; - box-sizing: border-box; -} - -.group-title-editor.node-title-editor[data-v-fc3f26e3] { - z-index: 9999; - padding: 0.25rem; -} -[data-v-fc3f26e3] .editable-text { - width: 100%; - height: 100%; -} -[data-v-fc3f26e3] .editable-text input { - width: 100%; - height: 100%; - /* Override the default font size */ - font-size: inherit; -} - -.side-bar-button-icon { - font-size: var(--sidebar-icon-size) !important; -} -.side-bar-button-selected .side-bar-button-icon { - font-size: var(--sidebar-icon-size) !important; - font-weight: bold; -} - -.side-bar-button[data-v-caa3ee9c] { - width: var(--sidebar-width); - height: var(--sidebar-width); - border-radius: 0; -} -.comfyui-body-left .side-bar-button.side-bar-button-selected[data-v-caa3ee9c], -.comfyui-body-left .side-bar-button.side-bar-button-selected[data-v-caa3ee9c]:hover { - border-left: 4px solid var(--p-button-text-primary-color); -} -.comfyui-body-right .side-bar-button.side-bar-button-selected[data-v-caa3ee9c], -.comfyui-body-right .side-bar-button.side-bar-button-selected[data-v-caa3ee9c]:hover { - border-right: 4px solid var(--p-button-text-primary-color); -} - -:root { - --sidebar-width: 64px; - --sidebar-icon-size: 1.5rem; -} -:root .small-sidebar { - --sidebar-width: 40px; - --sidebar-icon-size: 1rem; -} - -.side-tool-bar-container[data-v-4da64512] { - display: flex; - flex-direction: column; - align-items: center; - - pointer-events: auto; - - width: var(--sidebar-width); - height: 100%; - - background-color: var(--comfy-menu-bg); - color: var(--fg-color); -} -.side-tool-bar-end[data-v-4da64512] { - align-self: flex-end; - margin-top: auto; -} -.sidebar-content-container[data-v-4da64512] { - height: 100%; - overflow-y: auto; -} - -.p-splitter-gutter { - pointer-events: auto; -} -.gutter-hidden { - display: none !important; -} - -.side-bar-panel[data-v-b9df3042] { - background-color: var(--bg-color); - pointer-events: auto; -} -.splitter-overlay[data-v-b9df3042] { - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - background-color: transparent; - pointer-events: none; - /* Set it the same as the ComfyUI menu */ - /* Note: Lite-graph DOM widgets have the same z-index as the node id, so - 999 should be sufficient to make sure splitter overlays on node's DOM - widgets */ - z-index: 999; - border: none; -} - -._content[data-v-e7b35fd9] { - - display: flex; - - flex-direction: column -} -._content[data-v-e7b35fd9] > :not([hidden]) ~ :not([hidden]) { - - --tw-space-y-reverse: 0; - - margin-top: calc(0.5rem * calc(1 - var(--tw-space-y-reverse))); - - margin-bottom: calc(0.5rem * var(--tw-space-y-reverse)) -} -._footer[data-v-e7b35fd9] { - - display: flex; - - flex-direction: column; - - align-items: flex-end; - - padding-top: 1rem -} - -[data-v-37f672ab] .highlight { - background-color: var(--p-primary-color); - color: var(--p-primary-contrast-color); - font-weight: bold; - border-radius: 0.25rem; - padding: 0rem 0.125rem; - margin: -0.125rem 0.125rem; -} - -.slot_row[data-v-ff07c900] { - padding: 2px; -} - -/* Original N-Sidebar styles */ -._sb_dot[data-v-ff07c900] { - width: 8px; - height: 8px; - border-radius: 50%; - background-color: grey; -} -.node_header[data-v-ff07c900] { - line-height: 1; - padding: 8px 13px 7px; - margin-bottom: 5px; - font-size: 15px; - text-wrap: nowrap; - overflow: hidden; - display: flex; - align-items: center; -} -.headdot[data-v-ff07c900] { - width: 10px; - height: 10px; - float: inline-start; - margin-right: 8px; -} -.IMAGE[data-v-ff07c900] { - background-color: #64b5f6; -} -.VAE[data-v-ff07c900] { - background-color: #ff6e6e; -} -.LATENT[data-v-ff07c900] { - background-color: #ff9cf9; -} -.MASK[data-v-ff07c900] { - background-color: #81c784; -} -.CONDITIONING[data-v-ff07c900] { - background-color: #ffa931; -} -.CLIP[data-v-ff07c900] { - background-color: #ffd500; -} -.MODEL[data-v-ff07c900] { - background-color: #b39ddb; -} -.CONTROL_NET[data-v-ff07c900] { - background-color: #a5d6a7; -} -._sb_node_preview[data-v-ff07c900] { - background-color: var(--comfy-menu-bg); - font-family: 'Open Sans', sans-serif; - font-size: small; - color: var(--descrip-text); - border: 1px solid var(--descrip-text); - min-width: 300px; - width: -moz-min-content; - width: min-content; - height: -moz-fit-content; - height: fit-content; - z-index: 9999; - border-radius: 12px; - overflow: hidden; - font-size: 12px; - padding-bottom: 10px; -} -._sb_node_preview ._sb_description[data-v-ff07c900] { - margin: 10px; - padding: 6px; - background: var(--border-color); - border-radius: 5px; - font-style: italic; - font-weight: 500; - font-size: 0.9rem; - word-break: break-word; -} -._sb_table[data-v-ff07c900] { - display: grid; - - grid-column-gap: 10px; - /* Spazio tra le colonne */ - width: 100%; - /* Imposta la larghezza della tabella al 100% del contenitore */ -} -._sb_row[data-v-ff07c900] { - display: grid; - grid-template-columns: 10px 1fr 1fr 1fr 10px; - grid-column-gap: 10px; - align-items: center; - padding-left: 9px; - padding-right: 9px; -} -._sb_row_string[data-v-ff07c900] { - grid-template-columns: 10px 1fr 1fr 10fr 1fr; -} -._sb_col[data-v-ff07c900] { - border: 0px solid #000; - display: flex; - align-items: flex-end; - flex-direction: row-reverse; - flex-wrap: nowrap; - align-content: flex-start; - justify-content: flex-end; -} -._sb_inherit[data-v-ff07c900] { - display: inherit; -} -._long_field[data-v-ff07c900] { - background: var(--bg-color); - border: 2px solid var(--border-color); - margin: 5px 5px 0 5px; - border-radius: 10px; - line-height: 1.7; - text-wrap: nowrap; -} -._sb_arrow[data-v-ff07c900] { - color: var(--fg-color); -} -._sb_preview_badge[data-v-ff07c900] { - text-align: center; - background: var(--comfy-input-bg); - font-weight: bold; - color: var(--error-text); -} - -.comfy-vue-node-search-container[data-v-2d409367] { - display: flex; - width: 100%; - min-width: 26rem; - align-items: center; - justify-content: center; -} -.comfy-vue-node-search-container[data-v-2d409367] * { - pointer-events: auto; -} -.comfy-vue-node-preview-container[data-v-2d409367] { - position: absolute; - left: -350px; - top: 50px; -} -.comfy-vue-node-search-box[data-v-2d409367] { - z-index: 10; - flex-grow: 1; -} -._filter-button[data-v-2d409367] { - z-index: 10; -} -._dialog[data-v-2d409367] { - min-width: 26rem; -} - -.invisible-dialog-root { - width: 60%; - min-width: 24rem; - max-width: 48rem; - border: 0 !important; - background-color: transparent !important; - margin-top: 25vh; - margin-left: 400px; -} -@media all and (max-width: 768px) { -.invisible-dialog-root { - margin-left: 0px; -} -} -.node-search-box-dialog-mask { - align-items: flex-start !important; -} - -.node-tooltip[data-v-0a4402f9] { - background: var(--comfy-input-bg); - border-radius: 5px; - box-shadow: 0 0 5px rgba(0, 0, 0, 0.4); - color: var(--input-text); - font-family: sans-serif; - left: 0; - max-width: 30vw; - padding: 4px 8px; - position: absolute; - top: 0; - transform: translate(5px, calc(-100% - 5px)); - white-space: pre-wrap; - z-index: 99999; -} - -.p-buttongroup-vertical[data-v-ce8bd6ac] { - display: flex; - flex-direction: column; - border-radius: var(--p-button-border-radius); - overflow: hidden; - border: 1px solid var(--p-panel-border-color); -} -.p-buttongroup-vertical .p-button[data-v-ce8bd6ac] { - margin: 0; - border-radius: 0; -} - -.comfy-image-wrap[data-v-9bc23daf] { - display: contents; -} -.comfy-image-blur[data-v-9bc23daf] { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - -o-object-fit: cover; - object-fit: cover; -} -.comfy-image-main[data-v-9bc23daf] { - width: 100%; - height: 100%; - -o-object-fit: cover; - object-fit: cover; - -o-object-position: center; - object-position: center; - z-index: 1; -} -.contain .comfy-image-wrap[data-v-9bc23daf] { - position: relative; - width: 100%; - height: 100%; -} -.contain .comfy-image-main[data-v-9bc23daf] { - -o-object-fit: contain; - object-fit: contain; - -webkit-backdrop-filter: blur(10px); - backdrop-filter: blur(10px); - position: absolute; -} -.broken-image-placeholder[data-v-9bc23daf] { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - width: 100%; - height: 100%; - margin: 2rem; -} -.broken-image-placeholder i[data-v-9bc23daf] { - font-size: 3rem; - margin-bottom: 0.5rem; -} - -.result-container[data-v-d9c060ae] { - width: 100%; - height: 100%; - aspect-ratio: 1 / 1; - overflow: hidden; - position: relative; - display: flex; - justify-content: center; - align-items: center; -} -.image-preview-mask[data-v-d9c060ae] { - position: absolute; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); - display: flex; - align-items: center; - justify-content: center; - opacity: 0; - transition: opacity 0.3s ease; - z-index: 1; -} -.result-container:hover .image-preview-mask[data-v-d9c060ae] { - opacity: 1; -} - -.task-result-preview[data-v-d4c8a1fe] { - aspect-ratio: 1 / 1; - overflow: hidden; - display: flex; - justify-content: center; - align-items: center; - width: 100%; - height: 100%; -} -.task-result-preview i[data-v-d4c8a1fe], -.task-result-preview span[data-v-d4c8a1fe] { - font-size: 2rem; -} -.task-item[data-v-d4c8a1fe] { - display: flex; - flex-direction: column; - border-radius: 4px; - overflow: hidden; - position: relative; -} -.task-item-details[data-v-d4c8a1fe] { - position: absolute; - bottom: 0; - padding: 0.6rem; - display: flex; - justify-content: space-between; - align-items: center; - width: 100%; - z-index: 1; -} -.task-node-link[data-v-d4c8a1fe] { - padding: 2px; -} - -/* In dark mode, transparent background color for tags is not ideal for tags that -are floating on top of images. */ -.tag-wrapper[data-v-d4c8a1fe] { - background-color: var(--p-primary-contrast-color); - border-radius: 6px; - display: inline-flex; -} -.node-name-tag[data-v-d4c8a1fe] { - word-break: break-all; -} -.status-tag-group[data-v-d4c8a1fe] { - display: flex; - flex-direction: column; -} -.progress-preview-img[data-v-d4c8a1fe] { - width: 100%; - height: 100%; - -o-object-fit: cover; - object-fit: cover; - -o-object-position: center; - object-position: center; -} - -/* PrimeVue's galleria teleports the fullscreen gallery out of subtree so we -cannot use scoped style here. */ -img.galleria-image { - max-width: 100vw; - max-height: 100vh; - -o-object-fit: contain; - object-fit: contain; -} -.p-galleria-close-button { - /* Set z-index so the close button doesn't get hidden behind the image when image is large */ - z-index: 1; -} - -.comfy-vue-side-bar-container[data-v-1b0a8fe3] { - display: flex; - flex-direction: column; - height: 100%; - overflow: hidden; -} -.comfy-vue-side-bar-header[data-v-1b0a8fe3] { - flex-shrink: 0; - border-left: none; - border-right: none; - border-top: none; - border-radius: 0; - padding: 0.25rem 1rem; - min-height: 2.5rem; -} -.comfy-vue-side-bar-header-span[data-v-1b0a8fe3] { - font-size: small; -} -.comfy-vue-side-bar-body[data-v-1b0a8fe3] { - flex-grow: 1; - overflow: auto; - scrollbar-width: thin; - scrollbar-color: transparent transparent; -} -.comfy-vue-side-bar-body[data-v-1b0a8fe3]::-webkit-scrollbar { - width: 1px; -} -.comfy-vue-side-bar-body[data-v-1b0a8fe3]::-webkit-scrollbar-thumb { - background-color: transparent; -} - -.scroll-container[data-v-08fa89b1] { - height: 100%; - overflow-y: auto; -} -.queue-grid[data-v-08fa89b1] { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); - padding: 0.5rem; - gap: 0.5rem; -} - -.tree-node[data-v-633e27ab] { - width: 100%; - display: flex; - align-items: center; - justify-content: space-between; -} -.leaf-count-badge[data-v-633e27ab] { - margin-left: 0.5rem; -} -.node-content[data-v-633e27ab] { - display: flex; - align-items: center; - flex-grow: 1; -} -.leaf-label[data-v-633e27ab] { - margin-left: 0.5rem; -} -[data-v-633e27ab] .editable-text span { - word-break: break-all; -} - -[data-v-bd7bae90] .tree-explorer-node-label { - width: 100%; - display: flex; - align-items: center; - margin-left: var(--p-tree-node-gap); - flex-grow: 1; -} - -/* - * The following styles are necessary to avoid layout shift when dragging nodes over folders. - * By setting the position to relative on the parent and using an absolutely positioned pseudo-element, - * we can create a visual indicator for the drop target without affecting the layout of other elements. - */ -[data-v-bd7bae90] .p-tree-node-content:has(.tree-folder) { - position: relative; -} -[data-v-bd7bae90] .p-tree-node-content:has(.tree-folder.can-drop)::after { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - border: 1px solid var(--p-content-color); - pointer-events: none; -} - -.node-lib-node-container[data-v-90dfee08] { - height: 100%; - width: 100% -} - -.p-selectbutton .p-button[data-v-91077f2a] { - padding: 0.5rem; -} -.p-selectbutton .p-button .pi[data-v-91077f2a] { - font-size: 1.5rem; -} -.field[data-v-91077f2a] { - display: flex; - flex-direction: column; - gap: 0.5rem; -} -.color-picker-container[data-v-91077f2a] { - display: flex; - align-items: center; - gap: 0.5rem; -} - -.node-lib-filter-popup { - margin-left: -13px; -} - -[data-v-f6a7371a] .comfy-vue-side-bar-body { - background: var(--p-tree-background); -} -[data-v-f6a7371a] .node-lib-bookmark-tree-explorer { - padding-bottom: 2px; -} -[data-v-f6a7371a] .p-divider { - margin: var(--comfy-tree-explorer-item-padding) 0px; -} - -.model_preview[data-v-32e6c4d9] { - background-color: var(--comfy-menu-bg); - font-family: 'Open Sans', sans-serif; - color: var(--descrip-text); - border: 1px solid var(--descrip-text); - min-width: 300px; - max-width: 500px; - width: -moz-fit-content; - width: fit-content; - height: -moz-fit-content; - height: fit-content; - z-index: 9999; - border-radius: 12px; - overflow: hidden; - font-size: 12px; - padding: 10px; -} -.model_preview_image[data-v-32e6c4d9] { - margin: auto; - width: -moz-fit-content; - width: fit-content; -} -.model_preview_image img[data-v-32e6c4d9] { - max-width: 100%; - max-height: 150px; - -o-object-fit: contain; - object-fit: contain; -} -.model_preview_title[data-v-32e6c4d9] { - font-weight: bold; - text-align: center; - font-size: 14px; -} -.model_preview_top_container[data-v-32e6c4d9] { - text-align: center; - line-height: 0.5; -} -.model_preview_filename[data-v-32e6c4d9], -.model_preview_author[data-v-32e6c4d9], -.model_preview_architecture[data-v-32e6c4d9] { - display: inline-block; - text-align: center; - margin: 5px; - font-size: 10px; -} -.model_preview_prefix[data-v-32e6c4d9] { - font-weight: bold; -} - -.model-lib-model-icon-container[data-v-70b69131] { - display: inline-block; - position: relative; - left: 0; - height: 1.5rem; - vertical-align: top; - width: 0px; -} -.model-lib-model-icon[data-v-70b69131] { - background-size: cover; - background-position: center; - display: inline-block; - position: relative; - left: -2.5rem; - height: 2rem; - width: 2rem; - vertical-align: top; -} - -.pi-fake-spacer { - height: 1px; - width: 16px; -} - -[data-v-74b01bce] .comfy-vue-side-bar-body { - background: var(--p-tree-background); -} - -[data-v-d2d58252] .comfy-vue-side-bar-body { - background: var(--p-tree-background); -} - -[data-v-84e785b8] .p-togglebutton::before { - display: none -} -[data-v-84e785b8] .p-togglebutton { - position: relative; - flex-shrink: 0; - border-radius: 0px; - background-color: transparent; - padding-left: 0.5rem; - padding-right: 0.5rem -} -[data-v-84e785b8] .p-togglebutton.p-togglebutton-checked { - border-bottom-width: 2px; - border-bottom-color: var(--p-button-text-primary-color) -} -[data-v-84e785b8] .p-togglebutton-checked .close-button,[data-v-84e785b8] .p-togglebutton:hover .close-button { - visibility: visible -} -.status-indicator[data-v-84e785b8] { - position: absolute; - font-weight: 700; - font-size: 1.5rem; - top: 50%; - left: 50%; - transform: translate(-50%, -50%) -} -[data-v-84e785b8] .p-togglebutton:hover .status-indicator { - display: none -} -[data-v-84e785b8] .p-togglebutton .close-button { - visibility: hidden -} - -.top-menubar[data-v-2ec1b620] .p-menubar-item-link svg { - display: none; -} -[data-v-2ec1b620] .p-menubar-submenu.dropdown-direction-up { - top: auto; - bottom: 100%; - flex-direction: column-reverse; -} -.keybinding-tag[data-v-2ec1b620] { - background: var(--p-content-hover-background); - border-color: var(--p-content-border-color); - border-style: solid; -} - -[data-v-713442be] .p-inputtext { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} - -.comfyui-queue-button[data-v-fcd3efcd] .p-splitbutton-dropdown { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -.actionbar[data-v-bc6c78dd] { - pointer-events: all; - position: fixed; - z-index: 1000; -} -.actionbar.is-docked[data-v-bc6c78dd] { - position: static; - border-style: none; - background-color: transparent; - padding: 0px; -} -.actionbar.is-dragging[data-v-bc6c78dd] { - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; -} -[data-v-bc6c78dd] .p-panel-content { - padding: 0.25rem; -} -[data-v-bc6c78dd] .p-panel-header { - display: none; -} - -.comfyui-menu[data-v-b13fdc92] { - width: 100vw; - background: var(--comfy-menu-bg); - color: var(--fg-color); - font-family: Arial, Helvetica, sans-serif; - font-size: 0.8em; - box-sizing: border-box; - z-index: 1000; - order: 0; - grid-column: 1/-1; - max-height: 90vh; -} -.comfyui-menu.dropzone[data-v-b13fdc92] { - background: var(--p-highlight-background); -} -.comfyui-menu.dropzone-active[data-v-b13fdc92] { - background: var(--p-highlight-background-focus); -} -.comfyui-logo[data-v-b13fdc92] { - font-size: 1.2em; - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; - cursor: default; -} diff --git a/web/assets/GraphView-Bx1-rDWO.css b/web/assets/GraphView-Bx1-rDWO.css new file mode 100644 index 00000000..93521667 --- /dev/null +++ b/web/assets/GraphView-Bx1-rDWO.css @@ -0,0 +1,278 @@ + +.group-title-editor.node-title-editor[data-v-fc3f26e3] { + z-index: 9999; + padding: 0.25rem; +} +[data-v-fc3f26e3] .editable-text { + width: 100%; + height: 100%; +} +[data-v-fc3f26e3] .editable-text input { + width: 100%; + height: 100%; + /* Override the default font size */ + font-size: inherit; +} + +.side-bar-button-icon { + font-size: var(--sidebar-icon-size) !important; +} +.side-bar-button-selected .side-bar-button-icon { + font-size: var(--sidebar-icon-size) !important; + font-weight: bold; +} + +.side-bar-button[data-v-caa3ee9c] { + width: var(--sidebar-width); + height: var(--sidebar-width); + border-radius: 0; +} +.comfyui-body-left .side-bar-button.side-bar-button-selected[data-v-caa3ee9c], +.comfyui-body-left .side-bar-button.side-bar-button-selected[data-v-caa3ee9c]:hover { + border-left: 4px solid var(--p-button-text-primary-color); +} +.comfyui-body-right .side-bar-button.side-bar-button-selected[data-v-caa3ee9c], +.comfyui-body-right .side-bar-button.side-bar-button-selected[data-v-caa3ee9c]:hover { + border-right: 4px solid var(--p-button-text-primary-color); +} + +:root { + --sidebar-width: 64px; + --sidebar-icon-size: 1.5rem; +} +:root .small-sidebar { + --sidebar-width: 40px; + --sidebar-icon-size: 1rem; +} + +.side-tool-bar-container[data-v-b6bfc188] { + display: flex; + flex-direction: column; + align-items: center; + + pointer-events: auto; + + width: var(--sidebar-width); + height: 100%; + + background-color: var(--comfy-menu-bg); + color: var(--fg-color); +} +.side-tool-bar-end[data-v-b6bfc188] { + align-self: flex-end; + margin-top: auto; +} + +.p-splitter-gutter { + pointer-events: auto; +} +.gutter-hidden { + display: none !important; +} + +.side-bar-panel[data-v-b9df3042] { + background-color: var(--bg-color); + pointer-events: auto; +} +.splitter-overlay[data-v-b9df3042] { + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + background-color: transparent; + pointer-events: none; + /* Set it the same as the ComfyUI menu */ + /* Note: Lite-graph DOM widgets have the same z-index as the node id, so + 999 should be sufficient to make sure splitter overlays on node's DOM + widgets */ + z-index: 999; + border: none; +} + +[data-v-37f672ab] .highlight { + background-color: var(--p-primary-color); + color: var(--p-primary-contrast-color); + font-weight: bold; + border-radius: 0.25rem; + padding: 0rem 0.125rem; + margin: -0.125rem 0.125rem; +} + +.comfy-vue-node-search-container[data-v-2d409367] { + display: flex; + width: 100%; + min-width: 26rem; + align-items: center; + justify-content: center; +} +.comfy-vue-node-search-container[data-v-2d409367] * { + pointer-events: auto; +} +.comfy-vue-node-preview-container[data-v-2d409367] { + position: absolute; + left: -350px; + top: 50px; +} +.comfy-vue-node-search-box[data-v-2d409367] { + z-index: 10; + flex-grow: 1; +} +._filter-button[data-v-2d409367] { + z-index: 10; +} +._dialog[data-v-2d409367] { + min-width: 26rem; +} + +.invisible-dialog-root { + width: 60%; + min-width: 24rem; + max-width: 48rem; + border: 0 !important; + background-color: transparent !important; + margin-top: 25vh; + margin-left: 400px; +} +@media all and (max-width: 768px) { +.invisible-dialog-root { + margin-left: 0px; +} +} +.node-search-box-dialog-mask { + align-items: flex-start !important; +} + +.node-tooltip[data-v-79ec8c53] { + background: var(--comfy-input-bg); + border-radius: 5px; + box-shadow: 0 0 5px rgba(0, 0, 0, 0.4); + color: var(--input-text); + font-family: sans-serif; + left: 0; + max-width: 30vw; + padding: 4px 8px; + position: absolute; + top: 0; + transform: translate(5px, calc(-100% - 5px)); + white-space: pre-wrap; + z-index: 99999; +} + +.p-buttongroup-vertical[data-v-444d3768] { + display: flex; + flex-direction: column; + border-radius: var(--p-button-border-radius); + overflow: hidden; + border: 1px solid var(--p-panel-border-color); +} +.p-buttongroup-vertical .p-button[data-v-444d3768] { + margin: 0; + border-radius: 0; +} + +[data-v-84e785b8] .p-togglebutton::before { + display: none +} +[data-v-84e785b8] .p-togglebutton { + position: relative; + flex-shrink: 0; + border-radius: 0px; + background-color: transparent; + padding-left: 0.5rem; + padding-right: 0.5rem +} +[data-v-84e785b8] .p-togglebutton.p-togglebutton-checked { + border-bottom-width: 2px; + border-bottom-color: var(--p-button-text-primary-color) +} +[data-v-84e785b8] .p-togglebutton-checked .close-button,[data-v-84e785b8] .p-togglebutton:hover .close-button { + visibility: visible +} +.status-indicator[data-v-84e785b8] { + position: absolute; + font-weight: 700; + font-size: 1.5rem; + top: 50%; + left: 50%; + transform: translate(-50%, -50%) +} +[data-v-84e785b8] .p-togglebutton:hover .status-indicator { + display: none +} +[data-v-84e785b8] .p-togglebutton .close-button { + visibility: hidden +} + +.top-menubar[data-v-9646ca0a] .p-menubar-item-link svg { + display: none; +} +[data-v-9646ca0a] .p-menubar-submenu.dropdown-direction-up { + top: auto; + bottom: 100%; + flex-direction: column-reverse; +} +.keybinding-tag[data-v-9646ca0a] { + background: var(--p-content-hover-background); + border-color: var(--p-content-border-color); + border-style: solid; +} + +[data-v-713442be] .p-inputtext { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} + +.comfyui-queue-button[data-v-2b80bf74] .p-splitbutton-dropdown { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.actionbar[data-v-2e54db00] { + pointer-events: all; + position: fixed; + z-index: 1000; +} +.actionbar.is-docked[data-v-2e54db00] { + position: static; + border-style: none; + background-color: transparent; + padding: 0px; +} +.actionbar.is-dragging[data-v-2e54db00] { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; +} +[data-v-2e54db00] .p-panel-content { + padding: 0.25rem; +} +[data-v-2e54db00] .p-panel-header { + display: none; +} + +.comfyui-menu[data-v-b13fdc92] { + width: 100vw; + background: var(--comfy-menu-bg); + color: var(--fg-color); + font-family: Arial, Helvetica, sans-serif; + font-size: 0.8em; + box-sizing: border-box; + z-index: 1000; + order: 0; + grid-column: 1/-1; + max-height: 90vh; +} +.comfyui-menu.dropzone[data-v-b13fdc92] { + background: var(--p-highlight-background); +} +.comfyui-menu.dropzone-active[data-v-b13fdc92] { + background: var(--p-highlight-background-focus); +} +.comfyui-logo[data-v-b13fdc92] { + font-size: 1.2em; + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + cursor: default; +} diff --git a/web/assets/GraphView-CVV2XJjS.js b/web/assets/GraphView-CVV2XJjS.js deleted file mode 100644 index 1d43b2f6..00000000 --- a/web/assets/GraphView-CVV2XJjS.js +++ /dev/null @@ -1,17465 +0,0 @@ -var __defProp = Object.defineProperty; -var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); -import { d as defineComponent, r as ref, w as watch, n as nextTick, o as openBlock, c as createElementBlock, t as toDisplayString, a as withDirectives, b as createBlock, e as withKeys, f as withModifiers, u as unref, s as script$m, p as pushScopeId, g as popScopeId, _ as _export_sfc, h as useSettingStore, i as useTitleEditorStore, j as useCanvasStore, L as LGraphGroup, k as app, l as LGraphNode, m as onMounted, q as onUnmounted, v as createVNode, x as normalizeStyle, y as createCommentVNode, z as LiteGraph, B as BaseStyle, A as script$n, C as resolveComponent, D as mergeProps, E as renderSlot, F as computed, G as resolveDirective, H as withCtx, I as createBaseVNode, J as normalizeClass, K as script$o, M as useDialogStore, S as SettingDialogHeader, N as SettingDialogContent, O as useWorkspaceStore, P as onBeforeUnmount, Q as Fragment, R as renderList, T as Teleport, U as resolveDynamicComponent, V as script$p, W as getWidth, X as getHeight, Y as getOuterWidth, Z as getOuterHeight, $ as getVNodeProp, a0 as isArray, a1 as vShow, a2 as isNotEmpty, a3 as UniqueComponentId, a4 as ZIndex, a5 as resolveFieldData, a6 as focus, a7 as OverlayEventBus, a8 as isEmpty, a9 as addStyle, aa as relativePosition, ab as absolutePosition, ac as ConnectedOverlayScrollHandler, ad as isTouchDevice, ae as equals, af as findLastIndex, ag as findSingle, ah as script$q, ai as script$r, aj as script$s, ak as script$t, al as script$u, am as Ripple, an as Transition, ao as createSlots, ap as createTextVNode, aq as useNodeDefStore, ar as script$v, as as defineStore, at as createDummyFolderNodeDef, au as _, av as buildNodeDefTree, aw as useNodeFrequencyStore, ax as highlightQuery, ay as script$w, az as formatNumberWithSuffix, aA as NodeSourceType, aB as ComfyNodeDefImpl, aC as useI18n, aD as script$x, aE as SearchFilterChip, aF as watchEffect, aG as toRaw, aH as LinkReleaseTriggerAction, aI as commonjsGlobal, aJ as getDefaultExportFromCjs, aK as markRaw, aL as useCommandStore, aM as LGraph, aN as LLink, aO as DragAndScale, aP as LGraphCanvas, aQ as ContextMenu, aR as LGraphBadge, aS as ComfyModelDef, aT as useKeybindingStore, aU as ConfirmationEventBus, aV as getOffset, aW as $dt, aX as addClass, aY as FocusTrap, aZ as resolve, a_ as nestedPosition, a$ as script$y, b0 as isPrintableCharacter, b1 as getHiddenElementOuterWidth, b2 as getHiddenElementOuterHeight, b3 as getViewport, b4 as api, b5 as TaskItemDisplayStatus, b6 as script$z, b7 as find, b8 as getAttribute, b9 as script$A, ba as script$B, bb as removeClass, bc as setAttribute, bd as localeComparator, be as sort, bf as script$C, bg as unblockBodyScroll, bh as blockBodyScroll, bi as useConfirm, bj as useToast, bk as useQueueStore, bl as useInfiniteScroll, bm as useResizeObserver, bn as script$D, bo as NoResultsPlaceholder, bp as isClient, bq as script$E, br as script$F, bs as script$G, bt as script$H, bu as script$I, bv as script$J, bw as inject, bx as useErrorHandling, by as mergeModels, bz as useModel, bA as provide, bB as script$K, bC as findNodeByKey, bD as sortedTree, bE as SearchBox, bF as useModelStore, bG as buildTree, bH as toRef, bI as script$L, bJ as script$M, bK as script$N, bL as normalizeProps, bM as ToastEventBus, bN as TransitionGroup, bO as useToastStore, bP as useExecutionStore, bQ as useWorkflowStore, bR as useTitle, bS as useWorkflowBookmarkStore, bT as script$O, bU as script$P, bV as guardReactiveProps, bW as useMenuItemStore, bX as script$Q, bY as useQueueSettingsStore, bZ as storeToRefs, b_ as isRef, b$ as script$R, c0 as useQueuePendingTaskCountStore, c1 as useLocalStorage, c2 as useDraggable, c3 as watchDebounced, c4 as useEventListener, c5 as useElementBounding, c6 as lodashExports, c7 as useEventBus, c8 as i18n } from "./index-DGAbdBYF.js"; -import { g as getColorPalette, d as defaultColorPalette } from "./colorPalette-D5oi2-2V.js"; -const _withScopeId$l = /* @__PURE__ */ __name((n) => (pushScopeId("data-v-54da6fc9"), n = n(), popScopeId(), n), "_withScopeId$l"); -const _hoisted_1$F = { class: "editable-text" }; -const _hoisted_2$v = { key: 0 }; -const _sfc_main$I = /* @__PURE__ */ defineComponent({ - __name: "EditableText", - props: { - modelValue: {}, - isEditing: { type: Boolean, default: false } - }, - emits: ["update:modelValue", "edit"], - setup(__props, { emit: __emit }) { - const props = __props; - const emit = __emit; - const inputValue2 = ref(props.modelValue); - const isEditingFinished = ref(false); - const inputRef = ref(null); - const finishEditing = /* @__PURE__ */ __name(() => { - if (isEditingFinished.value) { - return; - } - isEditingFinished.value = true; - emit("edit", inputValue2.value); - }, "finishEditing"); - watch( - () => props.isEditing, - (newVal) => { - if (newVal) { - inputValue2.value = props.modelValue; - isEditingFinished.value = false; - nextTick(() => { - if (!inputRef.value) return; - const fileName = inputValue2.value.includes(".") ? inputValue2.value.split(".").slice(0, -1).join(".") : inputValue2.value; - const start2 = 0; - const end = fileName.length; - const inputElement = inputRef.value.$el; - inputElement.setSelectionRange?.(start2, end); - }); - } - }, - { immediate: true } - ); - const vFocus = { - mounted: /* @__PURE__ */ __name((el) => el.focus(), "mounted") - }; - return (_ctx, _cache) => { - return openBlock(), createElementBlock("div", _hoisted_1$F, [ - !props.isEditing ? (openBlock(), createElementBlock("span", _hoisted_2$v, toDisplayString(_ctx.modelValue), 1)) : withDirectives((openBlock(), createBlock(unref(script$m), { - key: 1, - type: "text", - size: "small", - fluid: "", - modelValue: inputValue2.value, - "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => inputValue2.value = $event), - ref_key: "inputRef", - ref: inputRef, - onKeyup: withKeys(finishEditing, ["enter"]), - onClick: _cache[1] || (_cache[1] = withModifiers(() => { - }, ["stop"])), - pt: { - root: { - onBlur: finishEditing - } - } - }, null, 8, ["modelValue", "pt"])), [ - [vFocus] - ]) - ]); - }; - } -}); -const EditableText = /* @__PURE__ */ _export_sfc(_sfc_main$I, [["__scopeId", "data-v-54da6fc9"]]); -const _sfc_main$H = /* @__PURE__ */ defineComponent({ - __name: "TitleEditor", - setup(__props) { - const settingStore = useSettingStore(); - const showInput = ref(false); - const editedTitle = ref(""); - const inputStyle = ref({ - position: "fixed", - left: "0px", - top: "0px", - width: "200px", - height: "20px", - fontSize: "12px" - }); - const titleEditorStore = useTitleEditorStore(); - const canvasStore = useCanvasStore(); - const previousCanvasDraggable = ref(true); - const onEdit = /* @__PURE__ */ __name((newValue) => { - if (titleEditorStore.titleEditorTarget && newValue.trim() !== "") { - titleEditorStore.titleEditorTarget.title = newValue.trim(); - app.graph.setDirtyCanvas(true, true); - } - showInput.value = false; - titleEditorStore.titleEditorTarget = null; - canvasStore.canvas.allow_dragcanvas = previousCanvasDraggable.value; - }, "onEdit"); - watch( - () => titleEditorStore.titleEditorTarget, - (target) => { - if (target === null) { - return; - } - editedTitle.value = target.title; - showInput.value = true; - previousCanvasDraggable.value = canvasStore.canvas.allow_dragcanvas; - canvasStore.canvas.allow_dragcanvas = false; - if (target instanceof LGraphGroup) { - const group = target; - const [x, y] = group.pos; - const [w, h] = group.size; - const [left, top] = app.canvasPosToClientPos([x, y]); - inputStyle.value.left = `${left}px`; - inputStyle.value.top = `${top}px`; - const width = w * app.canvas.ds.scale; - const height = group.titleHeight * app.canvas.ds.scale; - inputStyle.value.width = `${width}px`; - inputStyle.value.height = `${height}px`; - const fontSize = group.font_size * app.canvas.ds.scale; - inputStyle.value.fontSize = `${fontSize}px`; - } else if (target instanceof LGraphNode) { - const node2 = target; - const [x, y] = node2.getBounding(); - const canvasWidth = node2.width; - const canvasHeight = LiteGraph.NODE_TITLE_HEIGHT; - const [left, top] = app.canvasPosToClientPos([x, y]); - inputStyle.value.left = `${left}px`; - inputStyle.value.top = `${top}px`; - const width = canvasWidth * app.canvas.ds.scale; - const height = canvasHeight * app.canvas.ds.scale; - inputStyle.value.width = `${width}px`; - inputStyle.value.height = `${height}px`; - const fontSize = 12 * app.canvas.ds.scale; - inputStyle.value.fontSize = `${fontSize}px`; - } - } - ); - const canvasEventHandler = /* @__PURE__ */ __name((event) => { - if (!settingStore.get("Comfy.Group.DoubleClickTitleToEdit")) { - return; - } - if (event.detail.subType === "group-double-click") { - const group = event.detail.group; - const [x, y] = group.pos; - const e = event.detail.originalEvent; - const relativeY = e.canvasY - y; - if (relativeY > group.titleHeight) { - return; - } - titleEditorStore.titleEditorTarget = group; - } - }, "canvasEventHandler"); - const extension = { - name: "Comfy.NodeTitleEditor", - nodeCreated(node2) { - const originalCallback = node2.onNodeTitleDblClick; - node2.onNodeTitleDblClick = function(e, ...args) { - if (!settingStore.get("Comfy.Node.DoubleClickTitleToEdit")) { - return; - } - titleEditorStore.titleEditorTarget = this; - if (typeof originalCallback === "function") { - originalCallback.call(this, e, ...args); - } - }; - } - }; - onMounted(() => { - document.addEventListener("litegraph:canvas", canvasEventHandler); - app.registerExtension(extension); - }); - onUnmounted(() => { - document.removeEventListener("litegraph:canvas", canvasEventHandler); - }); - return (_ctx, _cache) => { - return showInput.value ? (openBlock(), createElementBlock("div", { - key: 0, - class: "group-title-editor node-title-editor", - style: normalizeStyle(inputStyle.value) - }, [ - createVNode(EditableText, { - isEditing: showInput.value, - modelValue: editedTitle.value, - onEdit - }, null, 8, ["isEditing", "modelValue"]) - ], 4)) : createCommentVNode("", true); - }; - } -}); -const TitleEditor = /* @__PURE__ */ _export_sfc(_sfc_main$H, [["__scopeId", "data-v-fc3f26e3"]]); -var theme$h = /* @__PURE__ */ __name(function theme(_ref) { - var dt = _ref.dt; - return "\n.p-overlaybadge {\n position: relative;\n}\n\n.p-overlaybadge .p-badge {\n position: absolute;\n top: 0;\n right: 0;\n transform: translate(50%, -50%);\n transform-origin: 100% 0;\n margin: 0;\n outline-width: ".concat(dt("overlaybadge.outline.width"), ";\n outline-style: solid;\n outline-color: ").concat(dt("overlaybadge.outline.color"), ";\n}\n"); -}, "theme"); -var classes$i = { - root: "p-overlaybadge" -}; -var OverlayBadgeStyle = BaseStyle.extend({ - name: "overlaybadge", - theme: theme$h, - classes: classes$i -}); -var script$1$i = { - name: "OverlayBadge", - "extends": script$n, - style: OverlayBadgeStyle, - provide: /* @__PURE__ */ __name(function provide2() { - return { - $pcOverlayBadge: this, - $parentInstance: this - }; - }, "provide") -}; -var script$l = { - name: "OverlayBadge", - "extends": script$1$i, - inheritAttrs: false, - components: { - Badge: script$n - } -}; -function render$m(_ctx, _cache, $props, $setup, $data, $options) { - var _component_Badge = resolveComponent("Badge"); - return openBlock(), createElementBlock("div", mergeProps({ - "class": _ctx.cx("root") - }, _ctx.ptmi("root")), [renderSlot(_ctx.$slots, "default"), createVNode(_component_Badge, mergeProps(_ctx.$props, { - pt: _ctx.ptm("pcBadge") - }), null, 16, ["pt"])], 16); -} -__name(render$m, "render$m"); -script$l.render = render$m; -const _sfc_main$G = /* @__PURE__ */ defineComponent({ - __name: "SidebarIcon", - props: { - icon: String, - selected: Boolean, - tooltip: { - type: String, - default: "" - }, - class: { - type: String, - default: "" - }, - iconBadge: { - type: [String, Function], - default: "" - } - }, - emits: ["click"], - setup(__props, { emit: __emit }) { - const props = __props; - const emit = __emit; - const overlayValue = computed( - () => typeof props.iconBadge === "function" ? props.iconBadge() || "" : props.iconBadge - ); - const shouldShowBadge = computed(() => !!overlayValue.value); - return (_ctx, _cache) => { - const _directive_tooltip = resolveDirective("tooltip"); - return withDirectives((openBlock(), createBlock(unref(script$o), { - class: normalizeClass(props.class), - text: "", - pt: { - root: { - class: `side-bar-button ${props.selected ? "p-button-primary side-bar-button-selected" : "p-button-secondary"}`, - "aria-label": props.tooltip - } - }, - onClick: _cache[0] || (_cache[0] = ($event) => emit("click", $event)) - }, { - icon: withCtx(() => [ - shouldShowBadge.value ? (openBlock(), createBlock(unref(script$l), { - key: 0, - value: overlayValue.value - }, { - default: withCtx(() => [ - createBaseVNode("i", { - class: normalizeClass(props.icon + " side-bar-button-icon") - }, null, 2) - ]), - _: 1 - }, 8, ["value"])) : (openBlock(), createElementBlock("i", { - key: 1, - class: normalizeClass(props.icon + " side-bar-button-icon") - }, null, 2)) - ]), - _: 1 - }, 8, ["class", "pt"])), [ - [_directive_tooltip, { value: props.tooltip, showDelay: 300, hideDelay: 300 }] - ]); - }; - } -}); -const SidebarIcon = /* @__PURE__ */ _export_sfc(_sfc_main$G, [["__scopeId", "data-v-caa3ee9c"]]); -const _sfc_main$F = /* @__PURE__ */ defineComponent({ - __name: "SidebarThemeToggleIcon", - setup(__props) { - const previousDarkTheme = ref("dark"); - const currentTheme = computed(() => useSettingStore().get("Comfy.ColorPalette")); - const isDarkMode = computed(() => currentTheme.value !== "light"); - const icon = computed(() => isDarkMode.value ? "pi pi-moon" : "pi pi-sun"); - const toggleTheme = /* @__PURE__ */ __name(() => { - if (isDarkMode.value) { - previousDarkTheme.value = currentTheme.value; - useSettingStore().set("Comfy.ColorPalette", "light"); - } else { - useSettingStore().set("Comfy.ColorPalette", previousDarkTheme.value); - } - }, "toggleTheme"); - return (_ctx, _cache) => { - return openBlock(), createBlock(SidebarIcon, { - icon: icon.value, - onClick: toggleTheme, - tooltip: _ctx.$t("sideToolbar.themeToggle"), - class: "comfy-vue-theme-toggle" - }, null, 8, ["icon", "tooltip"]); - }; - } -}); -const _sfc_main$E = /* @__PURE__ */ defineComponent({ - __name: "SidebarSettingsToggleIcon", - setup(__props) { - const dialogStore = useDialogStore(); - const showSetting = /* @__PURE__ */ __name(() => { - dialogStore.showDialog({ - headerComponent: SettingDialogHeader, - component: SettingDialogContent - }); - }, "showSetting"); - return (_ctx, _cache) => { - return openBlock(), createBlock(SidebarIcon, { - icon: "pi pi-cog", - class: "comfy-settings-btn", - onClick: showSetting, - tooltip: _ctx.$t("settings") - }, null, 8, ["tooltip"]); - }; - } -}); -const _withScopeId$k = /* @__PURE__ */ __name((n) => (pushScopeId("data-v-4da64512"), n = n(), popScopeId(), n), "_withScopeId$k"); -const _hoisted_1$E = { class: "side-tool-bar-end" }; -const _hoisted_2$u = { - key: 0, - class: "sidebar-content-container" -}; -const _sfc_main$D = /* @__PURE__ */ defineComponent({ - __name: "SideToolbar", - setup(__props) { - const workspaceStore = useWorkspaceStore(); - const settingStore = useSettingStore(); - const teleportTarget = computed( - () => settingStore.get("Comfy.Sidebar.Location") === "left" ? ".comfyui-body-left" : ".comfyui-body-right" - ); - const isSmall = computed( - () => settingStore.get("Comfy.Sidebar.Size") === "small" - ); - const tabs = computed(() => workspaceStore.getSidebarTabs()); - const selectedTab = computed(() => workspaceStore.sidebarTab.activeSidebarTab); - const mountCustomTab = /* @__PURE__ */ __name((tab, el) => { - tab.render(el); - }, "mountCustomTab"); - const onTabClick = /* @__PURE__ */ __name((item4) => { - workspaceStore.sidebarTab.toggleSidebarTab(item4.id); - }, "onTabClick"); - onBeforeUnmount(() => { - tabs.value.forEach((tab) => { - if (tab.type === "custom" && tab.destroy) { - tab.destroy(); - } - }); - }); - return (_ctx, _cache) => { - return openBlock(), createElementBlock(Fragment, null, [ - (openBlock(), createBlock(Teleport, { to: teleportTarget.value }, [ - createBaseVNode("nav", { - class: normalizeClass("side-tool-bar-container" + (isSmall.value ? " small-sidebar" : "")) - }, [ - (openBlock(true), createElementBlock(Fragment, null, renderList(tabs.value, (tab) => { - return openBlock(), createBlock(SidebarIcon, { - key: tab.id, - icon: tab.icon, - iconBadge: tab.iconBadge, - tooltip: tab.tooltip, - selected: tab.id === selectedTab.value?.id, - class: normalizeClass(tab.id + "-tab-button"), - onClick: /* @__PURE__ */ __name(($event) => onTabClick(tab), "onClick") - }, null, 8, ["icon", "iconBadge", "tooltip", "selected", "class", "onClick"]); - }), 128)), - createBaseVNode("div", _hoisted_1$E, [ - createVNode(_sfc_main$F), - createVNode(_sfc_main$E) - ]) - ], 2) - ], 8, ["to"])), - selectedTab.value ? (openBlock(), createElementBlock("div", _hoisted_2$u, [ - selectedTab.value.type === "vue" ? (openBlock(), createBlock(resolveDynamicComponent(selectedTab.value.component), { key: 0 })) : (openBlock(), createElementBlock("div", { - key: 1, - ref: /* @__PURE__ */ __name((el) => { - if (el) - mountCustomTab( - selectedTab.value, - el - ); - }, "ref") - }, null, 512)) - ])) : createCommentVNode("", true) - ], 64); - }; - } -}); -const SideToolbar = /* @__PURE__ */ _export_sfc(_sfc_main$D, [["__scopeId", "data-v-4da64512"]]); -var theme$g = /* @__PURE__ */ __name(function theme2(_ref) { - var dt = _ref.dt; - return "\n.p-splitter {\n display: flex;\n flex-wrap: nowrap;\n border: 1px solid ".concat(dt("splitter.border.color"), ";\n background: ").concat(dt("splitter.background"), ";\n border-radius: ").concat(dt("border.radius.md"), ";\n color: ").concat(dt("splitter.color"), ";\n}\n\n.p-splitter-vertical {\n flex-direction: column;\n}\n\n.p-splitter-gutter {\n flex-grow: 0;\n flex-shrink: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 1;\n background: ").concat(dt("splitter.gutter.background"), ";\n}\n\n.p-splitter-gutter-handle {\n border-radius: ").concat(dt("splitter.handle.border.radius"), ";\n background: ").concat(dt("splitter.handle.background"), ";\n transition: outline-color ").concat(dt("splitter.transition.duration"), ", box-shadow ").concat(dt("splitter.transition.duration"), ";\n outline-color: transparent;\n}\n\n.p-splitter-gutter-handle:focus-visible {\n box-shadow: ").concat(dt("splitter.handle.focus.ring.shadow"), ";\n outline: ").concat(dt("splitter.handle.focus.ring.width"), " ").concat(dt("splitter.handle.focus.ring.style"), " ").concat(dt("splitter.handle.focus.ring.color"), ";\n outline-offset: ").concat(dt("splitter.handle.focus.ring.offset"), ";\n}\n\n.p-splitter-horizontal.p-splitter-resizing {\n cursor: col-resize;\n user-select: none;\n}\n\n.p-splitter-vertical.p-splitter-resizing {\n cursor: row-resize;\n user-select: none;\n}\n\n.p-splitter-horizontal > .p-splitter-gutter > .p-splitter-gutter-handle {\n height: ").concat(dt("splitter.handle.size"), ";\n width: 100%;\n}\n\n.p-splitter-vertical > .p-splitter-gutter > .p-splitter-gutter-handle {\n width: ").concat(dt("splitter.handle.size"), ";\n height: 100%;\n}\n\n.p-splitter-horizontal > .p-splitter-gutter {\n cursor: col-resize;\n}\n\n.p-splitter-vertical > .p-splitter-gutter {\n cursor: row-resize;\n}\n\n.p-splitterpanel {\n flex-grow: 1;\n overflow: hidden;\n}\n\n.p-splitterpanel-nested {\n display: flex;\n}\n\n.p-splitterpanel .p-splitter {\n flex-grow: 1;\n border: 0 none;\n}\n"); -}, "theme"); -var classes$h = { - root: /* @__PURE__ */ __name(function root(_ref2) { - var props = _ref2.props; - return ["p-splitter p-component", "p-splitter-" + props.layout]; - }, "root"), - gutter: "p-splitter-gutter", - gutterHandle: "p-splitter-gutter-handle" -}; -var inlineStyles$4 = { - root: /* @__PURE__ */ __name(function root2(_ref3) { - var props = _ref3.props; - return [{ - display: "flex", - "flex-wrap": "nowrap" - }, props.layout === "vertical" ? { - "flex-direction": "column" - } : ""]; - }, "root") -}; -var SplitterStyle = BaseStyle.extend({ - name: "splitter", - theme: theme$g, - classes: classes$h, - inlineStyles: inlineStyles$4 -}); -var script$1$h = { - name: "BaseSplitter", - "extends": script$p, - props: { - layout: { - type: String, - "default": "horizontal" - }, - gutterSize: { - type: Number, - "default": 4 - }, - stateKey: { - type: String, - "default": null - }, - stateStorage: { - type: String, - "default": "session" - }, - step: { - type: Number, - "default": 5 - } - }, - style: SplitterStyle, - provide: /* @__PURE__ */ __name(function provide3() { - return { - $pcSplitter: this, - $parentInstance: this - }; - }, "provide") -}; -function _toConsumableArray$7(r) { - return _arrayWithoutHoles$7(r) || _iterableToArray$7(r) || _unsupportedIterableToArray$9(r) || _nonIterableSpread$7(); -} -__name(_toConsumableArray$7, "_toConsumableArray$7"); -function _nonIterableSpread$7() { - throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); -} -__name(_nonIterableSpread$7, "_nonIterableSpread$7"); -function _unsupportedIterableToArray$9(r, a) { - if (r) { - if ("string" == typeof r) return _arrayLikeToArray$9(r, a); - var t = {}.toString.call(r).slice(8, -1); - return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray$9(r, a) : void 0; - } -} -__name(_unsupportedIterableToArray$9, "_unsupportedIterableToArray$9"); -function _iterableToArray$7(r) { - if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); -} -__name(_iterableToArray$7, "_iterableToArray$7"); -function _arrayWithoutHoles$7(r) { - if (Array.isArray(r)) return _arrayLikeToArray$9(r); -} -__name(_arrayWithoutHoles$7, "_arrayWithoutHoles$7"); -function _arrayLikeToArray$9(r, a) { - (null == a || a > r.length) && (a = r.length); - for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; - return n; -} -__name(_arrayLikeToArray$9, "_arrayLikeToArray$9"); -var script$k = { - name: "Splitter", - "extends": script$1$h, - inheritAttrs: false, - emits: ["resizestart", "resizeend", "resize"], - dragging: false, - mouseMoveListener: null, - mouseUpListener: null, - touchMoveListener: null, - touchEndListener: null, - size: null, - gutterElement: null, - startPos: null, - prevPanelElement: null, - nextPanelElement: null, - nextPanelSize: null, - prevPanelSize: null, - panelSizes: null, - prevPanelIndex: null, - timer: null, - data: /* @__PURE__ */ __name(function data() { - return { - prevSize: null - }; - }, "data"), - mounted: /* @__PURE__ */ __name(function mounted() { - var _this = this; - if (this.panels && this.panels.length) { - var initialized = false; - if (this.isStateful()) { - initialized = this.restoreState(); - } - if (!initialized) { - var children = _toConsumableArray$7(this.$el.children).filter(function(child) { - return child.getAttribute("data-pc-name") === "splitterpanel"; - }); - var _panelSizes = []; - this.panels.map(function(panel2, i) { - var panelInitialSize = panel2.props && panel2.props.size ? panel2.props.size : null; - var panelSize = panelInitialSize || 100 / _this.panels.length; - _panelSizes[i] = panelSize; - children[i].style.flexBasis = "calc(" + panelSize + "% - " + (_this.panels.length - 1) * _this.gutterSize + "px)"; - }); - this.panelSizes = _panelSizes; - this.prevSize = parseFloat(_panelSizes[0]).toFixed(4); - } - } - }, "mounted"), - beforeUnmount: /* @__PURE__ */ __name(function beforeUnmount() { - this.clear(); - this.unbindMouseListeners(); - }, "beforeUnmount"), - methods: { - isSplitterPanel: /* @__PURE__ */ __name(function isSplitterPanel(child) { - return child.type.name === "SplitterPanel"; - }, "isSplitterPanel"), - onResizeStart: /* @__PURE__ */ __name(function onResizeStart(event, index2, isKeyDown) { - this.gutterElement = event.currentTarget || event.target.parentElement; - this.size = this.horizontal ? getWidth(this.$el) : getHeight(this.$el); - if (!isKeyDown) { - this.dragging = true; - this.startPos = this.layout === "horizontal" ? event.pageX || event.changedTouches[0].pageX : event.pageY || event.changedTouches[0].pageY; - } - this.prevPanelElement = this.gutterElement.previousElementSibling; - this.nextPanelElement = this.gutterElement.nextElementSibling; - if (isKeyDown) { - this.prevPanelSize = this.horizontal ? getOuterWidth(this.prevPanelElement, true) : getOuterHeight(this.prevPanelElement, true); - this.nextPanelSize = this.horizontal ? getOuterWidth(this.nextPanelElement, true) : getOuterHeight(this.nextPanelElement, true); - } else { - this.prevPanelSize = 100 * (this.horizontal ? getOuterWidth(this.prevPanelElement, true) : getOuterHeight(this.prevPanelElement, true)) / this.size; - this.nextPanelSize = 100 * (this.horizontal ? getOuterWidth(this.nextPanelElement, true) : getOuterHeight(this.nextPanelElement, true)) / this.size; - } - this.prevPanelIndex = index2; - this.$emit("resizestart", { - originalEvent: event, - sizes: this.panelSizes - }); - this.$refs.gutter[index2].setAttribute("data-p-gutter-resizing", true); - this.$el.setAttribute("data-p-resizing", true); - }, "onResizeStart"), - onResize: /* @__PURE__ */ __name(function onResize(event, step2, isKeyDown) { - var newPos, newPrevPanelSize, newNextPanelSize; - if (isKeyDown) { - if (this.horizontal) { - newPrevPanelSize = 100 * (this.prevPanelSize + step2) / this.size; - newNextPanelSize = 100 * (this.nextPanelSize - step2) / this.size; - } else { - newPrevPanelSize = 100 * (this.prevPanelSize - step2) / this.size; - newNextPanelSize = 100 * (this.nextPanelSize + step2) / this.size; - } - } else { - if (this.horizontal) newPos = event.pageX * 100 / this.size - this.startPos * 100 / this.size; - else newPos = event.pageY * 100 / this.size - this.startPos * 100 / this.size; - newPrevPanelSize = this.prevPanelSize + newPos; - newNextPanelSize = this.nextPanelSize - newPos; - } - if (this.validateResize(newPrevPanelSize, newNextPanelSize)) { - this.prevPanelElement.style.flexBasis = "calc(" + newPrevPanelSize + "% - " + (this.panels.length - 1) * this.gutterSize + "px)"; - this.nextPanelElement.style.flexBasis = "calc(" + newNextPanelSize + "% - " + (this.panels.length - 1) * this.gutterSize + "px)"; - this.panelSizes[this.prevPanelIndex] = newPrevPanelSize; - this.panelSizes[this.prevPanelIndex + 1] = newNextPanelSize; - this.prevSize = parseFloat(newPrevPanelSize).toFixed(4); - } - this.$emit("resize", { - originalEvent: event, - sizes: this.panelSizes - }); - }, "onResize"), - onResizeEnd: /* @__PURE__ */ __name(function onResizeEnd(event) { - if (this.isStateful()) { - this.saveState(); - } - this.$emit("resizeend", { - originalEvent: event, - sizes: this.panelSizes - }); - this.$refs.gutter.forEach(function(gutter) { - return gutter.setAttribute("data-p-gutter-resizing", false); - }); - this.$el.setAttribute("data-p-resizing", false); - this.clear(); - }, "onResizeEnd"), - repeat: /* @__PURE__ */ __name(function repeat(event, index2, step2) { - this.onResizeStart(event, index2, true); - this.onResize(event, step2, true); - }, "repeat"), - setTimer: /* @__PURE__ */ __name(function setTimer(event, index2, step2) { - var _this2 = this; - if (!this.timer) { - this.timer = setInterval(function() { - _this2.repeat(event, index2, step2); - }, 40); - } - }, "setTimer"), - clearTimer: /* @__PURE__ */ __name(function clearTimer() { - if (this.timer) { - clearInterval(this.timer); - this.timer = null; - } - }, "clearTimer"), - onGutterKeyUp: /* @__PURE__ */ __name(function onGutterKeyUp() { - this.clearTimer(); - this.onResizeEnd(); - }, "onGutterKeyUp"), - onGutterKeyDown: /* @__PURE__ */ __name(function onGutterKeyDown(event, index2) { - switch (event.code) { - case "ArrowLeft": { - if (this.layout === "horizontal") { - this.setTimer(event, index2, this.step * -1); - } - event.preventDefault(); - break; - } - case "ArrowRight": { - if (this.layout === "horizontal") { - this.setTimer(event, index2, this.step); - } - event.preventDefault(); - break; - } - case "ArrowDown": { - if (this.layout === "vertical") { - this.setTimer(event, index2, this.step * -1); - } - event.preventDefault(); - break; - } - case "ArrowUp": { - if (this.layout === "vertical") { - this.setTimer(event, index2, this.step); - } - event.preventDefault(); - break; - } - } - }, "onGutterKeyDown"), - onGutterMouseDown: /* @__PURE__ */ __name(function onGutterMouseDown(event, index2) { - this.onResizeStart(event, index2); - this.bindMouseListeners(); - }, "onGutterMouseDown"), - onGutterTouchStart: /* @__PURE__ */ __name(function onGutterTouchStart(event, index2) { - this.onResizeStart(event, index2); - this.bindTouchListeners(); - event.preventDefault(); - }, "onGutterTouchStart"), - onGutterTouchMove: /* @__PURE__ */ __name(function onGutterTouchMove(event) { - this.onResize(event); - event.preventDefault(); - }, "onGutterTouchMove"), - onGutterTouchEnd: /* @__PURE__ */ __name(function onGutterTouchEnd(event) { - this.onResizeEnd(event); - this.unbindTouchListeners(); - event.preventDefault(); - }, "onGutterTouchEnd"), - bindMouseListeners: /* @__PURE__ */ __name(function bindMouseListeners() { - var _this3 = this; - if (!this.mouseMoveListener) { - this.mouseMoveListener = function(event) { - return _this3.onResize(event); - }; - document.addEventListener("mousemove", this.mouseMoveListener); - } - if (!this.mouseUpListener) { - this.mouseUpListener = function(event) { - _this3.onResizeEnd(event); - _this3.unbindMouseListeners(); - }; - document.addEventListener("mouseup", this.mouseUpListener); - } - }, "bindMouseListeners"), - bindTouchListeners: /* @__PURE__ */ __name(function bindTouchListeners() { - var _this4 = this; - if (!this.touchMoveListener) { - this.touchMoveListener = function(event) { - return _this4.onResize(event.changedTouches[0]); - }; - document.addEventListener("touchmove", this.touchMoveListener); - } - if (!this.touchEndListener) { - this.touchEndListener = function(event) { - _this4.resizeEnd(event); - _this4.unbindTouchListeners(); - }; - document.addEventListener("touchend", this.touchEndListener); - } - }, "bindTouchListeners"), - validateResize: /* @__PURE__ */ __name(function validateResize(newPrevPanelSize, newNextPanelSize) { - if (newPrevPanelSize > 100 || newPrevPanelSize < 0) return false; - if (newNextPanelSize > 100 || newNextPanelSize < 0) return false; - var prevPanelMinSize = getVNodeProp(this.panels[this.prevPanelIndex], "minSize"); - if (this.panels[this.prevPanelIndex].props && prevPanelMinSize && prevPanelMinSize > newPrevPanelSize) { - return false; - } - var newPanelMinSize = getVNodeProp(this.panels[this.prevPanelIndex + 1], "minSize"); - if (this.panels[this.prevPanelIndex + 1].props && newPanelMinSize && newPanelMinSize > newNextPanelSize) { - return false; - } - return true; - }, "validateResize"), - unbindMouseListeners: /* @__PURE__ */ __name(function unbindMouseListeners() { - if (this.mouseMoveListener) { - document.removeEventListener("mousemove", this.mouseMoveListener); - this.mouseMoveListener = null; - } - if (this.mouseUpListener) { - document.removeEventListener("mouseup", this.mouseUpListener); - this.mouseUpListener = null; - } - }, "unbindMouseListeners"), - unbindTouchListeners: /* @__PURE__ */ __name(function unbindTouchListeners() { - if (this.touchMoveListener) { - document.removeEventListener("touchmove", this.touchMoveListener); - this.touchMoveListener = null; - } - if (this.touchEndListener) { - document.removeEventListener("touchend", this.touchEndListener); - this.touchEndListener = null; - } - }, "unbindTouchListeners"), - clear: /* @__PURE__ */ __name(function clear() { - this.dragging = false; - this.size = null; - this.startPos = null; - this.prevPanelElement = null; - this.nextPanelElement = null; - this.prevPanelSize = null; - this.nextPanelSize = null; - this.gutterElement = null; - this.prevPanelIndex = null; - }, "clear"), - isStateful: /* @__PURE__ */ __name(function isStateful() { - return this.stateKey != null; - }, "isStateful"), - getStorage: /* @__PURE__ */ __name(function getStorage() { - switch (this.stateStorage) { - case "local": - return window.localStorage; - case "session": - return window.sessionStorage; - default: - throw new Error(this.stateStorage + ' is not a valid value for the state storage, supported values are "local" and "session".'); - } - }, "getStorage"), - saveState: /* @__PURE__ */ __name(function saveState() { - if (isArray(this.panelSizes)) { - this.getStorage().setItem(this.stateKey, JSON.stringify(this.panelSizes)); - } - }, "saveState"), - restoreState: /* @__PURE__ */ __name(function restoreState() { - var _this5 = this; - var storage = this.getStorage(); - var stateString = storage.getItem(this.stateKey); - if (stateString) { - this.panelSizes = JSON.parse(stateString); - var children = _toConsumableArray$7(this.$el.children).filter(function(child) { - return child.getAttribute("data-pc-name") === "splitterpanel"; - }); - children.forEach(function(child, i) { - child.style.flexBasis = "calc(" + _this5.panelSizes[i] + "% - " + (_this5.panels.length - 1) * _this5.gutterSize + "px)"; - }); - return true; - } - return false; - }, "restoreState") - }, - computed: { - panels: /* @__PURE__ */ __name(function panels() { - var _this6 = this; - var panels2 = []; - this.$slots["default"]().forEach(function(child) { - if (_this6.isSplitterPanel(child)) { - panels2.push(child); - } else if (child.children instanceof Array) { - child.children.forEach(function(nestedChild) { - if (_this6.isSplitterPanel(nestedChild)) { - panels2.push(nestedChild); - } - }); - } - }); - return panels2; - }, "panels"), - gutterStyle: /* @__PURE__ */ __name(function gutterStyle() { - if (this.horizontal) return { - width: this.gutterSize + "px" - }; - else return { - height: this.gutterSize + "px" - }; - }, "gutterStyle"), - horizontal: /* @__PURE__ */ __name(function horizontal() { - return this.layout === "horizontal"; - }, "horizontal"), - getPTOptions: /* @__PURE__ */ __name(function getPTOptions() { - var _this$$parentInstance; - return { - context: { - nested: (_this$$parentInstance = this.$parentInstance) === null || _this$$parentInstance === void 0 ? void 0 : _this$$parentInstance.nestedState - } - }; - }, "getPTOptions") - } -}; -var _hoisted_1$D = ["onMousedown", "onTouchstart", "onTouchmove", "onTouchend"]; -var _hoisted_2$t = ["aria-orientation", "aria-valuenow", "onKeydown"]; -function render$l(_ctx, _cache, $props, $setup, $data, $options) { - return openBlock(), createElementBlock("div", mergeProps({ - "class": _ctx.cx("root"), - style: _ctx.sx("root"), - "data-p-resizing": false - }, _ctx.ptmi("root", $options.getPTOptions)), [(openBlock(true), createElementBlock(Fragment, null, renderList($options.panels, function(panel2, i) { - return openBlock(), createElementBlock(Fragment, { - key: i - }, [(openBlock(), createBlock(resolveDynamicComponent(panel2), { - tabindex: "-1" - })), i !== $options.panels.length - 1 ? (openBlock(), createElementBlock("div", mergeProps({ - key: 0, - ref_for: true, - ref: "gutter", - "class": _ctx.cx("gutter"), - role: "separator", - tabindex: "-1", - onMousedown: /* @__PURE__ */ __name(function onMousedown($event) { - return $options.onGutterMouseDown($event, i); - }, "onMousedown"), - onTouchstart: /* @__PURE__ */ __name(function onTouchstart($event) { - return $options.onGutterTouchStart($event, i); - }, "onTouchstart"), - onTouchmove: /* @__PURE__ */ __name(function onTouchmove($event) { - return $options.onGutterTouchMove($event, i); - }, "onTouchmove"), - onTouchend: /* @__PURE__ */ __name(function onTouchend($event) { - return $options.onGutterTouchEnd($event, i); - }, "onTouchend"), - "data-p-gutter-resizing": false - }, _ctx.ptm("gutter")), [createBaseVNode("div", mergeProps({ - "class": _ctx.cx("gutterHandle"), - tabindex: "0", - style: [$options.gutterStyle], - "aria-orientation": _ctx.layout, - "aria-valuenow": $data.prevSize, - onKeyup: _cache[0] || (_cache[0] = function() { - return $options.onGutterKeyUp && $options.onGutterKeyUp.apply($options, arguments); - }), - onKeydown: /* @__PURE__ */ __name(function onKeydown($event) { - return $options.onGutterKeyDown($event, i); - }, "onKeydown"), - ref_for: true - }, _ctx.ptm("gutterHandle")), null, 16, _hoisted_2$t)], 16, _hoisted_1$D)) : createCommentVNode("", true)], 64); - }), 128))], 16); -} -__name(render$l, "render$l"); -script$k.render = render$l; -var classes$g = { - root: /* @__PURE__ */ __name(function root3(_ref) { - var instance = _ref.instance; - return ["p-splitterpanel", { - "p-splitterpanel-nested": instance.isNested - }]; - }, "root") -}; -var SplitterPanelStyle = BaseStyle.extend({ - name: "splitterpanel", - classes: classes$g -}); -var script$1$g = { - name: "BaseSplitterPanel", - "extends": script$p, - props: { - size: { - type: Number, - "default": null - }, - minSize: { - type: Number, - "default": null - } - }, - style: SplitterPanelStyle, - provide: /* @__PURE__ */ __name(function provide4() { - return { - $pcSplitterPanel: this, - $parentInstance: this - }; - }, "provide") -}; -var script$j = { - name: "SplitterPanel", - "extends": script$1$g, - inheritAttrs: false, - data: /* @__PURE__ */ __name(function data2() { - return { - nestedState: null - }; - }, "data"), - computed: { - isNested: /* @__PURE__ */ __name(function isNested() { - var _this = this; - return this.$slots["default"]().some(function(child) { - _this.nestedState = child.type.name === "Splitter" ? true : null; - return _this.nestedState; - }); - }, "isNested"), - getPTOptions: /* @__PURE__ */ __name(function getPTOptions2() { - return { - context: { - nested: this.isNested - } - }; - }, "getPTOptions") - } -}; -function render$k(_ctx, _cache, $props, $setup, $data, $options) { - return openBlock(), createElementBlock("div", mergeProps({ - ref: "container", - "class": _ctx.cx("root") - }, _ctx.ptmi("root", $options.getPTOptions)), [renderSlot(_ctx.$slots, "default")], 16); -} -__name(render$k, "render$k"); -script$j.render = render$k; -const _sfc_main$C = /* @__PURE__ */ defineComponent({ - __name: "LiteGraphCanvasSplitterOverlay", - setup(__props) { - const settingStore = useSettingStore(); - const sidebarLocation = computed( - () => settingStore.get("Comfy.Sidebar.Location") - ); - const sidebarPanelVisible = computed( - () => useWorkspaceStore().sidebarTab.activeSidebarTab !== null - ); - const gutterClass = computed(() => { - return sidebarPanelVisible.value ? "" : "gutter-hidden"; - }); - return (_ctx, _cache) => { - return openBlock(), createBlock(unref(script$k), { - class: "splitter-overlay", - "pt:gutter": gutterClass.value - }, { - default: withCtx(() => [ - sidebarLocation.value === "left" ? withDirectives((openBlock(), createBlock(unref(script$j), { - key: 0, - class: "side-bar-panel", - minSize: 10, - size: 20 - }, { - default: withCtx(() => [ - renderSlot(_ctx.$slots, "side-bar-panel", {}, void 0, true) - ]), - _: 3 - }, 512)), [ - [vShow, sidebarPanelVisible.value] - ]) : createCommentVNode("", true), - createVNode(unref(script$j), { - class: "graph-canvas-panel relative", - size: 100 - }, { - default: withCtx(() => [ - renderSlot(_ctx.$slots, "graph-canvas-panel", {}, void 0, true) - ]), - _: 3 - }), - sidebarLocation.value === "right" ? withDirectives((openBlock(), createBlock(unref(script$j), { - key: 1, - class: "side-bar-panel", - minSize: 10, - size: 20 - }, { - default: withCtx(() => [ - renderSlot(_ctx.$slots, "side-bar-panel", {}, void 0, true) - ]), - _: 3 - }, 512)), [ - [vShow, sidebarPanelVisible.value] - ]) : createCommentVNode("", true) - ]), - _: 3 - }, 8, ["pt:gutter"]); - }; - } -}); -const LiteGraphCanvasSplitterOverlay = /* @__PURE__ */ _export_sfc(_sfc_main$C, [["__scopeId", "data-v-b9df3042"]]); -var theme$f = /* @__PURE__ */ __name(function theme3(_ref) { - var dt = _ref.dt; - return "\n.p-autocomplete {\n display: inline-flex;\n}\n\n.p-autocomplete-loader {\n position: absolute;\n top: 50%;\n margin-top: -0.5rem;\n right: ".concat(dt("autocomplete.padding.x"), ";\n}\n\n.p-autocomplete:has(.p-autocomplete-dropdown) .p-autocomplete-loader {\n right: calc(").concat(dt("autocomplete.dropdown.width"), " + ").concat(dt("autocomplete.padding.x"), ");\n}\n\n.p-autocomplete:has(.p-autocomplete-dropdown) .p-autocomplete-input {\n flex: 1 1 auto;\n width: 1%;\n}\n\n.p-autocomplete:has(.p-autocomplete-dropdown) .p-autocomplete-input,\n.p-autocomplete:has(.p-autocomplete-dropdown) .p-autocomplete-input-multiple {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n}\n\n.p-autocomplete-dropdown {\n cursor: pointer;\n display: inline-flex;\n cursor: pointer;\n user-select: none;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n position: relative;\n width: ").concat(dt("autocomplete.dropdown.width"), ";\n border-top-right-radius: ").concat(dt("autocomplete.dropdown.border.radius"), ";\n border-bottom-right-radius: ").concat(dt("autocomplete.dropdown.border.radius"), ";\n background: ").concat(dt("autocomplete.dropdown.background"), ";\n border: 1px solid ").concat(dt("autocomplete.dropdown.border.color"), ";\n border-left: 0 none;\n color: ").concat(dt("autocomplete.dropdown.color"), ";\n transition: background ").concat(dt("autocomplete.transition.duration"), ", color ").concat(dt("autocomplete.transition.duration"), ", border-color ").concat(dt("autocomplete.transition.duration"), ", outline-color ").concat(dt("autocomplete.transition.duration"), ", box-shadow ").concat(dt("autocomplete.transition.duration"), ";\n outline-color: transparent;\n}\n\n.p-autocomplete-dropdown:not(:disabled):hover {\n background: ").concat(dt("autocomplete.dropdown.hover.background"), ";\n border-color: ").concat(dt("autocomplete.dropdown.hover.border.color"), ";\n color: ").concat(dt("autocomplete.dropdown.hover.color"), ";\n}\n\n.p-autocomplete-dropdown:not(:disabled):active {\n background: ").concat(dt("autocomplete.dropdown.active.background"), ";\n border-color: ").concat(dt("autocomplete.dropdown.active.border.color"), ";\n color: ").concat(dt("autocomplete.dropdown.active.color"), ";\n}\n\n.p-autocomplete-dropdown:focus-visible {\n box-shadow: ").concat(dt("autocomplete.dropdown.focus.ring.shadow"), ";\n outline: ").concat(dt("autocomplete.dropdown.focus.ring.width"), " ").concat(dt("autocomplete.dropdown.focus.ring.style"), " ").concat(dt("autocomplete.dropdown.focus.ring.color"), ";\n outline-offset: ").concat(dt("autocomplete.dropdown.focus.ring.offset"), ";\n}\n\n.p-autocomplete .p-autocomplete-overlay {\n min-width: 100%;\n}\n\n.p-autocomplete-overlay {\n position: absolute;\n overflow: auto;\n top: 0;\n left: 0;\n background: ").concat(dt("autocomplete.overlay.background"), ";\n color: ").concat(dt("autocomplete.overlay.color"), ";\n border: 1px solid ").concat(dt("autocomplete.overlay.border.color"), ";\n border-radius: ").concat(dt("autocomplete.overlay.border.radius"), ";\n box-shadow: ").concat(dt("autocomplete.overlay.shadow"), ";\n}\n\n.p-autocomplete-list {\n margin: 0;\n padding: 0;\n list-style-type: none;\n display: flex;\n flex-direction: column;\n gap: ").concat(dt("autocomplete.list.gap"), ";\n padding: ").concat(dt("autocomplete.list.padding"), ";\n}\n\n.p-autocomplete-option {\n cursor: pointer;\n white-space: nowrap;\n position: relative;\n overflow: hidden;\n display: flex;\n align-items: center;\n padding: ").concat(dt("autocomplete.option.padding"), ";\n border: 0 none;\n color: ").concat(dt("autocomplete.option.color"), ";\n background: transparent;\n transition: background ").concat(dt("autocomplete.transition.duration"), ", color ").concat(dt("autocomplete.transition.duration"), ", border-color ").concat(dt("autocomplete.transition.duration"), ";\n border-radius: ").concat(dt("autocomplete.option.border.radius"), ";\n}\n\n.p-autocomplete-option:not(.p-autocomplete-option-selected):not(.p-disabled).p-focus {\n background: ").concat(dt("autocomplete.option.focus.background"), ";\n color: ").concat(dt("autocomplete.option.focus.color"), ";\n}\n\n.p-autocomplete-option-selected {\n background: ").concat(dt("autocomplete.option.selected.background"), ";\n color: ").concat(dt("autocomplete.option.selected.color"), ";\n}\n\n.p-autocomplete-option-selected.p-focus {\n background: ").concat(dt("autocomplete.option.selected.focus.background"), ";\n color: ").concat(dt("autocomplete.option.selected.focus.color"), ";\n}\n\n.p-autocomplete-option-group {\n margin: 0;\n padding: ").concat(dt("autocomplete.option.group.padding"), ";\n color: ").concat(dt("autocomplete.option.group.color"), ";\n background: ").concat(dt("autocomplete.option.group.background"), ";\n font-weight: ").concat(dt("autocomplete.option.group.font.weight"), ";\n}\n\n.p-autocomplete-input-multiple {\n margin: 0;\n list-style-type: none;\n cursor: text;\n overflow: hidden;\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n padding: calc(").concat(dt("autocomplete.padding.y"), " / 2) ").concat(dt("autocomplete.padding.x"), ";\n gap: calc(").concat(dt("autocomplete.padding.y"), " / 2);\n color: ").concat(dt("autocomplete.color"), ";\n background: ").concat(dt("autocomplete.background"), ";\n border: 1px solid ").concat(dt("autocomplete.border.color"), ";\n border-radius: ").concat(dt("autocomplete.border.radius"), ";\n width: 100%;\n transition: background ").concat(dt("autocomplete.transition.duration"), ", color ").concat(dt("autocomplete.transition.duration"), ", border-color ").concat(dt("autocomplete.transition.duration"), ", outline-color ").concat(dt("autocomplete.transition.duration"), ", box-shadow ").concat(dt("autocomplete.transition.duration"), ";\n outline-color: transparent;\n box-shadow: ").concat(dt("autocomplete.shadow"), ";\n}\n\n.p-autocomplete:not(.p-disabled):hover .p-autocomplete-input-multiple {\n border-color: ").concat(dt("autocomplete.hover.border.color"), ";\n}\n\n.p-autocomplete:not(.p-disabled).p-focus .p-autocomplete-input-multiple {\n border-color: ").concat(dt("autocomplete.focus.border.color"), ";\n box-shadow: ").concat(dt("autocomplete.focus.ring.shadow"), ";\n outline: ").concat(dt("autocomplete.focus.ring.width"), " ").concat(dt("autocomplete.focus.ring.style"), " ").concat(dt("autocomplete.focus.ring.color"), ";\n outline-offset: ").concat(dt("autocomplete.focus.ring.offset"), ";\n}\n\n.p-autocomplete.p-invalid .p-autocomplete-input-multiple {\n border-color: ").concat(dt("autocomplete.invalid.border.color"), ";\n}\n\n.p-variant-filled.p-autocomplete-input-multiple {\n background: ").concat(dt("autocomplete.filled.background"), ";\n}\n\n.p-autocomplete:not(.p-disabled).p-focus .p-variant-filled.p-autocomplete-input-multiple {\n background: ").concat(dt("autocomplete.filled.focus.background"), ";\n}\n\n.p-autocomplete.p-disabled .p-autocomplete-input-multiple {\n opacity: 1;\n background: ").concat(dt("autocomplete.disabled.background"), ";\n color: ").concat(dt("autocomplete.disabled.color"), ";\n}\n\n.p-autocomplete-chip.p-chip {\n padding-top: calc(").concat(dt("autocomplete.padding.y"), " / 2);\n padding-bottom: calc(").concat(dt("autocomplete.padding.y"), " / 2);\n border-radius: ").concat(dt("autocomplete.chip.border.radius"), ";\n}\n\n.p-autocomplete-input-multiple:has(.p-autocomplete-chip) {\n padding-left: calc(").concat(dt("autocomplete.padding.y"), " / 2);\n padding-right: calc(").concat(dt("autocomplete.padding.y"), " / 2);\n}\n\n.p-autocomplete-chip-item.p-focus .p-autocomplete-chip {\n background: ").concat(dt("inputchips.chip.focus.background"), ";\n color: ").concat(dt("inputchips.chip.focus.color"), ";\n}\n\n.p-autocomplete-input-chip {\n flex: 1 1 auto;\n display: inline-flex;\n padding-top: calc(").concat(dt("autocomplete.padding.y"), " / 2);\n padding-bottom: calc(").concat(dt("autocomplete.padding.y"), " / 2);\n}\n\n.p-autocomplete-input-chip input {\n border: 0 none;\n outline: 0 none;\n background: transparent;\n margin: 0;\n padding: 0;\n box-shadow: none;\n border-radius: 0;\n width: 100%;\n font-family: inherit;\n font-feature-settings: inherit;\n font-size: 1rem;\n color: inherit;\n}\n\n.p-autocomplete-input-chip input::placeholder {\n color: ").concat(dt("autocomplete.placeholder.color"), ";\n}\n\n.p-autocomplete-empty-message {\n padding: ").concat(dt("autocomplete.empty.message.padding"), ";\n}\n\n.p-autocomplete-fluid {\n display: flex;\n}\n\n.p-autocomplete-fluid:has(.p-autocomplete-dropdown) .p-autocomplete-input {\n width: 1%;\n}\n"); -}, "theme"); -var inlineStyles$3 = { - root: { - position: "relative" - } -}; -var classes$f = { - root: /* @__PURE__ */ __name(function root4(_ref2) { - var instance = _ref2.instance, props = _ref2.props; - return ["p-autocomplete p-component p-inputwrapper", { - "p-disabled": props.disabled, - "p-invalid": props.invalid, - "p-focus": instance.focused, - "p-inputwrapper-filled": props.modelValue || isNotEmpty(instance.inputValue), - "p-inputwrapper-focus": instance.focused, - "p-autocomplete-open": instance.overlayVisible, - "p-autocomplete-fluid": instance.hasFluid - }]; - }, "root"), - pcInput: "p-autocomplete-input", - inputMultiple: /* @__PURE__ */ __name(function inputMultiple(_ref3) { - var props = _ref3.props, instance = _ref3.instance; - return ["p-autocomplete-input-multiple", { - "p-variant-filled": props.variant ? props.variant === "filled" : instance.$primevue.config.inputStyle === "filled" || instance.$primevue.config.inputVariant === "filled" - }]; - }, "inputMultiple"), - chipItem: /* @__PURE__ */ __name(function chipItem(_ref4) { - var instance = _ref4.instance, i = _ref4.i; - return ["p-autocomplete-chip-item", { - "p-focus": instance.focusedMultipleOptionIndex === i - }]; - }, "chipItem"), - pcChip: "p-autocomplete-chip", - chipIcon: "p-autocomplete-chip-icon", - inputChip: "p-autocomplete-input-chip", - loader: "p-autocomplete-loader", - dropdown: "p-autocomplete-dropdown", - overlay: "p-autocomplete-overlay p-component", - list: "p-autocomplete-list", - optionGroup: "p-autocomplete-option-group", - option: /* @__PURE__ */ __name(function option(_ref5) { - var instance = _ref5.instance, _option = _ref5.option, i = _ref5.i, getItemOptions = _ref5.getItemOptions; - return ["p-autocomplete-option", { - "p-autocomplete-option-selected": instance.isSelected(_option), - "p-focus": instance.focusedOptionIndex === instance.getOptionIndex(i, getItemOptions), - "p-disabled": instance.isOptionDisabled(_option) - }]; - }, "option"), - emptyMessage: "p-autocomplete-empty-message" -}; -var AutoCompleteStyle = BaseStyle.extend({ - name: "autocomplete", - theme: theme$f, - classes: classes$f, - inlineStyles: inlineStyles$3 -}); -var script$1$f = { - name: "BaseAutoComplete", - "extends": script$p, - props: { - modelValue: null, - suggestions: { - type: Array, - "default": null - }, - optionLabel: null, - optionDisabled: null, - optionGroupLabel: null, - optionGroupChildren: null, - scrollHeight: { - type: String, - "default": "14rem" - }, - dropdown: { - type: Boolean, - "default": false - }, - dropdownMode: { - type: String, - "default": "blank" - }, - multiple: { - type: Boolean, - "default": false - }, - loading: { - type: Boolean, - "default": false - }, - variant: { - type: String, - "default": null - }, - invalid: { - type: Boolean, - "default": false - }, - disabled: { - type: Boolean, - "default": false - }, - placeholder: { - type: String, - "default": null - }, - dataKey: { - type: String, - "default": null - }, - minLength: { - type: Number, - "default": 1 - }, - delay: { - type: Number, - "default": 300 - }, - appendTo: { - type: [String, Object], - "default": "body" - }, - forceSelection: { - type: Boolean, - "default": false - }, - completeOnFocus: { - type: Boolean, - "default": false - }, - inputId: { - type: String, - "default": null - }, - inputStyle: { - type: Object, - "default": null - }, - inputClass: { - type: [String, Object], - "default": null - }, - panelStyle: { - type: Object, - "default": null - }, - panelClass: { - type: [String, Object], - "default": null - }, - overlayStyle: { - type: Object, - "default": null - }, - overlayClass: { - type: [String, Object], - "default": null - }, - dropdownIcon: { - type: String, - "default": null - }, - dropdownClass: { - type: [String, Object], - "default": null - }, - loader: { - type: String, - "default": null - }, - loadingIcon: { - type: String, - "default": null - }, - removeTokenIcon: { - type: String, - "default": null - }, - chipIcon: { - type: String, - "default": null - }, - virtualScrollerOptions: { - type: Object, - "default": null - }, - autoOptionFocus: { - type: Boolean, - "default": false - }, - selectOnFocus: { - type: Boolean, - "default": false - }, - focusOnHover: { - type: Boolean, - "default": true - }, - searchLocale: { - type: String, - "default": void 0 - }, - searchMessage: { - type: String, - "default": null - }, - selectionMessage: { - type: String, - "default": null - }, - emptySelectionMessage: { - type: String, - "default": null - }, - emptySearchMessage: { - type: String, - "default": null - }, - tabindex: { - type: Number, - "default": 0 - }, - typeahead: { - type: Boolean, - "default": true - }, - ariaLabel: { - type: String, - "default": null - }, - ariaLabelledby: { - type: String, - "default": null - }, - fluid: { - type: Boolean, - "default": null - } - }, - style: AutoCompleteStyle, - provide: /* @__PURE__ */ __name(function provide5() { - return { - $pcAutoComplete: this, - $parentInstance: this - }; - }, "provide") -}; -function _typeof$1$3(o) { - "@babel/helpers - typeof"; - return _typeof$1$3 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o2) { - return typeof o2; - } : function(o2) { - return o2 && "function" == typeof Symbol && o2.constructor === Symbol && o2 !== Symbol.prototype ? "symbol" : typeof o2; - }, _typeof$1$3(o); -} -__name(_typeof$1$3, "_typeof$1$3"); -function _toConsumableArray$6(r) { - return _arrayWithoutHoles$6(r) || _iterableToArray$6(r) || _unsupportedIterableToArray$8(r) || _nonIterableSpread$6(); -} -__name(_toConsumableArray$6, "_toConsumableArray$6"); -function _nonIterableSpread$6() { - throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); -} -__name(_nonIterableSpread$6, "_nonIterableSpread$6"); -function _unsupportedIterableToArray$8(r, a) { - if (r) { - if ("string" == typeof r) return _arrayLikeToArray$8(r, a); - var t = {}.toString.call(r).slice(8, -1); - return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray$8(r, a) : void 0; - } -} -__name(_unsupportedIterableToArray$8, "_unsupportedIterableToArray$8"); -function _iterableToArray$6(r) { - if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); -} -__name(_iterableToArray$6, "_iterableToArray$6"); -function _arrayWithoutHoles$6(r) { - if (Array.isArray(r)) return _arrayLikeToArray$8(r); -} -__name(_arrayWithoutHoles$6, "_arrayWithoutHoles$6"); -function _arrayLikeToArray$8(r, a) { - (null == a || a > r.length) && (a = r.length); - for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; - return n; -} -__name(_arrayLikeToArray$8, "_arrayLikeToArray$8"); -var script$i = { - name: "AutoComplete", - "extends": script$1$f, - inheritAttrs: false, - emits: ["update:modelValue", "change", "focus", "blur", "item-select", "item-unselect", "option-select", "option-unselect", "dropdown-click", "clear", "complete", "before-show", "before-hide", "show", "hide"], - inject: { - $pcFluid: { - "default": null - } - }, - outsideClickListener: null, - resizeListener: null, - scrollHandler: null, - overlay: null, - virtualScroller: null, - searchTimeout: null, - dirty: false, - data: /* @__PURE__ */ __name(function data3() { - return { - id: this.$attrs.id, - clicked: false, - focused: false, - focusedOptionIndex: -1, - focusedMultipleOptionIndex: -1, - overlayVisible: false, - searching: false - }; - }, "data"), - watch: { - "$attrs.id": /* @__PURE__ */ __name(function $attrsId(newValue) { - this.id = newValue || UniqueComponentId(); - }, "$attrsId"), - suggestions: /* @__PURE__ */ __name(function suggestions() { - if (this.searching) { - this.show(); - this.focusedOptionIndex = this.overlayVisible && this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1; - this.searching = false; - } - this.autoUpdateModel(); - }, "suggestions") - }, - mounted: /* @__PURE__ */ __name(function mounted2() { - this.id = this.id || UniqueComponentId(); - this.autoUpdateModel(); - }, "mounted"), - updated: /* @__PURE__ */ __name(function updated() { - if (this.overlayVisible) { - this.alignOverlay(); - } - }, "updated"), - beforeUnmount: /* @__PURE__ */ __name(function beforeUnmount2() { - this.unbindOutsideClickListener(); - this.unbindResizeListener(); - if (this.scrollHandler) { - this.scrollHandler.destroy(); - this.scrollHandler = null; - } - if (this.overlay) { - ZIndex.clear(this.overlay); - this.overlay = null; - } - }, "beforeUnmount"), - methods: { - getOptionIndex: /* @__PURE__ */ __name(function getOptionIndex(index2, fn) { - return this.virtualScrollerDisabled ? index2 : fn && fn(index2)["index"]; - }, "getOptionIndex"), - getOptionLabel: /* @__PURE__ */ __name(function getOptionLabel(option2) { - return this.optionLabel ? resolveFieldData(option2, this.optionLabel) : option2; - }, "getOptionLabel"), - getOptionValue: /* @__PURE__ */ __name(function getOptionValue(option2) { - return option2; - }, "getOptionValue"), - getOptionRenderKey: /* @__PURE__ */ __name(function getOptionRenderKey(option2, index2) { - return (this.dataKey ? resolveFieldData(option2, this.dataKey) : this.getOptionLabel(option2)) + "_" + index2; - }, "getOptionRenderKey"), - getPTOptions: /* @__PURE__ */ __name(function getPTOptions3(option2, itemOptions, index2, key) { - return this.ptm(key, { - context: { - selected: this.isSelected(option2), - focused: this.focusedOptionIndex === this.getOptionIndex(index2, itemOptions), - disabled: this.isOptionDisabled(option2) - } - }); - }, "getPTOptions"), - isOptionDisabled: /* @__PURE__ */ __name(function isOptionDisabled(option2) { - return this.optionDisabled ? resolveFieldData(option2, this.optionDisabled) : false; - }, "isOptionDisabled"), - isOptionGroup: /* @__PURE__ */ __name(function isOptionGroup(option2) { - return this.optionGroupLabel && option2.optionGroup && option2.group; - }, "isOptionGroup"), - getOptionGroupLabel: /* @__PURE__ */ __name(function getOptionGroupLabel(optionGroup) { - return resolveFieldData(optionGroup, this.optionGroupLabel); - }, "getOptionGroupLabel"), - getOptionGroupChildren: /* @__PURE__ */ __name(function getOptionGroupChildren(optionGroup) { - return resolveFieldData(optionGroup, this.optionGroupChildren); - }, "getOptionGroupChildren"), - getAriaPosInset: /* @__PURE__ */ __name(function getAriaPosInset(index2) { - var _this = this; - return (this.optionGroupLabel ? index2 - this.visibleOptions.slice(0, index2).filter(function(option2) { - return _this.isOptionGroup(option2); - }).length : index2) + 1; - }, "getAriaPosInset"), - show: /* @__PURE__ */ __name(function show(isFocus) { - this.$emit("before-show"); - this.dirty = true; - this.overlayVisible = true; - this.focusedOptionIndex = this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1; - isFocus && focus(this.multiple ? this.$refs.focusInput : this.$refs.focusInput.$el); - }, "show"), - hide: /* @__PURE__ */ __name(function hide(isFocus) { - var _this2 = this; - var _hide = /* @__PURE__ */ __name(function _hide2() { - _this2.$emit("before-hide"); - _this2.dirty = isFocus; - _this2.overlayVisible = false; - _this2.clicked = false; - _this2.focusedOptionIndex = -1; - isFocus && focus(_this2.multiple ? _this2.$refs.focusInput : _this2.$refs.focusInput.$el); - }, "_hide"); - setTimeout(function() { - _hide(); - }, 0); - }, "hide"), - onFocus: /* @__PURE__ */ __name(function onFocus(event) { - if (this.disabled) { - return; - } - if (!this.dirty && this.completeOnFocus) { - this.search(event, event.target.value, "focus"); - } - this.dirty = true; - this.focused = true; - if (this.overlayVisible) { - this.focusedOptionIndex = this.focusedOptionIndex !== -1 ? this.focusedOptionIndex : this.overlayVisible && this.autoOptionFocus ? this.findFirstFocusedOptionIndex() : -1; - this.scrollInView(this.focusedOptionIndex); - } - this.$emit("focus", event); - }, "onFocus"), - onBlur: /* @__PURE__ */ __name(function onBlur(event) { - this.dirty = false; - this.focused = false; - this.focusedOptionIndex = -1; - this.$emit("blur", event); - }, "onBlur"), - onKeyDown: /* @__PURE__ */ __name(function onKeyDown(event) { - if (this.disabled) { - event.preventDefault(); - return; - } - switch (event.code) { - case "ArrowDown": - this.onArrowDownKey(event); - break; - case "ArrowUp": - this.onArrowUpKey(event); - break; - case "ArrowLeft": - this.onArrowLeftKey(event); - break; - case "ArrowRight": - this.onArrowRightKey(event); - break; - case "Home": - this.onHomeKey(event); - break; - case "End": - this.onEndKey(event); - break; - case "PageDown": - this.onPageDownKey(event); - break; - case "PageUp": - this.onPageUpKey(event); - break; - case "Enter": - case "NumpadEnter": - this.onEnterKey(event); - break; - case "Escape": - this.onEscapeKey(event); - break; - case "Tab": - this.onTabKey(event); - break; - case "Backspace": - this.onBackspaceKey(event); - break; - } - this.clicked = false; - }, "onKeyDown"), - onInput: /* @__PURE__ */ __name(function onInput(event) { - var _this3 = this; - if (this.typeahead) { - if (this.searchTimeout) { - clearTimeout(this.searchTimeout); - } - var query = event.target.value; - if (!this.multiple) { - this.updateModel(event, query); - } - if (query.length === 0) { - this.hide(); - this.$emit("clear"); - } else { - if (query.length >= this.minLength) { - this.focusedOptionIndex = -1; - this.searchTimeout = setTimeout(function() { - _this3.search(event, query, "input"); - }, this.delay); - } else { - this.hide(); - } - } - } - }, "onInput"), - onChange: /* @__PURE__ */ __name(function onChange(event) { - var _this4 = this; - if (this.forceSelection) { - var valid = false; - if (this.visibleOptions && !this.multiple) { - var value = this.multiple ? this.$refs.focusInput.value : this.$refs.focusInput.$el.value; - var matchedValue = this.visibleOptions.find(function(option2) { - return _this4.isOptionMatched(option2, value || ""); - }); - if (matchedValue !== void 0) { - valid = true; - !this.isSelected(matchedValue) && this.onOptionSelect(event, matchedValue); - } - } - if (!valid) { - if (this.multiple) this.$refs.focusInput.value = ""; - else this.$refs.focusInput.$el.value = ""; - this.$emit("clear"); - !this.multiple && this.updateModel(event, null); - } - } - }, "onChange"), - onMultipleContainerFocus: /* @__PURE__ */ __name(function onMultipleContainerFocus() { - if (this.disabled) { - return; - } - this.focused = true; - }, "onMultipleContainerFocus"), - onMultipleContainerBlur: /* @__PURE__ */ __name(function onMultipleContainerBlur() { - this.focusedMultipleOptionIndex = -1; - this.focused = false; - }, "onMultipleContainerBlur"), - onMultipleContainerKeyDown: /* @__PURE__ */ __name(function onMultipleContainerKeyDown(event) { - if (this.disabled) { - event.preventDefault(); - return; - } - switch (event.code) { - case "ArrowLeft": - this.onArrowLeftKeyOnMultiple(event); - break; - case "ArrowRight": - this.onArrowRightKeyOnMultiple(event); - break; - case "Backspace": - this.onBackspaceKeyOnMultiple(event); - break; - } - }, "onMultipleContainerKeyDown"), - onContainerClick: /* @__PURE__ */ __name(function onContainerClick(event) { - this.clicked = true; - if (this.disabled || this.searching || this.loading || this.isInputClicked(event) || this.isDropdownClicked(event)) { - return; - } - if (!this.overlay || !this.overlay.contains(event.target)) { - focus(this.multiple ? this.$refs.focusInput : this.$refs.focusInput.$el); - } - }, "onContainerClick"), - onDropdownClick: /* @__PURE__ */ __name(function onDropdownClick(event) { - var query = void 0; - if (this.overlayVisible) { - this.hide(true); - } else { - var target = this.multiple ? this.$refs.focusInput : this.$refs.focusInput.$el; - focus(target); - query = target.value; - if (this.dropdownMode === "blank") this.search(event, "", "dropdown"); - else if (this.dropdownMode === "current") this.search(event, query, "dropdown"); - } - this.$emit("dropdown-click", { - originalEvent: event, - query - }); - }, "onDropdownClick"), - onOptionSelect: /* @__PURE__ */ __name(function onOptionSelect(event, option2) { - var isHide = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : true; - var value = this.getOptionValue(option2); - if (this.multiple) { - this.$refs.focusInput.value = ""; - if (!this.isSelected(option2)) { - this.updateModel(event, [].concat(_toConsumableArray$6(this.modelValue || []), [value])); - } - } else { - this.updateModel(event, value); - } - this.$emit("item-select", { - originalEvent: event, - value: option2 - }); - this.$emit("option-select", { - originalEvent: event, - value: option2 - }); - isHide && this.hide(true); - }, "onOptionSelect"), - onOptionMouseMove: /* @__PURE__ */ __name(function onOptionMouseMove(event, index2) { - if (this.focusOnHover) { - this.changeFocusedOptionIndex(event, index2); - } - }, "onOptionMouseMove"), - onOverlayClick: /* @__PURE__ */ __name(function onOverlayClick(event) { - OverlayEventBus.emit("overlay-click", { - originalEvent: event, - target: this.$el - }); - }, "onOverlayClick"), - onOverlayKeyDown: /* @__PURE__ */ __name(function onOverlayKeyDown(event) { - switch (event.code) { - case "Escape": - this.onEscapeKey(event); - break; - } - }, "onOverlayKeyDown"), - onArrowDownKey: /* @__PURE__ */ __name(function onArrowDownKey(event) { - if (!this.overlayVisible) { - return; - } - var optionIndex = this.focusedOptionIndex !== -1 ? this.findNextOptionIndex(this.focusedOptionIndex) : this.clicked ? this.findFirstOptionIndex() : this.findFirstFocusedOptionIndex(); - this.changeFocusedOptionIndex(event, optionIndex); - event.preventDefault(); - }, "onArrowDownKey"), - onArrowUpKey: /* @__PURE__ */ __name(function onArrowUpKey(event) { - if (!this.overlayVisible) { - return; - } - if (event.altKey) { - if (this.focusedOptionIndex !== -1) { - this.onOptionSelect(event, this.visibleOptions[this.focusedOptionIndex]); - } - this.overlayVisible && this.hide(); - event.preventDefault(); - } else { - var optionIndex = this.focusedOptionIndex !== -1 ? this.findPrevOptionIndex(this.focusedOptionIndex) : this.clicked ? this.findLastOptionIndex() : this.findLastFocusedOptionIndex(); - this.changeFocusedOptionIndex(event, optionIndex); - event.preventDefault(); - } - }, "onArrowUpKey"), - onArrowLeftKey: /* @__PURE__ */ __name(function onArrowLeftKey(event) { - var target = event.currentTarget; - this.focusedOptionIndex = -1; - if (this.multiple) { - if (isEmpty(target.value) && this.hasSelectedOption) { - focus(this.$refs.multiContainer); - this.focusedMultipleOptionIndex = this.modelValue.length; - } else { - event.stopPropagation(); - } - } - }, "onArrowLeftKey"), - onArrowRightKey: /* @__PURE__ */ __name(function onArrowRightKey(event) { - this.focusedOptionIndex = -1; - this.multiple && event.stopPropagation(); - }, "onArrowRightKey"), - onHomeKey: /* @__PURE__ */ __name(function onHomeKey(event) { - var currentTarget = event.currentTarget; - var len = currentTarget.value.length; - currentTarget.setSelectionRange(0, event.shiftKey ? len : 0); - this.focusedOptionIndex = -1; - event.preventDefault(); - }, "onHomeKey"), - onEndKey: /* @__PURE__ */ __name(function onEndKey(event) { - var currentTarget = event.currentTarget; - var len = currentTarget.value.length; - currentTarget.setSelectionRange(event.shiftKey ? 0 : len, len); - this.focusedOptionIndex = -1; - event.preventDefault(); - }, "onEndKey"), - onPageUpKey: /* @__PURE__ */ __name(function onPageUpKey(event) { - this.scrollInView(0); - event.preventDefault(); - }, "onPageUpKey"), - onPageDownKey: /* @__PURE__ */ __name(function onPageDownKey(event) { - this.scrollInView(this.visibleOptions.length - 1); - event.preventDefault(); - }, "onPageDownKey"), - onEnterKey: /* @__PURE__ */ __name(function onEnterKey(event) { - if (!this.typeahead) { - if (this.multiple) { - this.updateModel(event, [].concat(_toConsumableArray$6(this.modelValue || []), [event.target.value])); - this.$refs.focusInput.value = ""; - } - } else { - if (!this.overlayVisible) { - this.focusedOptionIndex = -1; - this.onArrowDownKey(event); - } else { - if (this.focusedOptionIndex !== -1) { - this.onOptionSelect(event, this.visibleOptions[this.focusedOptionIndex]); - } - this.hide(); - } - } - }, "onEnterKey"), - onEscapeKey: /* @__PURE__ */ __name(function onEscapeKey(event) { - this.overlayVisible && this.hide(true); - event.preventDefault(); - }, "onEscapeKey"), - onTabKey: /* @__PURE__ */ __name(function onTabKey(event) { - if (this.focusedOptionIndex !== -1) { - this.onOptionSelect(event, this.visibleOptions[this.focusedOptionIndex]); - } - this.overlayVisible && this.hide(); - }, "onTabKey"), - onBackspaceKey: /* @__PURE__ */ __name(function onBackspaceKey(event) { - if (this.multiple) { - if (isNotEmpty(this.modelValue) && !this.$refs.focusInput.value) { - var removedValue = this.modelValue[this.modelValue.length - 1]; - var newValue = this.modelValue.slice(0, -1); - this.$emit("update:modelValue", newValue); - this.$emit("item-unselect", { - originalEvent: event, - value: removedValue - }); - this.$emit("option-unselect", { - originalEvent: event, - value: removedValue - }); - } - event.stopPropagation(); - } - }, "onBackspaceKey"), - onArrowLeftKeyOnMultiple: /* @__PURE__ */ __name(function onArrowLeftKeyOnMultiple() { - this.focusedMultipleOptionIndex = this.focusedMultipleOptionIndex < 1 ? 0 : this.focusedMultipleOptionIndex - 1; - }, "onArrowLeftKeyOnMultiple"), - onArrowRightKeyOnMultiple: /* @__PURE__ */ __name(function onArrowRightKeyOnMultiple() { - this.focusedMultipleOptionIndex++; - if (this.focusedMultipleOptionIndex > this.modelValue.length - 1) { - this.focusedMultipleOptionIndex = -1; - focus(this.$refs.focusInput); - } - }, "onArrowRightKeyOnMultiple"), - onBackspaceKeyOnMultiple: /* @__PURE__ */ __name(function onBackspaceKeyOnMultiple(event) { - if (this.focusedMultipleOptionIndex !== -1) { - this.removeOption(event, this.focusedMultipleOptionIndex); - } - }, "onBackspaceKeyOnMultiple"), - onOverlayEnter: /* @__PURE__ */ __name(function onOverlayEnter(el) { - ZIndex.set("overlay", el, this.$primevue.config.zIndex.overlay); - addStyle(el, { - position: "absolute", - top: "0", - left: "0" - }); - this.alignOverlay(); - }, "onOverlayEnter"), - onOverlayAfterEnter: /* @__PURE__ */ __name(function onOverlayAfterEnter() { - this.bindOutsideClickListener(); - this.bindScrollListener(); - this.bindResizeListener(); - this.$emit("show"); - }, "onOverlayAfterEnter"), - onOverlayLeave: /* @__PURE__ */ __name(function onOverlayLeave() { - this.unbindOutsideClickListener(); - this.unbindScrollListener(); - this.unbindResizeListener(); - this.$emit("hide"); - this.overlay = null; - }, "onOverlayLeave"), - onOverlayAfterLeave: /* @__PURE__ */ __name(function onOverlayAfterLeave(el) { - ZIndex.clear(el); - }, "onOverlayAfterLeave"), - alignOverlay: /* @__PURE__ */ __name(function alignOverlay() { - var target = this.multiple ? this.$refs.multiContainer : this.$refs.focusInput.$el; - if (this.appendTo === "self") { - relativePosition(this.overlay, target); - } else { - this.overlay.style.minWidth = getOuterWidth(target) + "px"; - absolutePosition(this.overlay, target); - } - }, "alignOverlay"), - bindOutsideClickListener: /* @__PURE__ */ __name(function bindOutsideClickListener() { - var _this5 = this; - if (!this.outsideClickListener) { - this.outsideClickListener = function(event) { - if (_this5.overlayVisible && _this5.overlay && _this5.isOutsideClicked(event)) { - _this5.hide(); - } - }; - document.addEventListener("click", this.outsideClickListener); - } - }, "bindOutsideClickListener"), - unbindOutsideClickListener: /* @__PURE__ */ __name(function unbindOutsideClickListener() { - if (this.outsideClickListener) { - document.removeEventListener("click", this.outsideClickListener); - this.outsideClickListener = null; - } - }, "unbindOutsideClickListener"), - bindScrollListener: /* @__PURE__ */ __name(function bindScrollListener() { - var _this6 = this; - if (!this.scrollHandler) { - this.scrollHandler = new ConnectedOverlayScrollHandler(this.$refs.container, function() { - if (_this6.overlayVisible) { - _this6.hide(); - } - }); - } - this.scrollHandler.bindScrollListener(); - }, "bindScrollListener"), - unbindScrollListener: /* @__PURE__ */ __name(function unbindScrollListener() { - if (this.scrollHandler) { - this.scrollHandler.unbindScrollListener(); - } - }, "unbindScrollListener"), - bindResizeListener: /* @__PURE__ */ __name(function bindResizeListener() { - var _this7 = this; - if (!this.resizeListener) { - this.resizeListener = function() { - if (_this7.overlayVisible && !isTouchDevice()) { - _this7.hide(); - } - }; - window.addEventListener("resize", this.resizeListener); - } - }, "bindResizeListener"), - unbindResizeListener: /* @__PURE__ */ __name(function unbindResizeListener() { - if (this.resizeListener) { - window.removeEventListener("resize", this.resizeListener); - this.resizeListener = null; - } - }, "unbindResizeListener"), - isOutsideClicked: /* @__PURE__ */ __name(function isOutsideClicked(event) { - return !this.overlay.contains(event.target) && !this.isInputClicked(event) && !this.isDropdownClicked(event); - }, "isOutsideClicked"), - isInputClicked: /* @__PURE__ */ __name(function isInputClicked(event) { - if (this.multiple) return event.target === this.$refs.multiContainer || this.$refs.multiContainer.contains(event.target); - else return event.target === this.$refs.focusInput.$el; - }, "isInputClicked"), - isDropdownClicked: /* @__PURE__ */ __name(function isDropdownClicked(event) { - return this.$refs.dropdownButton ? event.target === this.$refs.dropdownButton || this.$refs.dropdownButton.contains(event.target) : false; - }, "isDropdownClicked"), - isOptionMatched: /* @__PURE__ */ __name(function isOptionMatched(option2, value) { - var _this$getOptionLabel; - return this.isValidOption(option2) && ((_this$getOptionLabel = this.getOptionLabel(option2)) === null || _this$getOptionLabel === void 0 ? void 0 : _this$getOptionLabel.toLocaleLowerCase(this.searchLocale)) === value.toLocaleLowerCase(this.searchLocale); - }, "isOptionMatched"), - isValidOption: /* @__PURE__ */ __name(function isValidOption(option2) { - return isNotEmpty(option2) && !(this.isOptionDisabled(option2) || this.isOptionGroup(option2)); - }, "isValidOption"), - isValidSelectedOption: /* @__PURE__ */ __name(function isValidSelectedOption(option2) { - return this.isValidOption(option2) && this.isSelected(option2); - }, "isValidSelectedOption"), - isEquals: /* @__PURE__ */ __name(function isEquals(value1, value2) { - return equals(value1, value2, this.equalityKey); - }, "isEquals"), - isSelected: /* @__PURE__ */ __name(function isSelected(option2) { - var _this8 = this; - var optionValue = this.getOptionValue(option2); - return this.multiple ? (this.modelValue || []).some(function(value) { - return _this8.isEquals(value, optionValue); - }) : this.isEquals(this.modelValue, this.getOptionValue(option2)); - }, "isSelected"), - findFirstOptionIndex: /* @__PURE__ */ __name(function findFirstOptionIndex() { - var _this9 = this; - return this.visibleOptions.findIndex(function(option2) { - return _this9.isValidOption(option2); - }); - }, "findFirstOptionIndex"), - findLastOptionIndex: /* @__PURE__ */ __name(function findLastOptionIndex() { - var _this10 = this; - return findLastIndex(this.visibleOptions, function(option2) { - return _this10.isValidOption(option2); - }); - }, "findLastOptionIndex"), - findNextOptionIndex: /* @__PURE__ */ __name(function findNextOptionIndex(index2) { - var _this11 = this; - var matchedOptionIndex = index2 < this.visibleOptions.length - 1 ? this.visibleOptions.slice(index2 + 1).findIndex(function(option2) { - return _this11.isValidOption(option2); - }) : -1; - return matchedOptionIndex > -1 ? matchedOptionIndex + index2 + 1 : index2; - }, "findNextOptionIndex"), - findPrevOptionIndex: /* @__PURE__ */ __name(function findPrevOptionIndex(index2) { - var _this12 = this; - var matchedOptionIndex = index2 > 0 ? findLastIndex(this.visibleOptions.slice(0, index2), function(option2) { - return _this12.isValidOption(option2); - }) : -1; - return matchedOptionIndex > -1 ? matchedOptionIndex : index2; - }, "findPrevOptionIndex"), - findSelectedOptionIndex: /* @__PURE__ */ __name(function findSelectedOptionIndex() { - var _this13 = this; - return this.hasSelectedOption ? this.visibleOptions.findIndex(function(option2) { - return _this13.isValidSelectedOption(option2); - }) : -1; - }, "findSelectedOptionIndex"), - findFirstFocusedOptionIndex: /* @__PURE__ */ __name(function findFirstFocusedOptionIndex() { - var selectedIndex = this.findSelectedOptionIndex(); - return selectedIndex < 0 ? this.findFirstOptionIndex() : selectedIndex; - }, "findFirstFocusedOptionIndex"), - findLastFocusedOptionIndex: /* @__PURE__ */ __name(function findLastFocusedOptionIndex() { - var selectedIndex = this.findSelectedOptionIndex(); - return selectedIndex < 0 ? this.findLastOptionIndex() : selectedIndex; - }, "findLastFocusedOptionIndex"), - search: /* @__PURE__ */ __name(function search(event, query, source) { - if (query === void 0 || query === null) { - return; - } - if (source === "input" && query.trim().length === 0) { - return; - } - this.searching = true; - this.$emit("complete", { - originalEvent: event, - query - }); - }, "search"), - removeOption: /* @__PURE__ */ __name(function removeOption(event, index2) { - var _this14 = this; - var removedOption = this.modelValue[index2]; - var value = this.modelValue.filter(function(_2, i) { - return i !== index2; - }).map(function(option2) { - return _this14.getOptionValue(option2); - }); - this.updateModel(event, value); - this.$emit("item-unselect", { - originalEvent: event, - value: removedOption - }); - this.$emit("option-unselect", { - originalEvent: event, - value: removedOption - }); - this.dirty = true; - focus(this.multiple ? this.$refs.focusInput : this.$refs.focusInput.$el); - }, "removeOption"), - changeFocusedOptionIndex: /* @__PURE__ */ __name(function changeFocusedOptionIndex(event, index2) { - if (this.focusedOptionIndex !== index2) { - this.focusedOptionIndex = index2; - this.scrollInView(); - if (this.selectOnFocus) { - this.onOptionSelect(event, this.visibleOptions[index2], false); - } - } - }, "changeFocusedOptionIndex"), - scrollInView: /* @__PURE__ */ __name(function scrollInView() { - var _this15 = this; - var index2 = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : -1; - this.$nextTick(function() { - var id = index2 !== -1 ? "".concat(_this15.id, "_").concat(index2) : _this15.focusedOptionId; - var element = findSingle(_this15.list, 'li[id="'.concat(id, '"]')); - if (element) { - element.scrollIntoView && element.scrollIntoView({ - block: "nearest", - inline: "start" - }); - } else if (!_this15.virtualScrollerDisabled) { - _this15.virtualScroller && _this15.virtualScroller.scrollToIndex(index2 !== -1 ? index2 : _this15.focusedOptionIndex); - } - }); - }, "scrollInView"), - autoUpdateModel: /* @__PURE__ */ __name(function autoUpdateModel() { - if (this.selectOnFocus && this.autoOptionFocus && !this.hasSelectedOption) { - this.focusedOptionIndex = this.findFirstFocusedOptionIndex(); - this.onOptionSelect(null, this.visibleOptions[this.focusedOptionIndex], false); - } - }, "autoUpdateModel"), - updateModel: /* @__PURE__ */ __name(function updateModel(event, value) { - this.$emit("update:modelValue", value); - this.$emit("change", { - originalEvent: event, - value - }); - }, "updateModel"), - flatOptions: /* @__PURE__ */ __name(function flatOptions(options) { - var _this16 = this; - return (options || []).reduce(function(result, option2, index2) { - result.push({ - optionGroup: option2, - group: true, - index: index2 - }); - var optionGroupChildren = _this16.getOptionGroupChildren(option2); - optionGroupChildren && optionGroupChildren.forEach(function(o) { - return result.push(o); - }); - return result; - }, []); - }, "flatOptions"), - overlayRef: /* @__PURE__ */ __name(function overlayRef(el) { - this.overlay = el; - }, "overlayRef"), - listRef: /* @__PURE__ */ __name(function listRef(el, contentRef) { - this.list = el; - contentRef && contentRef(el); - }, "listRef"), - virtualScrollerRef: /* @__PURE__ */ __name(function virtualScrollerRef(el) { - this.virtualScroller = el; - }, "virtualScrollerRef") - }, - computed: { - visibleOptions: /* @__PURE__ */ __name(function visibleOptions() { - return this.optionGroupLabel ? this.flatOptions(this.suggestions) : this.suggestions || []; - }, "visibleOptions"), - inputValue: /* @__PURE__ */ __name(function inputValue() { - if (isNotEmpty(this.modelValue)) { - if (_typeof$1$3(this.modelValue) === "object") { - var label3 = this.getOptionLabel(this.modelValue); - return label3 != null ? label3 : this.modelValue; - } else { - return this.modelValue; - } - } else { - return ""; - } - }, "inputValue"), - hasSelectedOption: /* @__PURE__ */ __name(function hasSelectedOption() { - return isNotEmpty(this.modelValue); - }, "hasSelectedOption"), - equalityKey: /* @__PURE__ */ __name(function equalityKey() { - return this.dataKey; - }, "equalityKey"), - searchResultMessageText: /* @__PURE__ */ __name(function searchResultMessageText() { - return isNotEmpty(this.visibleOptions) && this.overlayVisible ? this.searchMessageText.replaceAll("{0}", this.visibleOptions.length) : this.emptySearchMessageText; - }, "searchResultMessageText"), - searchMessageText: /* @__PURE__ */ __name(function searchMessageText() { - return this.searchMessage || this.$primevue.config.locale.searchMessage || ""; - }, "searchMessageText"), - emptySearchMessageText: /* @__PURE__ */ __name(function emptySearchMessageText() { - return this.emptySearchMessage || this.$primevue.config.locale.emptySearchMessage || ""; - }, "emptySearchMessageText"), - selectionMessageText: /* @__PURE__ */ __name(function selectionMessageText() { - return this.selectionMessage || this.$primevue.config.locale.selectionMessage || ""; - }, "selectionMessageText"), - emptySelectionMessageText: /* @__PURE__ */ __name(function emptySelectionMessageText() { - return this.emptySelectionMessage || this.$primevue.config.locale.emptySelectionMessage || ""; - }, "emptySelectionMessageText"), - selectedMessageText: /* @__PURE__ */ __name(function selectedMessageText() { - return this.hasSelectedOption ? this.selectionMessageText.replaceAll("{0}", this.multiple ? this.modelValue.length : "1") : this.emptySelectionMessageText; - }, "selectedMessageText"), - listAriaLabel: /* @__PURE__ */ __name(function listAriaLabel() { - return this.$primevue.config.locale.aria ? this.$primevue.config.locale.aria.listLabel : void 0; - }, "listAriaLabel"), - focusedOptionId: /* @__PURE__ */ __name(function focusedOptionId() { - return this.focusedOptionIndex !== -1 ? "".concat(this.id, "_").concat(this.focusedOptionIndex) : null; - }, "focusedOptionId"), - focusedMultipleOptionId: /* @__PURE__ */ __name(function focusedMultipleOptionId() { - return this.focusedMultipleOptionIndex !== -1 ? "".concat(this.id, "_multiple_option_").concat(this.focusedMultipleOptionIndex) : null; - }, "focusedMultipleOptionId"), - ariaSetSize: /* @__PURE__ */ __name(function ariaSetSize() { - var _this17 = this; - return this.visibleOptions.filter(function(option2) { - return !_this17.isOptionGroup(option2); - }).length; - }, "ariaSetSize"), - virtualScrollerDisabled: /* @__PURE__ */ __name(function virtualScrollerDisabled() { - return !this.virtualScrollerOptions; - }, "virtualScrollerDisabled"), - panelId: /* @__PURE__ */ __name(function panelId() { - return this.id + "_panel"; - }, "panelId"), - hasFluid: /* @__PURE__ */ __name(function hasFluid() { - return isEmpty(this.fluid) ? !!this.$pcFluid : this.fluid; - }, "hasFluid") - }, - components: { - InputText: script$m, - VirtualScroller: script$q, - Portal: script$r, - ChevronDownIcon: script$s, - SpinnerIcon: script$t, - Chip: script$u - }, - directives: { - ripple: Ripple - } -}; -function _typeof$7(o) { - "@babel/helpers - typeof"; - return _typeof$7 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o2) { - return typeof o2; - } : function(o2) { - return o2 && "function" == typeof Symbol && o2.constructor === Symbol && o2 !== Symbol.prototype ? "symbol" : typeof o2; - }, _typeof$7(o); -} -__name(_typeof$7, "_typeof$7"); -function ownKeys$8(e, r) { - var t = Object.keys(e); - if (Object.getOwnPropertySymbols) { - var o = Object.getOwnPropertySymbols(e); - r && (o = o.filter(function(r2) { - return Object.getOwnPropertyDescriptor(e, r2).enumerable; - })), t.push.apply(t, o); - } - return t; -} -__name(ownKeys$8, "ownKeys$8"); -function _objectSpread$8(e) { - for (var r = 1; r < arguments.length; r++) { - var t = null != arguments[r] ? arguments[r] : {}; - r % 2 ? ownKeys$8(Object(t), true).forEach(function(r2) { - _defineProperty$7(e, r2, t[r2]); - }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$8(Object(t)).forEach(function(r2) { - Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2)); - }); - } - return e; -} -__name(_objectSpread$8, "_objectSpread$8"); -function _defineProperty$7(e, r, t) { - return (r = _toPropertyKey$6(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: true, configurable: true, writable: true }) : e[r] = t, e; -} -__name(_defineProperty$7, "_defineProperty$7"); -function _toPropertyKey$6(t) { - var i = _toPrimitive$6(t, "string"); - return "symbol" == _typeof$7(i) ? i : i + ""; -} -__name(_toPropertyKey$6, "_toPropertyKey$6"); -function _toPrimitive$6(t, r) { - if ("object" != _typeof$7(t) || !t) return t; - var e = t[Symbol.toPrimitive]; - if (void 0 !== e) { - var i = e.call(t, r || "default"); - if ("object" != _typeof$7(i)) return i; - throw new TypeError("@@toPrimitive must return a primitive value."); - } - return ("string" === r ? String : Number)(t); -} -__name(_toPrimitive$6, "_toPrimitive$6"); -var _hoisted_1$C = ["aria-activedescendant"]; -var _hoisted_2$s = ["id", "aria-label", "aria-setsize", "aria-posinset"]; -var _hoisted_3$l = ["id", "placeholder", "tabindex", "disabled", "aria-label", "aria-labelledby", "aria-expanded", "aria-controls", "aria-activedescendant", "aria-invalid"]; -var _hoisted_4$e = ["disabled", "aria-expanded", "aria-controls"]; -var _hoisted_5$a = ["id"]; -var _hoisted_6$8 = ["id", "aria-label"]; -var _hoisted_7$5 = ["id"]; -var _hoisted_8$4 = ["id", "aria-label", "aria-selected", "aria-disabled", "aria-setsize", "aria-posinset", "onClick", "onMousemove", "data-p-selected", "data-p-focus", "data-p-disabled"]; -function render$j(_ctx, _cache, $props, $setup, $data, $options) { - var _component_InputText = resolveComponent("InputText"); - var _component_Chip = resolveComponent("Chip"); - var _component_SpinnerIcon = resolveComponent("SpinnerIcon"); - var _component_VirtualScroller = resolveComponent("VirtualScroller"); - var _component_Portal = resolveComponent("Portal"); - var _directive_ripple = resolveDirective("ripple"); - return openBlock(), createElementBlock("div", mergeProps({ - ref: "container", - "class": _ctx.cx("root"), - style: _ctx.sx("root"), - onClick: _cache[11] || (_cache[11] = function() { - return $options.onContainerClick && $options.onContainerClick.apply($options, arguments); - }) - }, _ctx.ptmi("root")), [!_ctx.multiple ? (openBlock(), createBlock(_component_InputText, { - key: 0, - ref: "focusInput", - id: _ctx.inputId, - type: "text", - "class": normalizeClass([_ctx.cx("pcInput"), _ctx.inputClass]), - style: normalizeStyle(_ctx.inputStyle), - value: $options.inputValue, - placeholder: _ctx.placeholder, - tabindex: !_ctx.disabled ? _ctx.tabindex : -1, - fluid: $options.hasFluid, - disabled: _ctx.disabled, - invalid: _ctx.invalid, - variant: _ctx.variant, - autocomplete: "off", - role: "combobox", - "aria-label": _ctx.ariaLabel, - "aria-labelledby": _ctx.ariaLabelledby, - "aria-haspopup": "listbox", - "aria-autocomplete": "list", - "aria-expanded": $data.overlayVisible, - "aria-controls": $options.panelId, - "aria-activedescendant": $data.focused ? $options.focusedOptionId : void 0, - onFocus: $options.onFocus, - onBlur: $options.onBlur, - onKeydown: $options.onKeyDown, - onInput: $options.onInput, - onChange: $options.onChange, - unstyled: _ctx.unstyled, - pt: _ctx.ptm("pcInput") - }, null, 8, ["id", "class", "style", "value", "placeholder", "tabindex", "fluid", "disabled", "invalid", "variant", "aria-label", "aria-labelledby", "aria-expanded", "aria-controls", "aria-activedescendant", "onFocus", "onBlur", "onKeydown", "onInput", "onChange", "unstyled", "pt"])) : createCommentVNode("", true), _ctx.multiple ? (openBlock(), createElementBlock("ul", mergeProps({ - key: 1, - ref: "multiContainer", - "class": _ctx.cx("inputMultiple"), - tabindex: "-1", - role: "listbox", - "aria-orientation": "horizontal", - "aria-activedescendant": $data.focused ? $options.focusedMultipleOptionId : void 0, - onFocus: _cache[5] || (_cache[5] = function() { - return $options.onMultipleContainerFocus && $options.onMultipleContainerFocus.apply($options, arguments); - }), - onBlur: _cache[6] || (_cache[6] = function() { - return $options.onMultipleContainerBlur && $options.onMultipleContainerBlur.apply($options, arguments); - }), - onKeydown: _cache[7] || (_cache[7] = function() { - return $options.onMultipleContainerKeyDown && $options.onMultipleContainerKeyDown.apply($options, arguments); - }) - }, _ctx.ptm("inputMultiple")), [(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.modelValue, function(option2, i) { - return openBlock(), createElementBlock("li", mergeProps({ - key: "".concat(i, "_").concat($options.getOptionLabel(option2)), - id: $data.id + "_multiple_option_" + i, - "class": _ctx.cx("chipItem", { - i - }), - role: "option", - "aria-label": $options.getOptionLabel(option2), - "aria-selected": true, - "aria-setsize": _ctx.modelValue.length, - "aria-posinset": i + 1, - ref_for: true - }, _ctx.ptm("chipItem")), [renderSlot(_ctx.$slots, "chip", mergeProps({ - "class": _ctx.cx("pcChip"), - value: option2, - index: i, - removeCallback: /* @__PURE__ */ __name(function removeCallback(event) { - return $options.removeOption(event, i); - }, "removeCallback"), - ref_for: true - }, _ctx.ptm("pcChip")), function() { - return [createVNode(_component_Chip, { - "class": normalizeClass(_ctx.cx("pcChip")), - label: $options.getOptionLabel(option2), - removeIcon: _ctx.chipIcon || _ctx.removeTokenIcon, - removable: "", - unstyled: _ctx.unstyled, - onRemove: /* @__PURE__ */ __name(function onRemove2($event) { - return $options.removeOption($event, i); - }, "onRemove"), - pt: _ctx.ptm("pcChip") - }, { - removeicon: withCtx(function() { - return [renderSlot(_ctx.$slots, _ctx.$slots.chipicon ? "chipicon" : "removetokenicon", { - "class": normalizeClass(_ctx.cx("chipIcon")), - index: i, - removeCallback: /* @__PURE__ */ __name(function removeCallback(event) { - return $options.removeOption(event, i); - }, "removeCallback") - })]; - }), - _: 2 - }, 1032, ["class", "label", "removeIcon", "unstyled", "onRemove", "pt"])]; - })], 16, _hoisted_2$s); - }), 128)), createBaseVNode("li", mergeProps({ - "class": _ctx.cx("inputChip"), - role: "option" - }, _ctx.ptm("inputChip")), [createBaseVNode("input", mergeProps({ - ref: "focusInput", - id: _ctx.inputId, - type: "text", - style: _ctx.inputStyle, - "class": _ctx.inputClass, - placeholder: _ctx.placeholder, - tabindex: !_ctx.disabled ? _ctx.tabindex : -1, - disabled: _ctx.disabled, - autocomplete: "off", - role: "combobox", - "aria-label": _ctx.ariaLabel, - "aria-labelledby": _ctx.ariaLabelledby, - "aria-haspopup": "listbox", - "aria-autocomplete": "list", - "aria-expanded": $data.overlayVisible, - "aria-controls": $data.id + "_list", - "aria-activedescendant": $data.focused ? $options.focusedOptionId : void 0, - "aria-invalid": _ctx.invalid || void 0, - onFocus: _cache[0] || (_cache[0] = function() { - return $options.onFocus && $options.onFocus.apply($options, arguments); - }), - onBlur: _cache[1] || (_cache[1] = function() { - return $options.onBlur && $options.onBlur.apply($options, arguments); - }), - onKeydown: _cache[2] || (_cache[2] = function() { - return $options.onKeyDown && $options.onKeyDown.apply($options, arguments); - }), - onInput: _cache[3] || (_cache[3] = function() { - return $options.onInput && $options.onInput.apply($options, arguments); - }), - onChange: _cache[4] || (_cache[4] = function() { - return $options.onChange && $options.onChange.apply($options, arguments); - }) - }, _ctx.ptm("input")), null, 16, _hoisted_3$l)], 16)], 16, _hoisted_1$C)) : createCommentVNode("", true), $data.searching || _ctx.loading ? renderSlot(_ctx.$slots, _ctx.$slots.loader ? "loader" : "loadingicon", { - key: 2, - "class": normalizeClass(_ctx.cx("loader")) - }, function() { - return [_ctx.loader || _ctx.loadingIcon ? (openBlock(), createElementBlock("i", mergeProps({ - key: 0, - "class": ["pi-spin", _ctx.cx("loader"), _ctx.loader, _ctx.loadingIcon], - "aria-hidden": "true" - }, _ctx.ptm("loader")), null, 16)) : (openBlock(), createBlock(_component_SpinnerIcon, mergeProps({ - key: 1, - "class": _ctx.cx("loader"), - spin: "", - "aria-hidden": "true" - }, _ctx.ptm("loader")), null, 16, ["class"]))]; - }) : createCommentVNode("", true), renderSlot(_ctx.$slots, _ctx.$slots.dropdown ? "dropdown" : "dropdownbutton", { - toggleCallback: /* @__PURE__ */ __name(function toggleCallback(event) { - return $options.onDropdownClick(event); - }, "toggleCallback") - }, function() { - return [_ctx.dropdown ? (openBlock(), createElementBlock("button", mergeProps({ - key: 0, - ref: "dropdownButton", - type: "button", - "class": [_ctx.cx("dropdown"), _ctx.dropdownClass], - disabled: _ctx.disabled, - "aria-haspopup": "listbox", - "aria-expanded": $data.overlayVisible, - "aria-controls": $options.panelId, - onClick: _cache[8] || (_cache[8] = function() { - return $options.onDropdownClick && $options.onDropdownClick.apply($options, arguments); - }) - }, _ctx.ptm("dropdown")), [renderSlot(_ctx.$slots, "dropdownicon", { - "class": normalizeClass(_ctx.dropdownIcon) - }, function() { - return [(openBlock(), createBlock(resolveDynamicComponent(_ctx.dropdownIcon ? "span" : "ChevronDownIcon"), mergeProps({ - "class": _ctx.dropdownIcon - }, _ctx.ptm("dropdownIcon")), null, 16, ["class"]))]; - })], 16, _hoisted_4$e)) : createCommentVNode("", true)]; - }), createBaseVNode("span", mergeProps({ - role: "status", - "aria-live": "polite", - "class": "p-hidden-accessible" - }, _ctx.ptm("hiddenSearchResult"), { - "data-p-hidden-accessible": true - }), toDisplayString($options.searchResultMessageText), 17), createVNode(_component_Portal, { - appendTo: _ctx.appendTo - }, { - "default": withCtx(function() { - return [createVNode(Transition, mergeProps({ - name: "p-connected-overlay", - onEnter: $options.onOverlayEnter, - onAfterEnter: $options.onOverlayAfterEnter, - onLeave: $options.onOverlayLeave, - onAfterLeave: $options.onOverlayAfterLeave - }, _ctx.ptm("transition")), { - "default": withCtx(function() { - return [$data.overlayVisible ? (openBlock(), createElementBlock("div", mergeProps({ - key: 0, - ref: $options.overlayRef, - id: $options.panelId, - "class": [_ctx.cx("overlay"), _ctx.panelClass, _ctx.overlayClass], - style: _objectSpread$8(_objectSpread$8(_objectSpread$8({}, _ctx.panelStyle), _ctx.overlayStyle), {}, { - "max-height": $options.virtualScrollerDisabled ? _ctx.scrollHeight : "" - }), - onClick: _cache[9] || (_cache[9] = function() { - return $options.onOverlayClick && $options.onOverlayClick.apply($options, arguments); - }), - onKeydown: _cache[10] || (_cache[10] = function() { - return $options.onOverlayKeyDown && $options.onOverlayKeyDown.apply($options, arguments); - }) - }, _ctx.ptm("overlay")), [renderSlot(_ctx.$slots, "header", { - value: _ctx.modelValue, - suggestions: $options.visibleOptions - }), createVNode(_component_VirtualScroller, mergeProps({ - ref: $options.virtualScrollerRef - }, _ctx.virtualScrollerOptions, { - style: { - height: _ctx.scrollHeight - }, - items: $options.visibleOptions, - tabindex: -1, - disabled: $options.virtualScrollerDisabled, - pt: _ctx.ptm("virtualScroller") - }), createSlots({ - content: withCtx(function(_ref) { - var styleClass = _ref.styleClass, contentRef = _ref.contentRef, items = _ref.items, getItemOptions = _ref.getItemOptions, contentStyle = _ref.contentStyle, itemSize = _ref.itemSize; - return [createBaseVNode("ul", mergeProps({ - ref: /* @__PURE__ */ __name(function ref2(el) { - return $options.listRef(el, contentRef); - }, "ref"), - id: $data.id + "_list", - "class": [_ctx.cx("list"), styleClass], - style: contentStyle, - role: "listbox", - "aria-label": $options.listAriaLabel - }, _ctx.ptm("list")), [(openBlock(true), createElementBlock(Fragment, null, renderList(items, function(option2, i) { - return openBlock(), createElementBlock(Fragment, { - key: $options.getOptionRenderKey(option2, $options.getOptionIndex(i, getItemOptions)) - }, [$options.isOptionGroup(option2) ? (openBlock(), createElementBlock("li", mergeProps({ - key: 0, - id: $data.id + "_" + $options.getOptionIndex(i, getItemOptions), - style: { - height: itemSize ? itemSize + "px" : void 0 - }, - "class": _ctx.cx("optionGroup"), - role: "option", - ref_for: true - }, _ctx.ptm("optionGroup")), [renderSlot(_ctx.$slots, "optiongroup", { - option: option2.optionGroup, - index: $options.getOptionIndex(i, getItemOptions) - }, function() { - return [createTextVNode(toDisplayString($options.getOptionGroupLabel(option2.optionGroup)), 1)]; - })], 16, _hoisted_7$5)) : withDirectives((openBlock(), createElementBlock("li", mergeProps({ - key: 1, - id: $data.id + "_" + $options.getOptionIndex(i, getItemOptions), - style: { - height: itemSize ? itemSize + "px" : void 0 - }, - "class": _ctx.cx("option", { - option: option2, - i, - getItemOptions - }), - role: "option", - "aria-label": $options.getOptionLabel(option2), - "aria-selected": $options.isSelected(option2), - "aria-disabled": $options.isOptionDisabled(option2), - "aria-setsize": $options.ariaSetSize, - "aria-posinset": $options.getAriaPosInset($options.getOptionIndex(i, getItemOptions)), - onClick: /* @__PURE__ */ __name(function onClick2($event) { - return $options.onOptionSelect($event, option2); - }, "onClick"), - onMousemove: /* @__PURE__ */ __name(function onMousemove($event) { - return $options.onOptionMouseMove($event, $options.getOptionIndex(i, getItemOptions)); - }, "onMousemove"), - "data-p-selected": $options.isSelected(option2), - "data-p-focus": $data.focusedOptionIndex === $options.getOptionIndex(i, getItemOptions), - "data-p-disabled": $options.isOptionDisabled(option2), - ref_for: true - }, $options.getPTOptions(option2, getItemOptions, i, "option")), [renderSlot(_ctx.$slots, "option", { - option: option2, - index: $options.getOptionIndex(i, getItemOptions) - }, function() { - return [createTextVNode(toDisplayString($options.getOptionLabel(option2)), 1)]; - })], 16, _hoisted_8$4)), [[_directive_ripple]])], 64); - }), 128)), !items || items && items.length === 0 ? (openBlock(), createElementBlock("li", mergeProps({ - key: 0, - "class": _ctx.cx("emptyMessage"), - role: "option" - }, _ctx.ptm("emptyMessage")), [renderSlot(_ctx.$slots, "empty", {}, function() { - return [createTextVNode(toDisplayString($options.searchResultMessageText), 1)]; - })], 16)) : createCommentVNode("", true)], 16, _hoisted_6$8)]; - }), - _: 2 - }, [_ctx.$slots.loader ? { - name: "loader", - fn: withCtx(function(_ref2) { - var options = _ref2.options; - return [renderSlot(_ctx.$slots, "loader", { - options - })]; - }), - key: "0" - } : void 0]), 1040, ["style", "items", "disabled", "pt"]), renderSlot(_ctx.$slots, "footer", { - value: _ctx.modelValue, - suggestions: $options.visibleOptions - }), createBaseVNode("span", mergeProps({ - role: "status", - "aria-live": "polite", - "class": "p-hidden-accessible" - }, _ctx.ptm("hiddenSelectedMessage"), { - "data-p-hidden-accessible": true - }), toDisplayString($options.selectedMessageText), 17)], 16, _hoisted_5$a)) : createCommentVNode("", true)]; - }), - _: 3 - }, 16, ["onEnter", "onAfterEnter", "onLeave", "onAfterLeave"])]; - }), - _: 3 - }, 8, ["appendTo"])], 16); -} -__name(render$j, "render$j"); -script$i.render = render$j; -const _sfc_main$B = { - name: "AutoCompletePlus", - extends: script$i, - emits: ["focused-option-changed"], - mounted() { - if (typeof script$i.mounted === "function") { - script$i.mounted.call(this); - } - this.$watch( - () => this.focusedOptionIndex, - (newVal, oldVal) => { - this.$emit("focused-option-changed", newVal); - } - ); - } -}; -var theme$e = /* @__PURE__ */ __name(function theme4(_ref) { - var dt = _ref.dt; - return "\n.p-togglebutton {\n display: inline-flex;\n cursor: pointer;\n user-select: none;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n position: relative;\n color: ".concat(dt("togglebutton.color"), ";\n background: ").concat(dt("togglebutton.background"), ";\n border: 1px solid ").concat(dt("togglebutton.border.color"), ";\n padding: ").concat(dt("togglebutton.padding"), ";\n font-size: 1rem;\n font-family: inherit;\n font-feature-settings: inherit;\n transition: background ").concat(dt("togglebutton.transition.duration"), ", color ").concat(dt("togglebutton.transition.duration"), ", border-color ").concat(dt("togglebutton.transition.duration"), ",\n outline-color ").concat(dt("togglebutton.transition.duration"), ", box-shadow ").concat(dt("togglebutton.transition.duration"), ";\n border-radius: ").concat(dt("togglebutton.border.radius"), ";\n outline-color: transparent;\n font-weight: ").concat(dt("togglebutton.font.weight"), ";\n}\n\n.p-togglebutton-content {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: ").concat(dt("togglebutton.gap"), ';\n}\n\n.p-togglebutton-label,\n.p-togglebutton-icon {\n position: relative;\n transition: none;\n}\n\n.p-togglebutton::before {\n content: "";\n background: transparent;\n transition: background ').concat(dt("togglebutton.transition.duration"), ", color ").concat(dt("togglebutton.transition.duration"), ", border-color ").concat(dt("togglebutton.transition.duration"), ",\n outline-color ").concat(dt("togglebutton.transition.duration"), ", box-shadow ").concat(dt("togglebutton.transition.duration"), ";\n position: absolute;\n left: ").concat(dt("togglebutton.content.left"), ";\n top: ").concat(dt("togglebutton.content.top"), ";\n width: calc(100% - calc(2 * ").concat(dt("togglebutton.content.left"), "));\n height: calc(100% - calc(2 * ").concat(dt("togglebutton.content.top"), "));\n border-radius: ").concat(dt("togglebutton.border.radius"), ";\n}\n\n.p-togglebutton.p-togglebutton-checked::before {\n background: ").concat(dt("togglebutton.content.checked.background"), ";\n box-shadow: ").concat(dt("togglebutton.content.checked.shadow"), ";\n}\n\n.p-togglebutton:not(:disabled):not(.p-togglebutton-checked):hover {\n background: ").concat(dt("togglebutton.hover.background"), ";\n color: ").concat(dt("togglebutton.hover.color"), ";\n}\n\n.p-togglebutton.p-togglebutton-checked {\n background: ").concat(dt("togglebutton.checked.background"), ";\n border-color: ").concat(dt("togglebutton.checked.border.color"), ";\n color: ").concat(dt("togglebutton.checked.color"), ";\n}\n\n.p-togglebutton:focus-visible {\n box-shadow: ").concat(dt("togglebutton.focus.ring.shadow"), ";\n outline: ").concat(dt("togglebutton.focus.ring.width"), " ").concat(dt("togglebutton.focus.ring.style"), " ").concat(dt("togglebutton.focus.ring.color"), ";\n outline-offset: ").concat(dt("togglebutton.focus.ring.offset"), ";\n}\n\n.p-togglebutton.p-invalid {\n border-color: ").concat(dt("togglebutton.invalid.border.color"), ";\n}\n\n.p-togglebutton:disabled {\n opacity: 1;\n cursor: default;\n background: ").concat(dt("togglebutton.disabled.background"), ";\n border-color: ").concat(dt("togglebutton.disabled.border.color"), ";\n color: ").concat(dt("togglebutton.disabled.color"), ";\n}\n\n.p-togglebutton-icon {\n color: ").concat(dt("togglebutton.icon.color"), ";\n}\n\n.p-togglebutton:not(:disabled):not(.p-togglebutton-checked):hover .p-togglebutton-icon {\n color: ").concat(dt("togglebutton.icon.hover.color"), ";\n}\n\n.p-togglebutton.p-togglebutton-checked .p-togglebutton-icon {\n color: ").concat(dt("togglebutton.icon.checked.color"), ";\n}\n\n.p-togglebutton:disabled .p-togglebutton-icon {\n color: ").concat(dt("togglebutton.icon.disabled.color"), ";\n}\n"); -}, "theme"); -var classes$e = { - root: /* @__PURE__ */ __name(function root5(_ref2) { - var instance = _ref2.instance, props = _ref2.props; - return ["p-togglebutton p-component", { - "p-togglebutton-checked": instance.active, - "p-invalid": props.invalid - }]; - }, "root"), - content: "p-togglebutton-content", - icon: "p-togglebutton-icon", - label: "p-togglebutton-label" -}; -var ToggleButtonStyle = BaseStyle.extend({ - name: "togglebutton", - theme: theme$e, - classes: classes$e -}); -var script$1$e = { - name: "BaseToggleButton", - "extends": script$p, - props: { - modelValue: Boolean, - onIcon: String, - offIcon: String, - onLabel: { - type: String, - "default": "Yes" - }, - offLabel: { - type: String, - "default": "No" - }, - iconPos: { - type: String, - "default": "left" - }, - invalid: { - type: Boolean, - "default": false - }, - disabled: { - type: Boolean, - "default": false - }, - readonly: { - type: Boolean, - "default": false - }, - tabindex: { - type: Number, - "default": null - }, - ariaLabelledby: { - type: String, - "default": null - }, - ariaLabel: { - type: String, - "default": null - } - }, - style: ToggleButtonStyle, - provide: /* @__PURE__ */ __name(function provide6() { - return { - $pcToggleButton: this, - $parentInstance: this - }; - }, "provide") -}; -var script$h = { - name: "ToggleButton", - "extends": script$1$e, - inheritAttrs: false, - emits: ["update:modelValue", "change"], - methods: { - getPTOptions: /* @__PURE__ */ __name(function getPTOptions4(key) { - var _ptm = key === "root" ? this.ptmi : this.ptm; - return _ptm(key, { - context: { - active: this.active, - disabled: this.disabled - } - }); - }, "getPTOptions"), - onChange: /* @__PURE__ */ __name(function onChange2(event) { - if (!this.disabled && !this.readonly) { - this.$emit("update:modelValue", !this.modelValue); - this.$emit("change", event); - } - }, "onChange") - }, - computed: { - active: /* @__PURE__ */ __name(function active() { - return this.modelValue === true; - }, "active"), - hasLabel: /* @__PURE__ */ __name(function hasLabel() { - return isNotEmpty(this.onLabel) && isNotEmpty(this.offLabel); - }, "hasLabel"), - label: /* @__PURE__ */ __name(function label() { - return this.hasLabel ? this.modelValue ? this.onLabel : this.offLabel : " "; - }, "label") - }, - directives: { - ripple: Ripple - } -}; -var _hoisted_1$B = ["tabindex", "disabled", "aria-pressed", "data-p-checked", "data-p-disabled"]; -function render$i(_ctx, _cache, $props, $setup, $data, $options) { - var _directive_ripple = resolveDirective("ripple"); - return withDirectives((openBlock(), createElementBlock("button", mergeProps({ - type: "button", - "class": _ctx.cx("root"), - tabindex: _ctx.tabindex, - disabled: _ctx.disabled, - "aria-pressed": _ctx.modelValue, - onClick: _cache[0] || (_cache[0] = function() { - return $options.onChange && $options.onChange.apply($options, arguments); - }) - }, $options.getPTOptions("root"), { - "data-p-checked": $options.active, - "data-p-disabled": _ctx.disabled - }), [createBaseVNode("span", mergeProps({ - "class": _ctx.cx("content") - }, $options.getPTOptions("content")), [renderSlot(_ctx.$slots, "default", {}, function() { - return [renderSlot(_ctx.$slots, "icon", { - value: _ctx.modelValue, - "class": normalizeClass(_ctx.cx("icon")) - }, function() { - return [_ctx.onIcon || _ctx.offIcon ? (openBlock(), createElementBlock("span", mergeProps({ - key: 0, - "class": [_ctx.cx("icon"), _ctx.modelValue ? _ctx.onIcon : _ctx.offIcon] - }, $options.getPTOptions("icon")), null, 16)) : createCommentVNode("", true)]; - }), createBaseVNode("span", mergeProps({ - "class": _ctx.cx("label") - }, $options.getPTOptions("label")), toDisplayString($options.label), 17)]; - })], 16)], 16, _hoisted_1$B)), [[_directive_ripple]]); -} -__name(render$i, "render$i"); -script$h.render = render$i; -var theme$d = /* @__PURE__ */ __name(function theme5(_ref) { - var dt = _ref.dt; - return "\n.p-selectbutton {\n display: inline-flex;\n user-select: none;\n vertical-align: bottom;\n outline-color: transparent;\n border-radius: ".concat(dt("selectbutton.border.radius"), ";\n}\n\n.p-selectbutton .p-togglebutton {\n border-radius: 0;\n border-width: 1px 1px 1px 0;\n}\n\n.p-selectbutton .p-togglebutton:focus-visible {\n position: relative;\n z-index: 1;\n}\n\n.p-selectbutton .p-togglebutton:first-child {\n border-left-width: 1px;\n border-top-left-radius: ").concat(dt("selectbutton.border.radius"), ";\n border-bottom-left-radius: ").concat(dt("selectbutton.border.radius"), ";\n}\n\n.p-selectbutton .p-togglebutton:last-child {\n border-top-right-radius: ").concat(dt("selectbutton.border.radius"), ";\n border-bottom-right-radius: ").concat(dt("selectbutton.border.radius"), ";\n}\n\n.p-selectbutton.p-invalid {\n outline: 1px solid ").concat(dt("selectbutton.invalid.border.color"), ";\n outline-offset: 0;\n}\n"); -}, "theme"); -var classes$d = { - root: /* @__PURE__ */ __name(function root6(_ref2) { - var props = _ref2.props; - return ["p-selectbutton p-component", { - "p-invalid": props.invalid - }]; - }, "root") -}; -var SelectButtonStyle = BaseStyle.extend({ - name: "selectbutton", - theme: theme$d, - classes: classes$d -}); -var script$1$d = { - name: "BaseSelectButton", - "extends": script$p, - props: { - modelValue: null, - options: Array, - optionLabel: null, - optionValue: null, - optionDisabled: null, - multiple: Boolean, - allowEmpty: { - type: Boolean, - "default": true - }, - invalid: { - type: Boolean, - "default": false - }, - disabled: Boolean, - dataKey: null, - ariaLabelledby: { - type: String, - "default": null - } - }, - style: SelectButtonStyle, - provide: /* @__PURE__ */ __name(function provide7() { - return { - $pcSelectButton: this, - $parentInstance: this - }; - }, "provide") -}; -function _createForOfIteratorHelper$4(r, e) { - var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; - if (!t) { - if (Array.isArray(r) || (t = _unsupportedIterableToArray$7(r)) || e) { - t && (r = t); - var _n = 0, F = /* @__PURE__ */ __name(function F2() { - }, "F"); - return { s: F, n: /* @__PURE__ */ __name(function n() { - return _n >= r.length ? { done: true } : { done: false, value: r[_n++] }; - }, "n"), e: /* @__PURE__ */ __name(function e2(r2) { - throw r2; - }, "e"), f: F }; - } - throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); - } - var o, a = true, u = false; - return { s: /* @__PURE__ */ __name(function s() { - t = t.call(r); - }, "s"), n: /* @__PURE__ */ __name(function n() { - var r2 = t.next(); - return a = r2.done, r2; - }, "n"), e: /* @__PURE__ */ __name(function e2(r2) { - u = true, o = r2; - }, "e"), f: /* @__PURE__ */ __name(function f() { - try { - a || null == t["return"] || t["return"](); - } finally { - if (u) throw o; - } - }, "f") }; -} -__name(_createForOfIteratorHelper$4, "_createForOfIteratorHelper$4"); -function _toConsumableArray$5(r) { - return _arrayWithoutHoles$5(r) || _iterableToArray$5(r) || _unsupportedIterableToArray$7(r) || _nonIterableSpread$5(); -} -__name(_toConsumableArray$5, "_toConsumableArray$5"); -function _nonIterableSpread$5() { - throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); -} -__name(_nonIterableSpread$5, "_nonIterableSpread$5"); -function _unsupportedIterableToArray$7(r, a) { - if (r) { - if ("string" == typeof r) return _arrayLikeToArray$7(r, a); - var t = {}.toString.call(r).slice(8, -1); - return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray$7(r, a) : void 0; - } -} -__name(_unsupportedIterableToArray$7, "_unsupportedIterableToArray$7"); -function _iterableToArray$5(r) { - if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); -} -__name(_iterableToArray$5, "_iterableToArray$5"); -function _arrayWithoutHoles$5(r) { - if (Array.isArray(r)) return _arrayLikeToArray$7(r); -} -__name(_arrayWithoutHoles$5, "_arrayWithoutHoles$5"); -function _arrayLikeToArray$7(r, a) { - (null == a || a > r.length) && (a = r.length); - for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; - return n; -} -__name(_arrayLikeToArray$7, "_arrayLikeToArray$7"); -var script$g = { - name: "SelectButton", - "extends": script$1$d, - inheritAttrs: false, - emits: ["update:modelValue", "change"], - methods: { - getOptionLabel: /* @__PURE__ */ __name(function getOptionLabel2(option2) { - return this.optionLabel ? resolveFieldData(option2, this.optionLabel) : option2; - }, "getOptionLabel"), - getOptionValue: /* @__PURE__ */ __name(function getOptionValue2(option2) { - return this.optionValue ? resolveFieldData(option2, this.optionValue) : option2; - }, "getOptionValue"), - getOptionRenderKey: /* @__PURE__ */ __name(function getOptionRenderKey2(option2) { - return this.dataKey ? resolveFieldData(option2, this.dataKey) : this.getOptionLabel(option2); - }, "getOptionRenderKey"), - getPTOptions: /* @__PURE__ */ __name(function getPTOptions5(option2, key) { - return this.ptm(key, { - context: { - active: this.isSelected(option2), - disabled: this.isOptionDisabled(option2), - option: option2 - } - }); - }, "getPTOptions"), - isOptionDisabled: /* @__PURE__ */ __name(function isOptionDisabled2(option2) { - return this.optionDisabled ? resolveFieldData(option2, this.optionDisabled) : false; - }, "isOptionDisabled"), - onOptionSelect: /* @__PURE__ */ __name(function onOptionSelect2(event, option2, index2) { - var _this = this; - if (this.disabled || this.isOptionDisabled(option2)) { - return; - } - var selected2 = this.isSelected(option2); - if (selected2 && !this.allowEmpty) { - return; - } - var optionValue = this.getOptionValue(option2); - var newValue; - if (this.multiple) { - if (selected2) newValue = this.modelValue.filter(function(val) { - return !equals(val, optionValue, _this.equalityKey); - }); - else newValue = this.modelValue ? [].concat(_toConsumableArray$5(this.modelValue), [optionValue]) : [optionValue]; - } else { - newValue = selected2 ? null : optionValue; - } - this.focusedIndex = index2; - this.$emit("update:modelValue", newValue); - this.$emit("change", { - event, - value: newValue - }); - }, "onOptionSelect"), - isSelected: /* @__PURE__ */ __name(function isSelected2(option2) { - var selected2 = false; - var optionValue = this.getOptionValue(option2); - if (this.multiple) { - if (this.modelValue) { - var _iterator = _createForOfIteratorHelper$4(this.modelValue), _step; - try { - for (_iterator.s(); !(_step = _iterator.n()).done; ) { - var val = _step.value; - if (equals(val, optionValue, this.equalityKey)) { - selected2 = true; - break; - } - } - } catch (err) { - _iterator.e(err); - } finally { - _iterator.f(); - } - } - } else { - selected2 = equals(this.modelValue, optionValue, this.equalityKey); - } - return selected2; - }, "isSelected") - }, - computed: { - equalityKey: /* @__PURE__ */ __name(function equalityKey2() { - return this.optionValue ? null : this.dataKey; - }, "equalityKey") - }, - directives: { - ripple: Ripple - }, - components: { - ToggleButton: script$h - } -}; -var _hoisted_1$A = ["aria-labelledby"]; -function render$h(_ctx, _cache, $props, $setup, $data, $options) { - var _component_ToggleButton = resolveComponent("ToggleButton"); - return openBlock(), createElementBlock("div", mergeProps({ - "class": _ctx.cx("root"), - role: "group", - "aria-labelledby": _ctx.ariaLabelledby - }, _ctx.ptmi("root")), [(openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.options, function(option2, index2) { - return openBlock(), createBlock(_component_ToggleButton, { - key: $options.getOptionRenderKey(option2), - modelValue: $options.isSelected(option2), - onLabel: $options.getOptionLabel(option2), - offLabel: $options.getOptionLabel(option2), - disabled: _ctx.disabled || $options.isOptionDisabled(option2), - unstyled: _ctx.unstyled, - onChange: /* @__PURE__ */ __name(function onChange3($event) { - return $options.onOptionSelect($event, option2, index2); - }, "onChange"), - pt: _ctx.ptm("pcButton") - }, createSlots({ - _: 2 - }, [_ctx.$slots.option ? { - name: "default", - fn: withCtx(function() { - return [renderSlot(_ctx.$slots, "option", { - option: option2, - index: index2 - }, function() { - return [createBaseVNode("span", mergeProps({ - ref_for: true - }, _ctx.ptm("pcButton")["label"]), toDisplayString($options.getOptionLabel(option2)), 17)]; - })]; - }), - key: "0" - } : void 0]), 1032, ["modelValue", "onLabel", "offLabel", "disabled", "unstyled", "onChange", "pt"]); - }), 128))], 16, _hoisted_1$A); -} -__name(render$h, "render$h"); -script$g.render = render$h; -const _withScopeId$j = /* @__PURE__ */ __name((n) => (pushScopeId("data-v-e7b35fd9"), n = n(), popScopeId(), n), "_withScopeId$j"); -const _hoisted_1$z = { class: "_content" }; -const _hoisted_2$r = { class: "_footer" }; -const _sfc_main$A = /* @__PURE__ */ defineComponent({ - __name: "NodeSearchFilter", - emits: ["addFilter"], - setup(__props, { emit: __emit }) { - const filters = computed(() => nodeDefStore.nodeSearchService.nodeFilters); - const selectedFilter = ref(); - const filterValues = computed(() => selectedFilter.value?.fuseSearch.data ?? []); - const selectedFilterValue = ref(""); - const nodeDefStore = useNodeDefStore(); - onMounted(() => { - selectedFilter.value = nodeDefStore.nodeSearchService.nodeFilters[0]; - updateSelectedFilterValue(); - }); - const emit = __emit; - const updateSelectedFilterValue = /* @__PURE__ */ __name(() => { - if (filterValues.value.includes(selectedFilterValue.value)) { - return; - } - selectedFilterValue.value = filterValues.value[0]; - }, "updateSelectedFilterValue"); - const submit = /* @__PURE__ */ __name(() => { - emit("addFilter", [ - selectedFilter.value, - selectedFilterValue.value - ]); - }, "submit"); - return (_ctx, _cache) => { - return openBlock(), createElementBlock(Fragment, null, [ - createBaseVNode("div", _hoisted_1$z, [ - createVNode(unref(script$g), { - class: "filter-type-select", - modelValue: selectedFilter.value, - "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => selectedFilter.value = $event), - options: filters.value, - allowEmpty: false, - optionLabel: "name", - onChange: updateSelectedFilterValue - }, null, 8, ["modelValue", "options"]), - createVNode(unref(script$v), { - class: "filter-value-select", - modelValue: selectedFilterValue.value, - "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => selectedFilterValue.value = $event), - options: filterValues.value, - filter: "" - }, null, 8, ["modelValue", "options"]) - ]), - createBaseVNode("div", _hoisted_2$r, [ - createVNode(unref(script$o), { - type: "button", - label: _ctx.$t("add"), - onClick: submit - }, null, 8, ["label"]) - ]) - ], 64); - }; - } -}); -const NodeSearchFilter = /* @__PURE__ */ _export_sfc(_sfc_main$A, [["__scopeId", "data-v-e7b35fd9"]]); -const BOOKMARK_SETTING_ID = "Comfy.NodeLibrary.Bookmarks.V2"; -const useNodeBookmarkStore = defineStore("nodeBookmark", () => { - const settingStore = useSettingStore(); - const nodeDefStore = useNodeDefStore(); - const migrateLegacyBookmarks = /* @__PURE__ */ __name(() => { - settingStore.get("Comfy.NodeLibrary.Bookmarks").forEach((bookmark) => { - if (bookmark.endsWith("/")) { - addBookmark(bookmark); - return; - } - const category = bookmark.split("/").slice(0, -1).join("/"); - const displayName = bookmark.split("/").pop(); - const nodeDef = nodeDefStore.nodeDefsByDisplayName[displayName]; - if (!nodeDef) return; - addBookmark(`${category === "" ? "" : category + "/"}${nodeDef.name}`); - }); - settingStore.set("Comfy.NodeLibrary.Bookmarks", []); - }, "migrateLegacyBookmarks"); - const bookmarks = computed( - () => settingStore.get(BOOKMARK_SETTING_ID) - ); - const bookmarksSet = computed(() => new Set(bookmarks.value)); - const bookmarkedRoot = computed( - () => buildBookmarkTree(bookmarks.value) - ); - const isBookmarked = /* @__PURE__ */ __name((node2) => bookmarksSet.value.has(node2.nodePath) || bookmarksSet.value.has(node2.name), "isBookmarked"); - const toggleBookmark = /* @__PURE__ */ __name((node2) => { - if (isBookmarked(node2)) { - deleteBookmark(node2.nodePath); - deleteBookmark(node2.name); - } else { - addBookmark(node2.name); - } - }, "toggleBookmark"); - const buildBookmarkTree = /* @__PURE__ */ __name((bookmarks2) => { - const bookmarkNodes = bookmarks2.map((bookmark) => { - if (bookmark.endsWith("/")) return createDummyFolderNodeDef(bookmark); - const parts = bookmark.split("/"); - const name = parts.pop(); - const category = parts.join("/"); - const srcNodeDef = nodeDefStore.nodeDefsByName[name]; - if (!srcNodeDef) { - return null; - } - const nodeDef = _.clone(srcNodeDef); - nodeDef.category = category; - return nodeDef; - }).filter((nodeDef) => nodeDef !== null); - return buildNodeDefTree(bookmarkNodes); - }, "buildBookmarkTree"); - const addBookmark = /* @__PURE__ */ __name((nodePath) => { - settingStore.set(BOOKMARK_SETTING_ID, [...bookmarks.value, nodePath]); - }, "addBookmark"); - const deleteBookmark = /* @__PURE__ */ __name((nodePath) => { - settingStore.set( - BOOKMARK_SETTING_ID, - bookmarks.value.filter((b) => b !== nodePath) - ); - }, "deleteBookmark"); - const addNewBookmarkFolder = /* @__PURE__ */ __name((parent) => { - const parentPath = parent ? parent.nodePath : ""; - let newFolderPath = parentPath + "New Folder/"; - let suffix = 1; - while (bookmarks.value.some((b) => b.startsWith(newFolderPath))) { - newFolderPath = parentPath + `New Folder ${suffix}/`; - suffix++; - } - addBookmark(newFolderPath); - return newFolderPath; - }, "addNewBookmarkFolder"); - const renameBookmarkFolder = /* @__PURE__ */ __name((folderNode, newName) => { - if (!folderNode.isDummyFolder) { - throw new Error("Cannot rename non-folder node"); - } - const newNodePath = folderNode.category.split("/").slice(0, -1).concat(newName).join("/") + "/"; - if (newNodePath === folderNode.nodePath) { - return; - } - if (bookmarks.value.some((b) => b.startsWith(newNodePath))) { - throw new Error(`Folder name "${newNodePath}" already exists`); - } - settingStore.set( - BOOKMARK_SETTING_ID, - bookmarks.value.map( - (b) => b.startsWith(folderNode.nodePath) ? b.replace(folderNode.nodePath, newNodePath) : b - ) - ); - renameBookmarkCustomization(folderNode.nodePath, newNodePath); - }, "renameBookmarkFolder"); - const deleteBookmarkFolder = /* @__PURE__ */ __name((folderNode) => { - if (!folderNode.isDummyFolder) { - throw new Error("Cannot delete non-folder node"); - } - settingStore.set( - BOOKMARK_SETTING_ID, - bookmarks.value.filter( - (b) => b !== folderNode.nodePath && !b.startsWith(folderNode.nodePath) - ) - ); - deleteBookmarkCustomization(folderNode.nodePath); - }, "deleteBookmarkFolder"); - const bookmarksCustomization = computed(() => settingStore.get("Comfy.NodeLibrary.BookmarksCustomization")); - const updateBookmarkCustomization = /* @__PURE__ */ __name((nodePath, customization) => { - const currentCustomization = bookmarksCustomization.value[nodePath] || {}; - const newCustomization = { ...currentCustomization, ...customization }; - if (newCustomization.icon === defaultBookmarkIcon) { - delete newCustomization.icon; - } - if (newCustomization.color === defaultBookmarkColor) { - delete newCustomization.color; - } - if (Object.keys(newCustomization).length === 0) { - deleteBookmarkCustomization(nodePath); - } else { - settingStore.set("Comfy.NodeLibrary.BookmarksCustomization", { - ...bookmarksCustomization.value, - [nodePath]: newCustomization - }); - } - }, "updateBookmarkCustomization"); - const deleteBookmarkCustomization = /* @__PURE__ */ __name((nodePath) => { - settingStore.set("Comfy.NodeLibrary.BookmarksCustomization", { - ...bookmarksCustomization.value, - [nodePath]: void 0 - }); - }, "deleteBookmarkCustomization"); - const renameBookmarkCustomization = /* @__PURE__ */ __name((oldNodePath, newNodePath) => { - const updatedCustomization = { ...bookmarksCustomization.value }; - if (updatedCustomization[oldNodePath]) { - updatedCustomization[newNodePath] = updatedCustomization[oldNodePath]; - delete updatedCustomization[oldNodePath]; - } - settingStore.set( - "Comfy.NodeLibrary.BookmarksCustomization", - updatedCustomization - ); - }, "renameBookmarkCustomization"); - const defaultBookmarkIcon = "pi-bookmark-fill"; - const defaultBookmarkColor = "#a1a1aa"; - return { - bookmarks, - bookmarkedRoot, - isBookmarked, - toggleBookmark, - addBookmark, - addNewBookmarkFolder, - renameBookmarkFolder, - deleteBookmarkFolder, - bookmarksCustomization, - updateBookmarkCustomization, - deleteBookmarkCustomization, - renameBookmarkCustomization, - defaultBookmarkIcon, - defaultBookmarkColor, - migrateLegacyBookmarks - }; -}); -const _withScopeId$i = /* @__PURE__ */ __name((n) => (pushScopeId("data-v-37f672ab"), n = n(), popScopeId(), n), "_withScopeId$i"); -const _hoisted_1$y = { class: "option-container flex justify-between items-center px-2 py-0 cursor-pointer overflow-hidden w-full" }; -const _hoisted_2$q = { class: "option-display-name font-semibold flex flex-col" }; -const _hoisted_3$k = { key: 0 }; -const _hoisted_4$d = /* @__PURE__ */ _withScopeId$i(() => /* @__PURE__ */ createBaseVNode("i", { class: "pi pi-bookmark-fill text-sm mr-1" }, null, -1)); -const _hoisted_5$9 = [ - _hoisted_4$d -]; -const _hoisted_6$7 = ["innerHTML"]; -const _hoisted_7$4 = /* @__PURE__ */ _withScopeId$i(() => /* @__PURE__ */ createBaseVNode("span", null, " ", -1)); -const _hoisted_8$3 = ["innerHTML"]; -const _hoisted_9$3 = { - key: 0, - class: "option-category font-light text-sm text-gray-400 overflow-hidden text-ellipsis whitespace-nowrap" -}; -const _hoisted_10$3 = { class: "option-badges" }; -const _sfc_main$z = /* @__PURE__ */ defineComponent({ - __name: "NodeSearchItem", - props: { - nodeDef: {}, - currentQuery: {} - }, - setup(__props) { - const settingStore = useSettingStore(); - const showCategory = computed( - () => settingStore.get("Comfy.NodeSearchBoxImpl.ShowCategory") - ); - const showIdName = computed( - () => settingStore.get("Comfy.NodeSearchBoxImpl.ShowIdName") - ); - const showNodeFrequency = computed( - () => settingStore.get("Comfy.NodeSearchBoxImpl.ShowNodeFrequency") - ); - const nodeFrequencyStore = useNodeFrequencyStore(); - const nodeFrequency = computed( - () => nodeFrequencyStore.getNodeFrequency(props.nodeDef) - ); - const nodeBookmarkStore = useNodeBookmarkStore(); - const isBookmarked = computed( - () => nodeBookmarkStore.isBookmarked(props.nodeDef) - ); - const props = __props; - return (_ctx, _cache) => { - return openBlock(), createElementBlock("div", _hoisted_1$y, [ - createBaseVNode("div", _hoisted_2$q, [ - createBaseVNode("div", null, [ - isBookmarked.value ? (openBlock(), createElementBlock("span", _hoisted_3$k, _hoisted_5$9)) : createCommentVNode("", true), - createBaseVNode("span", { - innerHTML: unref(highlightQuery)(_ctx.nodeDef.display_name, _ctx.currentQuery) - }, null, 8, _hoisted_6$7), - _hoisted_7$4, - showIdName.value ? (openBlock(), createBlock(unref(script$w), { - key: 1, - severity: "secondary" - }, { - default: withCtx(() => [ - createBaseVNode("span", { - innerHTML: unref(highlightQuery)(_ctx.nodeDef.name, _ctx.currentQuery) - }, null, 8, _hoisted_8$3) - ]), - _: 1 - })) : createCommentVNode("", true) - ]), - showCategory.value ? (openBlock(), createElementBlock("div", _hoisted_9$3, toDisplayString(_ctx.nodeDef.category.replaceAll("/", " > ")), 1)) : createCommentVNode("", true) - ]), - createBaseVNode("div", _hoisted_10$3, [ - _ctx.nodeDef.experimental ? (openBlock(), createBlock(unref(script$w), { - key: 0, - value: _ctx.$t("experimental"), - severity: "primary" - }, null, 8, ["value"])) : createCommentVNode("", true), - _ctx.nodeDef.deprecated ? (openBlock(), createBlock(unref(script$w), { - key: 1, - value: _ctx.$t("deprecated"), - severity: "danger" - }, null, 8, ["value"])) : createCommentVNode("", true), - showNodeFrequency.value && nodeFrequency.value > 0 ? (openBlock(), createBlock(unref(script$w), { - key: 2, - value: unref(formatNumberWithSuffix)(nodeFrequency.value, { roundToInt: true }), - severity: "secondary" - }, null, 8, ["value"])) : createCommentVNode("", true), - _ctx.nodeDef.nodeSource.type !== unref(NodeSourceType).Unknown ? (openBlock(), createBlock(unref(script$u), { - key: 3, - class: "text-sm font-light" - }, { - default: withCtx(() => [ - createTextVNode(toDisplayString(_ctx.nodeDef.nodeSource.displayText), 1) - ]), - _: 1 - })) : createCommentVNode("", true) - ]) - ]); - }; - } -}); -const NodeSearchItem = /* @__PURE__ */ _export_sfc(_sfc_main$z, [["__scopeId", "data-v-37f672ab"]]); -const _withScopeId$h = /* @__PURE__ */ __name((n) => (pushScopeId("data-v-ff07c900"), n = n(), popScopeId(), n), "_withScopeId$h"); -const _hoisted_1$x = { class: "_sb_node_preview" }; -const _hoisted_2$p = { class: "_sb_table" }; -const _hoisted_3$j = /* @__PURE__ */ _withScopeId$h(() => /* @__PURE__ */ createBaseVNode("div", { class: "_sb_dot headdot" }, null, -1)); -const _hoisted_4$c = /* @__PURE__ */ _withScopeId$h(() => /* @__PURE__ */ createBaseVNode("div", { class: "_sb_preview_badge" }, "PREVIEW", -1)); -const _hoisted_5$8 = { class: "_sb_col" }; -const _hoisted_6$6 = { class: "_sb_col" }; -const _hoisted_7$3 = /* @__PURE__ */ _withScopeId$h(() => /* @__PURE__ */ createBaseVNode("div", { class: "_sb_col middle-column" }, null, -1)); -const _hoisted_8$2 = { class: "_sb_col" }; -const _hoisted_9$2 = /* @__PURE__ */ _withScopeId$h(() => /* @__PURE__ */ createBaseVNode("div", { class: "_sb_col _sb_arrow" }, "◀", -1)); -const _hoisted_10$2 = /* @__PURE__ */ _withScopeId$h(() => /* @__PURE__ */ createBaseVNode("div", { class: "_sb_col middle-column" }, null, -1)); -const _hoisted_11$2 = /* @__PURE__ */ _withScopeId$h(() => /* @__PURE__ */ createBaseVNode("div", { class: "_sb_col _sb_arrow" }, "▶", -1)); -const _sfc_main$y = /* @__PURE__ */ defineComponent({ - __name: "NodePreview", - props: { - nodeDef: { - type: ComfyNodeDefImpl, - required: true - } - }, - setup(__props) { - const props = __props; - const colors = getColorPalette()?.colors?.litegraph_base; - const litegraphColors = colors ?? defaultColorPalette.colors.litegraph_base; - const nodeDefStore = useNodeDefStore(); - const nodeDef = props.nodeDef; - const allInputDefs = nodeDef.input.all; - const allOutputDefs = nodeDef.output.all; - const slotInputDefs = allInputDefs.filter( - (input) => !nodeDefStore.inputIsWidget(input) - ); - const widgetInputDefs = allInputDefs.filter( - (input) => nodeDefStore.inputIsWidget(input) - ); - const truncateDefaultValue = /* @__PURE__ */ __name((value, charLimit = 32) => { - let stringValue; - if (typeof value === "object" && value !== null) { - stringValue = JSON.stringify(value); - } else if (Array.isArray(value)) { - stringValue = JSON.stringify(value); - } else if (typeof value === "string") { - stringValue = value; - } else { - stringValue = String(value); - } - return _.truncate(stringValue, { length: charLimit }); - }, "truncateDefaultValue"); - return (_ctx, _cache) => { - return openBlock(), createElementBlock("div", _hoisted_1$x, [ - createBaseVNode("div", _hoisted_2$p, [ - createBaseVNode("div", { - class: "node_header", - style: normalizeStyle({ - backgroundColor: unref(litegraphColors).NODE_DEFAULT_COLOR, - color: unref(litegraphColors).NODE_TITLE_COLOR - }) - }, [ - _hoisted_3$j, - createTextVNode(" " + toDisplayString(unref(nodeDef).display_name), 1) - ], 4), - _hoisted_4$c, - (openBlock(true), createElementBlock(Fragment, null, renderList(unref(_).zip(unref(slotInputDefs), unref(allOutputDefs)), ([slotInput, slotOutput]) => { - return openBlock(), createElementBlock("div", { - class: "_sb_row slot_row", - key: (slotInput?.name || "") + (slotOutput?.index.toString() || "") - }, [ - createBaseVNode("div", _hoisted_5$8, [ - slotInput ? (openBlock(), createElementBlock("div", { - key: 0, - class: normalizeClass(["_sb_dot", slotInput.type]) - }, null, 2)) : createCommentVNode("", true) - ]), - createBaseVNode("div", _hoisted_6$6, toDisplayString(slotInput ? slotInput.name : ""), 1), - _hoisted_7$3, - createBaseVNode("div", { - class: "_sb_col _sb_inherit", - style: normalizeStyle({ - color: unref(litegraphColors).NODE_TEXT_COLOR - }) - }, toDisplayString(slotOutput ? slotOutput.name : ""), 5), - createBaseVNode("div", _hoisted_8$2, [ - slotOutput ? (openBlock(), createElementBlock("div", { - key: 0, - class: normalizeClass(["_sb_dot", slotOutput.type]) - }, null, 2)) : createCommentVNode("", true) - ]) - ]); - }), 128)), - (openBlock(true), createElementBlock(Fragment, null, renderList(unref(widgetInputDefs), (widgetInput) => { - return openBlock(), createElementBlock("div", { - class: "_sb_row _long_field", - key: widgetInput.name - }, [ - _hoisted_9$2, - createBaseVNode("div", { - class: "_sb_col", - style: normalizeStyle({ - color: unref(litegraphColors).WIDGET_SECONDARY_TEXT_COLOR - }) - }, toDisplayString(widgetInput.name), 5), - _hoisted_10$2, - createBaseVNode("div", { - class: "_sb_col _sb_inherit", - style: normalizeStyle({ color: unref(litegraphColors).WIDGET_TEXT_COLOR }) - }, toDisplayString(truncateDefaultValue(widgetInput.default)), 5), - _hoisted_11$2 - ]); - }), 128)) - ]), - unref(nodeDef).description ? (openBlock(), createElementBlock("div", { - key: 0, - class: "_sb_description", - style: normalizeStyle({ - color: unref(litegraphColors).WIDGET_SECONDARY_TEXT_COLOR, - backgroundColor: unref(litegraphColors).WIDGET_BGCOLOR - }) - }, toDisplayString(unref(nodeDef).description), 5)) : createCommentVNode("", true) - ]); - }; - } -}); -const NodePreview = /* @__PURE__ */ _export_sfc(_sfc_main$y, [["__scopeId", "data-v-ff07c900"]]); -const _withScopeId$g = /* @__PURE__ */ __name((n) => (pushScopeId("data-v-2d409367"), n = n(), popScopeId(), n), "_withScopeId$g"); -const _hoisted_1$w = { class: "comfy-vue-node-search-container" }; -const _hoisted_2$o = { - key: 0, - class: "comfy-vue-node-preview-container" -}; -const _hoisted_3$i = /* @__PURE__ */ _withScopeId$g(() => /* @__PURE__ */ createBaseVNode("h3", null, "Add node filter condition", -1)); -const _hoisted_4$b = { class: "_dialog-body" }; -const _sfc_main$x = /* @__PURE__ */ defineComponent({ - __name: "NodeSearchBox", - props: { - filters: {}, - searchLimit: { default: 64 } - }, - emits: ["addFilter", "removeFilter", "addNode"], - setup(__props, { emit: __emit }) { - const settingStore = useSettingStore(); - const { t } = useI18n(); - const enableNodePreview = computed( - () => settingStore.get("Comfy.NodeSearchBoxImpl.NodePreview") - ); - const props = __props; - const nodeSearchFilterVisible = ref(false); - const inputId = `comfy-vue-node-search-box-input-${Math.random()}`; - const suggestions2 = ref([]); - const hoveredSuggestion = ref(null); - const currentQuery = ref(""); - const placeholder = computed(() => { - return props.filters.length === 0 ? t("searchNodes") + "..." : ""; - }); - const nodeDefStore = useNodeDefStore(); - const nodeFrequencyStore = useNodeFrequencyStore(); - const search2 = /* @__PURE__ */ __name((query) => { - const queryIsEmpty = query === "" && props.filters.length === 0; - currentQuery.value = query; - suggestions2.value = queryIsEmpty ? nodeFrequencyStore.topNodeDefs : [ - ...nodeDefStore.nodeSearchService.searchNode(query, props.filters, { - limit: props.searchLimit - }) - ]; - }, "search"); - const emit = __emit; - const reFocusInput = /* @__PURE__ */ __name(() => { - const inputElement = document.getElementById(inputId); - if (inputElement) { - inputElement.blur(); - inputElement.focus(); - } - }, "reFocusInput"); - onMounted(reFocusInput); - const onAddFilter = /* @__PURE__ */ __name((filterAndValue) => { - nodeSearchFilterVisible.value = false; - emit("addFilter", filterAndValue); - reFocusInput(); - }, "onAddFilter"); - const onRemoveFilter = /* @__PURE__ */ __name((event, filterAndValue) => { - event.stopPropagation(); - event.preventDefault(); - emit("removeFilter", filterAndValue); - reFocusInput(); - }, "onRemoveFilter"); - const setHoverSuggestion = /* @__PURE__ */ __name((index2) => { - if (index2 === -1) { - hoveredSuggestion.value = null; - return; - } - const value = suggestions2.value[index2]; - hoveredSuggestion.value = value; - }, "setHoverSuggestion"); - return (_ctx, _cache) => { - return openBlock(), createElementBlock("div", _hoisted_1$w, [ - enableNodePreview.value ? (openBlock(), createElementBlock("div", _hoisted_2$o, [ - hoveredSuggestion.value ? (openBlock(), createBlock(NodePreview, { - nodeDef: hoveredSuggestion.value, - key: hoveredSuggestion.value?.name || "" - }, null, 8, ["nodeDef"])) : createCommentVNode("", true) - ])) : createCommentVNode("", true), - createVNode(unref(script$o), { - icon: "pi pi-filter", - severity: "secondary", - class: "_filter-button", - onClick: _cache[0] || (_cache[0] = ($event) => nodeSearchFilterVisible.value = true) - }), - createVNode(unref(script$x), { - visible: nodeSearchFilterVisible.value, - "onUpdate:visible": _cache[1] || (_cache[1] = ($event) => nodeSearchFilterVisible.value = $event), - class: "_dialog" - }, { - header: withCtx(() => [ - _hoisted_3$i - ]), - default: withCtx(() => [ - createBaseVNode("div", _hoisted_4$b, [ - createVNode(NodeSearchFilter, { onAddFilter }) - ]) - ]), - _: 1 - }, 8, ["visible"]), - createVNode(_sfc_main$B, { - "model-value": props.filters, - class: "comfy-vue-node-search-box", - scrollHeight: "40vh", - placeholder: placeholder.value, - "input-id": inputId, - "append-to": "self", - suggestions: suggestions2.value, - "min-length": 0, - delay: 100, - loading: !unref(nodeFrequencyStore).isLoaded, - onComplete: _cache[2] || (_cache[2] = ($event) => search2($event.query)), - onOptionSelect: _cache[3] || (_cache[3] = ($event) => emit("addNode", $event.value)), - onFocusedOptionChanged: _cache[4] || (_cache[4] = ($event) => setHoverSuggestion($event)), - "complete-on-focus": "", - "auto-option-focus": "", - "force-selection": "", - multiple: "", - optionLabel: "display_name" - }, { - option: withCtx(({ option: option2 }) => [ - createVNode(NodeSearchItem, { - nodeDef: option2, - currentQuery: currentQuery.value - }, null, 8, ["nodeDef", "currentQuery"]) - ]), - chip: withCtx(({ value }) => [ - createVNode(SearchFilterChip, { - onRemove: /* @__PURE__ */ __name(($event) => onRemoveFilter($event, value), "onRemove"), - text: value[1], - badge: value[0].invokeSequence.toUpperCase(), - "badge-class": value[0].invokeSequence + "-badge" - }, null, 8, ["onRemove", "text", "badge", "badge-class"]) - ]), - _: 1 - }, 8, ["model-value", "placeholder", "suggestions", "loading"]) - ]); - }; - } -}); -const NodeSearchBox = /* @__PURE__ */ _export_sfc(_sfc_main$x, [["__scopeId", "data-v-2d409367"]]); -class ConnectingLinkImpl { - static { - __name(this, "ConnectingLinkImpl"); - } - node; - slot; - input; - output; - pos; - constructor(node2, slot, input, output, pos) { - this.node = node2; - this.slot = slot; - this.input = input; - this.output = output; - this.pos = pos; - } - static createFromPlainObject(obj) { - return new ConnectingLinkImpl( - obj.node, - obj.slot, - obj.input, - obj.output, - obj.pos - ); - } - get type() { - const result = this.input ? this.input.type : this.output.type; - return result === -1 ? null : result; - } - /** - * Which slot type is release and need to be reconnected. - * - 'output' means we need a new node's outputs slot to connect with this link - */ - get releaseSlotType() { - return this.output ? "input" : "output"; - } - connectTo(newNode) { - const newNodeSlots = this.releaseSlotType === "output" ? newNode.outputs : newNode.inputs; - if (!newNodeSlots) return; - const newNodeSlot = newNodeSlots.findIndex( - (slot) => LiteGraph.isValidConnection(slot.type, this.type) - ); - if (newNodeSlot === -1) { - console.warn( - `Could not find slot with type ${this.type} on node ${newNode.title}. This should never happen` - ); - return; - } - if (this.releaseSlotType === "input") { - this.node.connect(this.slot, newNode, newNodeSlot); - } else { - newNode.connect(newNodeSlot, this.node, this.slot); - } - } -} -const _sfc_main$w = /* @__PURE__ */ defineComponent({ - __name: "NodeSearchBoxPopover", - setup(__props) { - const settingStore = useSettingStore(); - const visible = ref(false); - const dismissable = ref(true); - const triggerEvent = ref(null); - const getNewNodeLocation = /* @__PURE__ */ __name(() => { - if (triggerEvent.value === null) { - return [100, 100]; - } - const originalEvent = triggerEvent.value.detail.originalEvent; - return [originalEvent.canvasX, originalEvent.canvasY]; - }, "getNewNodeLocation"); - const nodeFilters = ref([]); - const addFilter = /* @__PURE__ */ __name((filter) => { - nodeFilters.value.push(filter); - }, "addFilter"); - const removeFilter = /* @__PURE__ */ __name((filter) => { - nodeFilters.value = nodeFilters.value.filter( - (f) => toRaw(f) !== toRaw(filter) - ); - }, "removeFilter"); - const clearFilters = /* @__PURE__ */ __name(() => { - nodeFilters.value = []; - }, "clearFilters"); - const closeDialog = /* @__PURE__ */ __name(() => { - visible.value = false; - }, "closeDialog"); - const addNode = /* @__PURE__ */ __name((nodeDef) => { - const node2 = app.addNodeOnGraph(nodeDef, { pos: getNewNodeLocation() }); - const eventDetail = triggerEvent.value.detail; - if (eventDetail.subType === "empty-release") { - eventDetail.linkReleaseContext.links.forEach((link) => { - ConnectingLinkImpl.createFromPlainObject(link).connectTo(node2); - }); - } - window.setTimeout(() => { - closeDialog(); - }, 100); - }, "addNode"); - const newSearchBoxEnabled = computed( - () => settingStore.get("Comfy.NodeSearchBoxImpl") === "default" - ); - const showSearchBox = /* @__PURE__ */ __name((e) => { - if (newSearchBoxEnabled.value) { - if (e.detail.originalEvent?.pointerType === "touch") { - setTimeout(() => { - showNewSearchBox(e); - }, 128); - } else { - showNewSearchBox(e); - } - } else { - canvasStore.canvas.showSearchBox(e.detail.originalEvent); - } - }, "showSearchBox"); - const nodeDefStore = useNodeDefStore(); - const showNewSearchBox = /* @__PURE__ */ __name((e) => { - if (e.detail.linkReleaseContext) { - const links = e.detail.linkReleaseContext.links; - if (links.length === 0) { - console.warn("Empty release with no links! This should never happen"); - return; - } - const firstLink = ConnectingLinkImpl.createFromPlainObject(links[0]); - const filter = nodeDefStore.nodeSearchService.getFilterById( - firstLink.releaseSlotType - ); - const dataType = firstLink.type; - addFilter([filter, dataType]); - } - visible.value = true; - triggerEvent.value = e; - dismissable.value = false; - setTimeout(() => { - dismissable.value = true; - }, 300); - }, "showNewSearchBox"); - const showContextMenu = /* @__PURE__ */ __name((e) => { - const links = e.detail.linkReleaseContext.links; - if (links.length === 0) { - console.warn("Empty release with no links! This should never happen"); - return; - } - const firstLink = ConnectingLinkImpl.createFromPlainObject(links[0]); - const mouseEvent = e.detail.originalEvent; - const commonOptions = { - e: mouseEvent, - allow_searchbox: true, - showSearchBox: /* @__PURE__ */ __name(() => showSearchBox(e), "showSearchBox") - }; - const connectionOptions = firstLink.output ? { nodeFrom: firstLink.node, slotFrom: firstLink.output } : { nodeTo: firstLink.node, slotTo: firstLink.input }; - canvasStore.canvas.showConnectionMenu({ - ...connectionOptions, - ...commonOptions - }); - }, "showContextMenu"); - const canvasStore = useCanvasStore(); - watchEffect(() => { - if (canvasStore.canvas) { - LiteGraph.release_link_on_empty_shows_menu = false; - canvasStore.canvas.allow_searchbox = false; - } - }); - const canvasEventHandler = /* @__PURE__ */ __name((e) => { - if (e.detail.subType === "empty-double-click") { - showSearchBox(e); - } else if (e.detail.subType === "empty-release") { - handleCanvasEmptyRelease(e); - } else if (e.detail.subType === "group-double-click") { - const group = e.detail.group; - const [x, y] = group.pos; - const relativeY = e.detail.originalEvent.canvasY - y; - if (relativeY > group.titleHeight) { - showSearchBox(e); - } - } - }, "canvasEventHandler"); - const linkReleaseAction = computed(() => { - return settingStore.get("Comfy.LinkRelease.Action"); - }); - const linkReleaseActionShift = computed(() => { - return settingStore.get("Comfy.LinkRelease.ActionShift"); - }); - const handleCanvasEmptyRelease = /* @__PURE__ */ __name((e) => { - const originalEvent = e.detail.originalEvent; - const shiftPressed = originalEvent.shiftKey; - const action = shiftPressed ? linkReleaseActionShift.value : linkReleaseAction.value; - switch (action) { - case LinkReleaseTriggerAction.SEARCH_BOX: - showSearchBox(e); - break; - case LinkReleaseTriggerAction.CONTEXT_MENU: - showContextMenu(e); - break; - case LinkReleaseTriggerAction.NO_ACTION: - default: - break; - } - }, "handleCanvasEmptyRelease"); - onMounted(() => { - document.addEventListener("litegraph:canvas", canvasEventHandler); - }); - onUnmounted(() => { - document.removeEventListener("litegraph:canvas", canvasEventHandler); - }); - return (_ctx, _cache) => { - return openBlock(), createElementBlock("div", null, [ - createVNode(unref(script$x), { - visible: visible.value, - "onUpdate:visible": _cache[0] || (_cache[0] = ($event) => visible.value = $event), - modal: "", - "dismissable-mask": dismissable.value, - onHide: clearFilters, - pt: { - root: { - class: "invisible-dialog-root", - role: "search" - }, - mask: { class: "node-search-box-dialog-mask" }, - transition: { - enterFromClass: "opacity-0 scale-75", - // 100ms is the duration of the transition in the dialog component - enterActiveClass: "transition-all duration-100 ease-out", - leaveActiveClass: "transition-all duration-100 ease-in", - leaveToClass: "opacity-0 scale-75" - } - } - }, { - container: withCtx(() => [ - createVNode(NodeSearchBox, { - filters: nodeFilters.value, - onAddFilter: addFilter, - onRemoveFilter: removeFilter, - onAddNode: addNode - }, null, 8, ["filters"]) - ]), - _: 1 - }, 8, ["visible", "dismissable-mask"]) - ]); - }; - } -}); -const _sfc_main$v = /* @__PURE__ */ defineComponent({ - __name: "NodeTooltip", - setup(__props) { - let idleTimeout; - const nodeDefStore = useNodeDefStore(); - const settingStore = useSettingStore(); - const tooltipRef = ref(); - const tooltipText = ref(""); - const left = ref(); - const top = ref(); - const getHoveredWidget = /* @__PURE__ */ __name(() => { - const node2 = app.canvas.node_over; - if (!node2.widgets) return; - const graphPos = app.canvas.graph_mouse; - const x = graphPos[0] - node2.pos[0]; - const y = graphPos[1] - node2.pos[1]; - for (const w of node2.widgets) { - let widgetWidth, widgetHeight; - if (w.computeSize) { - ; - [widgetWidth, widgetHeight] = w.computeSize(node2.size[0]); - } else { - widgetWidth = w.width || node2.size[0]; - widgetHeight = LiteGraph.NODE_WIDGET_HEIGHT; - } - if (w.last_y !== void 0 && x >= 6 && x <= widgetWidth - 12 && y >= w.last_y && y <= w.last_y + widgetHeight) { - return w; - } - } - }, "getHoveredWidget"); - const hideTooltip = /* @__PURE__ */ __name(() => tooltipText.value = null, "hideTooltip"); - const showTooltip = /* @__PURE__ */ __name(async (tooltip) => { - if (!tooltip) return; - left.value = app.canvas.mouse[0] + "px"; - top.value = app.canvas.mouse[1] + "px"; - tooltipText.value = tooltip; - await nextTick(); - const rect = tooltipRef.value.getBoundingClientRect(); - if (rect.right > window.innerWidth) { - left.value = app.canvas.mouse[0] - rect.width + "px"; - } - if (rect.top < 0) { - top.value = app.canvas.mouse[1] + rect.height + "px"; - } - }, "showTooltip"); - const onIdle = /* @__PURE__ */ __name(() => { - const { canvas } = app; - const node2 = canvas.node_over; - if (!node2) return; - const ctor = node2.constructor; - const nodeDef = nodeDefStore.nodeDefsByName[node2.type]; - if (ctor.title_mode !== LiteGraph.NO_TITLE && canvas.graph_mouse[1] < node2.pos[1]) { - return showTooltip(nodeDef.description); - } - if (node2.flags?.collapsed) return; - const inputSlot = canvas.isOverNodeInput( - node2, - canvas.graph_mouse[0], - canvas.graph_mouse[1], - [0, 0] - ); - if (inputSlot !== -1) { - const inputName = node2.inputs[inputSlot].name; - return showTooltip(nodeDef.input.getInput(inputName)?.tooltip); - } - const outputSlot = canvas.isOverNodeOutput( - node2, - canvas.graph_mouse[0], - canvas.graph_mouse[1], - [0, 0] - ); - if (outputSlot !== -1) { - return showTooltip(nodeDef.output.all?.[outputSlot]?.tooltip); - } - const widget = getHoveredWidget(); - if (widget && !widget.element) { - return showTooltip( - widget.tooltip ?? nodeDef.input.getInput(widget.name)?.tooltip - ); - } - }, "onIdle"); - const onMouseMove = /* @__PURE__ */ __name((e) => { - hideTooltip(); - clearTimeout(idleTimeout); - if (e.target.nodeName !== "CANVAS") return; - idleTimeout = window.setTimeout(onIdle, 500); - }, "onMouseMove"); - watch( - () => settingStore.get("Comfy.EnableTooltips"), - (enabled) => { - if (enabled) { - window.addEventListener("mousemove", onMouseMove); - window.addEventListener("click", hideTooltip); - } else { - window.removeEventListener("mousemove", onMouseMove); - window.removeEventListener("click", hideTooltip); - } - }, - { immediate: true } - ); - onBeforeUnmount(() => { - window.removeEventListener("mousemove", onMouseMove); - window.removeEventListener("click", hideTooltip); - }); - return (_ctx, _cache) => { - return tooltipText.value ? (openBlock(), createElementBlock("div", { - key: 0, - ref_key: "tooltipRef", - ref: tooltipRef, - class: "node-tooltip", - style: normalizeStyle({ left: left.value, top: top.value }) - }, toDisplayString(tooltipText.value), 5)) : createCommentVNode("", true); - }; - } -}); -const NodeTooltip = /* @__PURE__ */ _export_sfc(_sfc_main$v, [["__scopeId", "data-v-0a4402f9"]]); -function _arrayWithHoles(r) { - if (Array.isArray(r)) return r; -} -__name(_arrayWithHoles, "_arrayWithHoles"); -function _iterableToArrayLimit(r, l) { - var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; - if (null != t) { - var e, n, i, u, a = [], f = true, o = false; - try { - if (i = (t = t.call(r)).next, 0 === l) { - if (Object(t) !== t) return; - f = false; - } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = true) ; - } catch (r2) { - o = true, n = r2; - } finally { - try { - if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; - } finally { - if (o) throw n; - } - } - return a; - } -} -__name(_iterableToArrayLimit, "_iterableToArrayLimit"); -function _arrayLikeToArray$6(r, a) { - (null == a || a > r.length) && (a = r.length); - for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; - return n; -} -__name(_arrayLikeToArray$6, "_arrayLikeToArray$6"); -function _unsupportedIterableToArray$6(r, a) { - if (r) { - if ("string" == typeof r) return _arrayLikeToArray$6(r, a); - var t = {}.toString.call(r).slice(8, -1); - return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray$6(r, a) : void 0; - } -} -__name(_unsupportedIterableToArray$6, "_unsupportedIterableToArray$6"); -function _nonIterableRest() { - throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); -} -__name(_nonIterableRest, "_nonIterableRest"); -function _slicedToArray(r, e) { - return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray$6(r, e) || _nonIterableRest(); -} -__name(_slicedToArray, "_slicedToArray"); -var dist = {}; -var bind$1 = {}; -"use strict"; -Object.defineProperty(bind$1, "__esModule", { value: true }); -var bind_2 = bind$1.bind = void 0; -function bind(target, _a) { - var type = _a.type, listener = _a.listener, options = _a.options; - target.addEventListener(type, listener, options); - return /* @__PURE__ */ __name(function unbind() { - target.removeEventListener(type, listener, options); - }, "unbind"); -} -__name(bind, "bind"); -bind_2 = bind$1.bind = bind; -var bindAll$1 = {}; -"use strict"; -var __assign = commonjsGlobal && commonjsGlobal.__assign || function() { - __assign = Object.assign || function(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) - t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); -}; -Object.defineProperty(bindAll$1, "__esModule", { value: true }); -var bindAll_2 = bindAll$1.bindAll = void 0; -var bind_1 = bind$1; -function toOptions(value) { - if (typeof value === "undefined") { - return void 0; - } - if (typeof value === "boolean") { - return { - capture: value - }; - } - return value; -} -__name(toOptions, "toOptions"); -function getBinding(original, sharedOptions) { - if (sharedOptions == null) { - return original; - } - var binding = __assign(__assign({}, original), { options: __assign(__assign({}, toOptions(sharedOptions)), toOptions(original.options)) }); - return binding; -} -__name(getBinding, "getBinding"); -function bindAll(target, bindings, sharedOptions) { - var unbinds = bindings.map(function(original) { - var binding = getBinding(original, sharedOptions); - return (0, bind_1.bind)(target, binding); - }); - return /* @__PURE__ */ __name(function unbindAll() { - unbinds.forEach(function(unbind) { - return unbind(); - }); - }, "unbindAll"); -} -__name(bindAll, "bindAll"); -bindAll_2 = bindAll$1.bindAll = bindAll; -(function(exports) { - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.bindAll = exports.bind = void 0; - var bind_12 = bind$1; - Object.defineProperty(exports, "bind", { enumerable: true, get: /* @__PURE__ */ __name(function() { - return bind_12.bind; - }, "get") }); - var bind_all_1 = bindAll$1; - Object.defineProperty(exports, "bindAll", { enumerable: true, get: /* @__PURE__ */ __name(function() { - return bind_all_1.bindAll; - }, "get") }); -})(dist); -const index = /* @__PURE__ */ getDefaultExportFromCjs(dist); -var honeyPotDataAttribute = "data-pdnd-honey-pot"; -function isHoneyPotElement(target) { - return target instanceof Element && target.hasAttribute(honeyPotDataAttribute); -} -__name(isHoneyPotElement, "isHoneyPotElement"); -function getElementFromPointWithoutHoneypot(client) { - var _document$elementsFro = document.elementsFromPoint(client.x, client.y), _document$elementsFro2 = _slicedToArray(_document$elementsFro, 2), top = _document$elementsFro2[0], second = _document$elementsFro2[1]; - if (!top) { - return null; - } - if (isHoneyPotElement(top)) { - return second !== null && second !== void 0 ? second : null; - } - return top; -} -__name(getElementFromPointWithoutHoneypot, "getElementFromPointWithoutHoneypot"); -function _typeof$6(o) { - "@babel/helpers - typeof"; - return _typeof$6 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o2) { - return typeof o2; - } : function(o2) { - return o2 && "function" == typeof Symbol && o2.constructor === Symbol && o2 !== Symbol.prototype ? "symbol" : typeof o2; - }, _typeof$6(o); -} -__name(_typeof$6, "_typeof$6"); -function toPrimitive(t, r) { - if ("object" != _typeof$6(t) || !t) return t; - var e = t[Symbol.toPrimitive]; - if (void 0 !== e) { - var i = e.call(t, r || "default"); - if ("object" != _typeof$6(i)) return i; - throw new TypeError("@@toPrimitive must return a primitive value."); - } - return ("string" === r ? String : Number)(t); -} -__name(toPrimitive, "toPrimitive"); -function toPropertyKey(t) { - var i = toPrimitive(t, "string"); - return "symbol" == _typeof$6(i) ? i : i + ""; -} -__name(toPropertyKey, "toPropertyKey"); -function _defineProperty$6(e, r, t) { - return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, { - value: t, - enumerable: true, - configurable: true, - writable: true - }) : e[r] = t, e; -} -__name(_defineProperty$6, "_defineProperty$6"); -var maxZIndex = 2147483647; -function ownKeys$7(e, r) { - var t = Object.keys(e); - if (Object.getOwnPropertySymbols) { - var o = Object.getOwnPropertySymbols(e); - r && (o = o.filter(function(r2) { - return Object.getOwnPropertyDescriptor(e, r2).enumerable; - })), t.push.apply(t, o); - } - return t; -} -__name(ownKeys$7, "ownKeys$7"); -function _objectSpread$7(e) { - for (var r = 1; r < arguments.length; r++) { - var t = null != arguments[r] ? arguments[r] : {}; - r % 2 ? ownKeys$7(Object(t), true).forEach(function(r2) { - _defineProperty$6(e, r2, t[r2]); - }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$7(Object(t)).forEach(function(r2) { - Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2)); - }); - } - return e; -} -__name(_objectSpread$7, "_objectSpread$7"); -var honeyPotSize = 2; -var halfHoneyPotSize = honeyPotSize / 2; -function floorToClosestPixel(point) { - return { - x: Math.floor(point.x), - y: Math.floor(point.y) - }; -} -__name(floorToClosestPixel, "floorToClosestPixel"); -function pullBackByHalfHoneyPotSize(point) { - return { - x: point.x - halfHoneyPotSize, - y: point.y - halfHoneyPotSize - }; -} -__name(pullBackByHalfHoneyPotSize, "pullBackByHalfHoneyPotSize"); -function preventGoingBackwardsOffScreen(point) { - return { - x: Math.max(point.x, 0), - y: Math.max(point.y, 0) - }; -} -__name(preventGoingBackwardsOffScreen, "preventGoingBackwardsOffScreen"); -function preventGoingForwardsOffScreen(point) { - return { - x: Math.min(point.x, window.innerWidth - honeyPotSize), - y: Math.min(point.y, window.innerHeight - honeyPotSize) - }; -} -__name(preventGoingForwardsOffScreen, "preventGoingForwardsOffScreen"); -function getHoneyPotRectFor(_ref) { - var client = _ref.client; - var point = preventGoingForwardsOffScreen(preventGoingBackwardsOffScreen(pullBackByHalfHoneyPotSize(floorToClosestPixel(client)))); - return DOMRect.fromRect({ - x: point.x, - y: point.y, - width: honeyPotSize, - height: honeyPotSize - }); -} -__name(getHoneyPotRectFor, "getHoneyPotRectFor"); -function getRectStyles(_ref2) { - var clientRect = _ref2.clientRect; - return { - left: "".concat(clientRect.left, "px"), - top: "".concat(clientRect.top, "px"), - width: "".concat(clientRect.width, "px"), - height: "".concat(clientRect.height, "px") - }; -} -__name(getRectStyles, "getRectStyles"); -function isWithin(_ref3) { - var client = _ref3.client, clientRect = _ref3.clientRect; - return ( - // is within horizontal bounds - client.x >= clientRect.x && client.x <= clientRect.x + clientRect.width && // is within vertical bounds - client.y >= clientRect.y && client.y <= clientRect.y + clientRect.height - ); -} -__name(isWithin, "isWithin"); -function mountHoneyPot(_ref4) { - var initial = _ref4.initial; - var element = document.createElement("div"); - element.setAttribute(honeyPotDataAttribute, "true"); - var clientRect = getHoneyPotRectFor({ - client: initial - }); - Object.assign(element.style, _objectSpread$7(_objectSpread$7({ - // Setting a background color explicitly to avoid any inherited styles. - // Looks like this could be `opacity: 0`, but worried that _might_ - // cause the element to be ignored on some platforms. - // When debugging, set backgroundColor to something like "red". - backgroundColor: "transparent", - position: "fixed", - // Being explicit to avoid inheriting styles - padding: 0, - margin: 0, - boxSizing: "border-box" - }, getRectStyles({ - clientRect - })), {}, { - // We want this element to absorb pointer events, - // it's kind of the whole point 😉 - pointerEvents: "auto", - // Want to make sure the honey pot is top of everything else. - // Don't need to worry about native drag previews, as they will - // have been rendered (and removed) before the honey pot is rendered - zIndex: maxZIndex - })); - document.body.appendChild(element); - var unbindPointerMove = dist.bind(window, { - type: "pointermove", - listener: /* @__PURE__ */ __name(function listener(event) { - var client = { - x: event.clientX, - y: event.clientY - }; - clientRect = getHoneyPotRectFor({ - client - }); - Object.assign(element.style, getRectStyles({ - clientRect - })); - }, "listener"), - // using capture so we are less likely to be impacted by event stopping - options: { - capture: true - } - }); - return /* @__PURE__ */ __name(function finish(_ref5) { - var current = _ref5.current; - unbindPointerMove(); - if (isWithin({ - client: current, - clientRect - })) { - element.remove(); - return; - } - function cleanup() { - unbindPostDragEvents(); - element.remove(); - } - __name(cleanup, "cleanup"); - var unbindPostDragEvents = dist.bindAll(window, [ - { - type: "pointerdown", - listener: cleanup - }, - { - type: "pointermove", - listener: cleanup - }, - { - type: "focusin", - listener: cleanup - }, - { - type: "focusout", - listener: cleanup - }, - // a 'pointerdown' should happen before 'dragstart', but just being super safe - { - type: "dragstart", - listener: cleanup - }, - // if the user has dragged something out of the window - // and then is dragging something back into the window - // the first events we will see are "dragenter" (and then "dragover"). - // So if we see any of these we need to clear the post drag fix. - { - type: "dragenter", - listener: cleanup - }, - { - type: "dragover", - listener: cleanup - } - // Not adding a "wheel" event listener, as "wheel" by itself does not - // resolve the bug. - ], { - // Using `capture` so less likely to be impacted by other code stopping events - capture: true - }); - }, "finish"); -} -__name(mountHoneyPot, "mountHoneyPot"); -function makeHoneyPotFix() { - var latestPointerMove = null; - function bindEvents() { - latestPointerMove = null; - return dist.bind(window, { - type: "pointermove", - listener: /* @__PURE__ */ __name(function listener(event) { - latestPointerMove = { - x: event.clientX, - y: event.clientY - }; - }, "listener"), - // listening for pointer move in capture phase - // so we are less likely to be impacted by events being stopped. - options: { - capture: true - } - }); - } - __name(bindEvents, "bindEvents"); - function getOnPostDispatch() { - var finish = null; - return /* @__PURE__ */ __name(function onPostEvent(_ref6) { - var eventName = _ref6.eventName, payload = _ref6.payload; - if (eventName === "onDragStart") { - var _latestPointerMove; - var input = payload.location.initial.input; - var initial = (_latestPointerMove = latestPointerMove) !== null && _latestPointerMove !== void 0 ? _latestPointerMove : { - x: input.clientX, - y: input.clientY - }; - finish = mountHoneyPot({ - initial - }); - } - if (eventName === "onDrop") { - var _finish; - var _input = payload.location.current.input; - (_finish = finish) === null || _finish === void 0 || _finish({ - current: { - x: _input.clientX, - y: _input.clientY - } - }); - finish = null; - latestPointerMove = null; - } - }, "onPostEvent"); - } - __name(getOnPostDispatch, "getOnPostDispatch"); - return { - bindEvents, - getOnPostDispatch - }; -} -__name(makeHoneyPotFix, "makeHoneyPotFix"); -function _arrayWithoutHoles$4(r) { - if (Array.isArray(r)) return _arrayLikeToArray$6(r); -} -__name(_arrayWithoutHoles$4, "_arrayWithoutHoles$4"); -function _iterableToArray$4(r) { - if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); -} -__name(_iterableToArray$4, "_iterableToArray$4"); -function _nonIterableSpread$4() { - throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); -} -__name(_nonIterableSpread$4, "_nonIterableSpread$4"); -function _toConsumableArray$4(r) { - return _arrayWithoutHoles$4(r) || _iterableToArray$4(r) || _unsupportedIterableToArray$6(r) || _nonIterableSpread$4(); -} -__name(_toConsumableArray$4, "_toConsumableArray$4"); -function once(fn) { - var cache = null; - return /* @__PURE__ */ __name(function wrapped() { - if (!cache) { - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - var result = fn.apply(this, args); - cache = { - result - }; - } - return cache.result; - }, "wrapped"); -} -__name(once, "once"); -var isFirefox = once(/* @__PURE__ */ __name(function isFirefox2() { - if (false) { - return false; - } - return navigator.userAgent.includes("Firefox"); -}, "isFirefox2")); -var isSafari = once(/* @__PURE__ */ __name(function isSafari2() { - if (false) { - return false; - } - var _navigator = navigator, userAgent = _navigator.userAgent; - return userAgent.includes("AppleWebKit") && !userAgent.includes("Chrome"); -}, "isSafari2")); -var symbols = { - isLeavingWindow: Symbol("leaving"), - isEnteringWindow: Symbol("entering") -}; -function isEnteringWindowInSafari(_ref) { - var dragEnter = _ref.dragEnter; - if (!isSafari()) { - return false; - } - return dragEnter.hasOwnProperty(symbols.isEnteringWindow); -} -__name(isEnteringWindowInSafari, "isEnteringWindowInSafari"); -function isLeavingWindowInSafari(_ref2) { - var dragLeave = _ref2.dragLeave; - if (!isSafari()) { - return false; - } - return dragLeave.hasOwnProperty(symbols.isLeavingWindow); -} -__name(isLeavingWindowInSafari, "isLeavingWindowInSafari"); -(/* @__PURE__ */ __name(function fixSafari() { - if (typeof window === "undefined") { - return; - } - if (false) { - return; - } - if (!isSafari()) { - return; - } - function getInitialState() { - return { - enterCount: 0, - isOverWindow: false - }; - } - __name(getInitialState, "getInitialState"); - var state = getInitialState(); - function resetState() { - state = getInitialState(); - } - __name(resetState, "resetState"); - dist.bindAll( - window, - [{ - type: "dragstart", - listener: /* @__PURE__ */ __name(function listener() { - state.enterCount = 0; - state.isOverWindow = true; - }, "listener") - }, { - type: "drop", - listener: resetState - }, { - type: "dragend", - listener: resetState - }, { - type: "dragenter", - listener: /* @__PURE__ */ __name(function listener(event) { - if (!state.isOverWindow && state.enterCount === 0) { - event[symbols.isEnteringWindow] = true; - } - state.isOverWindow = true; - state.enterCount++; - }, "listener") - }, { - type: "dragleave", - listener: /* @__PURE__ */ __name(function listener(event) { - state.enterCount--; - if (state.isOverWindow && state.enterCount === 0) { - event[symbols.isLeavingWindow] = true; - state.isOverWindow = false; - } - }, "listener") - }], - // using `capture: true` so that adding event listeners - // in bubble phase will have the correct symbols - { - capture: true - } - ); -}, "fixSafari"))(); -function isNodeLike(target) { - return "nodeName" in target; -} -__name(isNodeLike, "isNodeLike"); -function isFromAnotherWindow(eventTarget) { - return isNodeLike(eventTarget) && eventTarget.ownerDocument !== document; -} -__name(isFromAnotherWindow, "isFromAnotherWindow"); -function isLeavingWindow(_ref) { - var dragLeave = _ref.dragLeave; - var type = dragLeave.type, relatedTarget = dragLeave.relatedTarget; - if (type !== "dragleave") { - return false; - } - if (isSafari()) { - return isLeavingWindowInSafari({ - dragLeave - }); - } - if (relatedTarget == null) { - return true; - } - if (isFirefox()) { - return isFromAnotherWindow(relatedTarget); - } - return relatedTarget instanceof HTMLIFrameElement; -} -__name(isLeavingWindow, "isLeavingWindow"); -function getBindingsForBrokenDrags(_ref) { - var onDragEnd2 = _ref.onDragEnd; - return [ - // ## Detecting drag ending for removed draggables - // - // If a draggable element is removed during a drag and the user drops: - // 1. if over a valid drop target: we get a "drop" event to know the drag is finished - // 2. if not over a valid drop target (or cancelled): we get nothing - // The "dragend" event will not fire on the source draggable if it has been - // removed from the DOM. - // So we need to figure out if a drag operation has finished by looking at other events - // We can do this by looking at other events - // ### First detection: "pointermove" events - // 1. "pointermove" events cannot fire during a drag and drop operation - // according to the spec. So if we get a "pointermove" it means that - // the drag and drop operations has finished. So if we get a "pointermove" - // we know that the drag is over - // 2. 🦊😤 Drag and drop operations are _supposed_ to suppress - // other pointer events. However, firefox will allow a few - // pointer event to get through after a drag starts. - // The most I've seen is 3 - { - type: "pointermove", - listener: /* @__PURE__ */ function() { - var callCount = 0; - return /* @__PURE__ */ __name(function listener() { - if (callCount < 20) { - callCount++; - return; - } - onDragEnd2(); - }, "listener"); - }() - }, - // ### Second detection: "pointerdown" events - // If we receive this event then we know that a drag operation has finished - // and potentially another one is about to start. - // Note: `pointerdown` fires on all browsers / platforms before "dragstart" - { - type: "pointerdown", - listener: onDragEnd2 - } - ]; -} -__name(getBindingsForBrokenDrags, "getBindingsForBrokenDrags"); -function getInput(event) { - return { - altKey: event.altKey, - button: event.button, - buttons: event.buttons, - ctrlKey: event.ctrlKey, - metaKey: event.metaKey, - shiftKey: event.shiftKey, - clientX: event.clientX, - clientY: event.clientY, - pageX: event.pageX, - pageY: event.pageY - }; -} -__name(getInput, "getInput"); -var rafSchd = /* @__PURE__ */ __name(function rafSchd2(fn) { - var lastArgs = []; - var frameId = null; - var wrapperFn = /* @__PURE__ */ __name(function wrapperFn2() { - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - lastArgs = args; - if (frameId) { - return; - } - frameId = requestAnimationFrame(function() { - frameId = null; - fn.apply(void 0, lastArgs); - }); - }, "wrapperFn"); - wrapperFn.cancel = function() { - if (!frameId) { - return; - } - cancelAnimationFrame(frameId); - frameId = null; - }; - return wrapperFn; -}, "rafSchd"); -var scheduleOnDrag = rafSchd(function(fn) { - return fn(); -}); -var dragStart = /* @__PURE__ */ function() { - var scheduled = null; - function schedule(fn) { - var frameId = requestAnimationFrame(function() { - scheduled = null; - fn(); - }); - scheduled = { - frameId, - fn - }; - } - __name(schedule, "schedule"); - function flush() { - if (scheduled) { - cancelAnimationFrame(scheduled.frameId); - scheduled.fn(); - scheduled = null; - } - } - __name(flush, "flush"); - return { - schedule, - flush - }; -}(); -function makeDispatch(_ref) { - var source = _ref.source, initial = _ref.initial, dispatchEvent = _ref.dispatchEvent; - var previous = { - dropTargets: [] - }; - function safeDispatch(args) { - dispatchEvent(args); - previous = { - dropTargets: args.payload.location.current.dropTargets - }; - } - __name(safeDispatch, "safeDispatch"); - var dispatch = { - start: /* @__PURE__ */ __name(function start2(_ref2) { - var nativeSetDragImage = _ref2.nativeSetDragImage; - var location = { - current: initial, - previous, - initial - }; - safeDispatch({ - eventName: "onGenerateDragPreview", - payload: { - source, - location, - nativeSetDragImage - } - }); - dragStart.schedule(function() { - safeDispatch({ - eventName: "onDragStart", - payload: { - source, - location - } - }); - }); - }, "start"), - dragUpdate: /* @__PURE__ */ __name(function dragUpdate(_ref3) { - var current = _ref3.current; - dragStart.flush(); - scheduleOnDrag.cancel(); - safeDispatch({ - eventName: "onDropTargetChange", - payload: { - source, - location: { - initial, - previous, - current - } - } - }); - }, "dragUpdate"), - drag: /* @__PURE__ */ __name(function drag(_ref4) { - var current = _ref4.current; - scheduleOnDrag(function() { - dragStart.flush(); - var location = { - initial, - previous, - current - }; - safeDispatch({ - eventName: "onDrag", - payload: { - source, - location - } - }); - }); - }, "drag"), - drop: /* @__PURE__ */ __name(function drop(_ref5) { - var current = _ref5.current, updatedSourcePayload = _ref5.updatedSourcePayload; - dragStart.flush(); - scheduleOnDrag.cancel(); - safeDispatch({ - eventName: "onDrop", - payload: { - source: updatedSourcePayload !== null && updatedSourcePayload !== void 0 ? updatedSourcePayload : source, - location: { - current, - previous, - initial - } - } - }); - }, "drop") - }; - return dispatch; -} -__name(makeDispatch, "makeDispatch"); -var globalState = { - isActive: false -}; -function canStart() { - return !globalState.isActive; -} -__name(canStart, "canStart"); -function getNativeSetDragImage(event) { - if (event.dataTransfer) { - return event.dataTransfer.setDragImage.bind(event.dataTransfer); - } - return null; -} -__name(getNativeSetDragImage, "getNativeSetDragImage"); -function hasHierarchyChanged(_ref) { - var current = _ref.current, next2 = _ref.next; - if (current.length !== next2.length) { - return true; - } - for (var i = 0; i < current.length; i++) { - if (current[i].element !== next2[i].element) { - return true; - } - } - return false; -} -__name(hasHierarchyChanged, "hasHierarchyChanged"); -function start(_ref2) { - var event = _ref2.event, dragType = _ref2.dragType, getDropTargetsOver = _ref2.getDropTargetsOver, dispatchEvent = _ref2.dispatchEvent; - if (!canStart()) { - return; - } - var initial = getStartLocation({ - event, - dragType, - getDropTargetsOver - }); - globalState.isActive = true; - var state = { - current: initial - }; - setDropEffectOnEvent({ - event, - current: initial.dropTargets - }); - var dispatch = makeDispatch({ - source: dragType.payload, - dispatchEvent, - initial - }); - function updateState(next2) { - var hasChanged = hasHierarchyChanged({ - current: state.current.dropTargets, - next: next2.dropTargets - }); - state.current = next2; - if (hasChanged) { - dispatch.dragUpdate({ - current: state.current - }); - } - } - __name(updateState, "updateState"); - function onUpdateEvent(event2) { - var input = getInput(event2); - var target = isHoneyPotElement(event2.target) ? getElementFromPointWithoutHoneypot({ - x: input.clientX, - y: input.clientY - }) : event2.target; - var nextDropTargets = getDropTargetsOver({ - target, - input, - source: dragType.payload, - current: state.current.dropTargets - }); - if (nextDropTargets.length) { - event2.preventDefault(); - setDropEffectOnEvent({ - event: event2, - current: nextDropTargets - }); - } - updateState({ - dropTargets: nextDropTargets, - input - }); - } - __name(onUpdateEvent, "onUpdateEvent"); - function cancel() { - if (state.current.dropTargets.length) { - updateState({ - dropTargets: [], - input: state.current.input - }); - } - dispatch.drop({ - current: state.current, - updatedSourcePayload: null - }); - finish(); - } - __name(cancel, "cancel"); - function finish() { - globalState.isActive = false; - unbindEvents(); - } - __name(finish, "finish"); - var unbindEvents = dist.bindAll( - window, - [{ - // 👋 Note: we are repurposing the `dragover` event as our `drag` event - // this is because firefox does not publish pointer coordinates during - // a `drag` event, but does for every other type of drag event - // `dragover` fires on all elements that are being dragged over - // Because we are binding to `window` - our `dragover` is effectively the same as a `drag` - // 🦊😤 - type: "dragover", - listener: /* @__PURE__ */ __name(function listener(event2) { - onUpdateEvent(event2); - dispatch.drag({ - current: state.current - }); - }, "listener") - }, { - type: "dragenter", - listener: onUpdateEvent - }, { - type: "dragleave", - listener: /* @__PURE__ */ __name(function listener(event2) { - if (!isLeavingWindow({ - dragLeave: event2 - })) { - return; - } - updateState({ - input: state.current.input, - dropTargets: [] - }); - if (dragType.startedFrom === "external") { - cancel(); - } - }, "listener") - }, { - // A "drop" can only happen if the browser allowed the drop - type: "drop", - listener: /* @__PURE__ */ __name(function listener(event2) { - state.current = { - dropTargets: state.current.dropTargets, - input: getInput(event2) - }; - if (!state.current.dropTargets.length) { - cancel(); - return; - } - event2.preventDefault(); - setDropEffectOnEvent({ - event: event2, - current: state.current.dropTargets - }); - dispatch.drop({ - current: state.current, - // When dropping something native, we need to extract the latest - // `.items` from the "drop" event as it is now accessible - updatedSourcePayload: dragType.type === "external" ? dragType.getDropPayload(event2) : null - }); - finish(); - }, "listener") - }, { - // "dragend" fires when on the drag source (eg a draggable element) - // when the drag is finished. - // "dragend" will fire after "drop" (if there was a successful drop) - // "dragend" does not fire if the draggable source has been removed during the drag - // or for external drag sources (eg files) - // This "dragend" listener will not fire if there was a successful drop - // as we will have already removed the event listener - type: "dragend", - listener: /* @__PURE__ */ __name(function listener(event2) { - state.current = { - dropTargets: state.current.dropTargets, - input: getInput(event2) - }; - cancel(); - }, "listener") - }].concat(_toConsumableArray$4(getBindingsForBrokenDrags({ - onDragEnd: cancel - }))), - // Once we have started a managed drag operation it is important that we see / own all drag events - // We got one adoption bug pop up where some code was stopping (`event.stopPropagation()`) - // all "drop" events in the bubble phase on the `document.body`. - // This meant that we never saw the "drop" event. - { - capture: true - } - ); - dispatch.start({ - nativeSetDragImage: getNativeSetDragImage(event) - }); -} -__name(start, "start"); -function setDropEffectOnEvent(_ref3) { - var _current$; - var event = _ref3.event, current = _ref3.current; - var innerMost = (_current$ = current[0]) === null || _current$ === void 0 ? void 0 : _current$.dropEffect; - if (innerMost != null && event.dataTransfer) { - event.dataTransfer.dropEffect = innerMost; - } -} -__name(setDropEffectOnEvent, "setDropEffectOnEvent"); -function getStartLocation(_ref4) { - var event = _ref4.event, dragType = _ref4.dragType, getDropTargetsOver = _ref4.getDropTargetsOver; - var input = getInput(event); - if (dragType.startedFrom === "external") { - return { - input, - dropTargets: [] - }; - } - var dropTargets = getDropTargetsOver({ - input, - source: dragType.payload, - target: event.target, - current: [] - }); - return { - input, - dropTargets - }; -} -__name(getStartLocation, "getStartLocation"); -var lifecycle = { - canStart, - start -}; -var ledger = /* @__PURE__ */ new Map(); -function registerUsage(_ref) { - var typeKey = _ref.typeKey, mount2 = _ref.mount; - var entry = ledger.get(typeKey); - if (entry) { - entry.usageCount++; - return entry; - } - var initial = { - typeKey, - unmount: mount2(), - usageCount: 1 - }; - ledger.set(typeKey, initial); - return initial; -} -__name(registerUsage, "registerUsage"); -function register(args) { - var entry = registerUsage(args); - return /* @__PURE__ */ __name(function unregister() { - entry.usageCount--; - if (entry.usageCount > 0) { - return; - } - entry.unmount(); - ledger.delete(args.typeKey); - }, "unregister"); -} -__name(register, "register"); -function combine() { - for (var _len = arguments.length, fns = new Array(_len), _key = 0; _key < _len; _key++) { - fns[_key] = arguments[_key]; - } - return /* @__PURE__ */ __name(function cleanup() { - fns.forEach(function(fn) { - return fn(); - }); - }, "cleanup"); -} -__name(combine, "combine"); -function addAttribute(element, _ref) { - var attribute = _ref.attribute, value = _ref.value; - element.setAttribute(attribute, value); - return function() { - return element.removeAttribute(attribute); - }; -} -__name(addAttribute, "addAttribute"); -function ownKeys$6(e, r) { - var t = Object.keys(e); - if (Object.getOwnPropertySymbols) { - var o = Object.getOwnPropertySymbols(e); - r && (o = o.filter(function(r2) { - return Object.getOwnPropertyDescriptor(e, r2).enumerable; - })), t.push.apply(t, o); - } - return t; -} -__name(ownKeys$6, "ownKeys$6"); -function _objectSpread$6(e) { - for (var r = 1; r < arguments.length; r++) { - var t = null != arguments[r] ? arguments[r] : {}; - r % 2 ? ownKeys$6(Object(t), true).forEach(function(r2) { - _defineProperty$6(e, r2, t[r2]); - }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$6(Object(t)).forEach(function(r2) { - Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2)); - }); - } - return e; -} -__name(_objectSpread$6, "_objectSpread$6"); -function _createForOfIteratorHelper$3(o, allowArrayLike) { - var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; - if (!it) { - if (Array.isArray(o) || (it = _unsupportedIterableToArray$5(o)) || allowArrayLike && o && typeof o.length === "number") { - if (it) o = it; - var i = 0; - var F = /* @__PURE__ */ __name(function F2() { - }, "F2"); - return { s: F, n: /* @__PURE__ */ __name(function n() { - if (i >= o.length) return { done: true }; - return { done: false, value: o[i++] }; - }, "n"), e: /* @__PURE__ */ __name(function e(_e) { - throw _e; - }, "e"), f: F }; - } - throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); - } - var normalCompletion = true, didErr = false, err; - return { s: /* @__PURE__ */ __name(function s() { - it = it.call(o); - }, "s"), n: /* @__PURE__ */ __name(function n() { - var step2 = it.next(); - normalCompletion = step2.done; - return step2; - }, "n"), e: /* @__PURE__ */ __name(function e(_e2) { - didErr = true; - err = _e2; - }, "e"), f: /* @__PURE__ */ __name(function f() { - try { - if (!normalCompletion && it.return != null) it.return(); - } finally { - if (didErr) throw err; - } - }, "f") }; -} -__name(_createForOfIteratorHelper$3, "_createForOfIteratorHelper$3"); -function _unsupportedIterableToArray$5(o, minLen) { - if (!o) return; - if (typeof o === "string") return _arrayLikeToArray$5(o, minLen); - var n = Object.prototype.toString.call(o).slice(8, -1); - if (n === "Object" && o.constructor) n = o.constructor.name; - if (n === "Map" || n === "Set") return Array.from(o); - if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray$5(o, minLen); -} -__name(_unsupportedIterableToArray$5, "_unsupportedIterableToArray$5"); -function _arrayLikeToArray$5(arr, len) { - if (len == null || len > arr.length) len = arr.length; - for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; - return arr2; -} -__name(_arrayLikeToArray$5, "_arrayLikeToArray$5"); -function copyReverse(array) { - return array.slice(0).reverse(); -} -__name(copyReverse, "copyReverse"); -function makeDropTarget(_ref) { - var typeKey = _ref.typeKey, defaultDropEffect = _ref.defaultDropEffect; - var registry = /* @__PURE__ */ new WeakMap(); - var dropTargetDataAtt = "data-drop-target-for-".concat(typeKey); - var dropTargetSelector = "[".concat(dropTargetDataAtt, "]"); - function addToRegistry2(args) { - registry.set(args.element, args); - return function() { - return registry.delete(args.element); - }; - } - __name(addToRegistry2, "addToRegistry"); - function dropTargetForConsumers(args) { - if (false) { - var existing = registry.get(args.element); - if (existing) { - console.warn("You have already registered a [".concat(typeKey, "] dropTarget on the same element"), { - existing, - proposed: args - }); - } - if (args.element instanceof HTMLIFrameElement) { - console.warn("\n We recommend not registering