mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Merge branch 'main' into pr-labeler
This commit is contained in:
commit
e160cbb1e9
@ -30,6 +30,7 @@ from invokeai.app.invocations.primitives import ImageField, ImageOutput
|
||||
from invokeai.app.invocations.util import validate_begin_end_step, validate_weights
|
||||
from invokeai.app.services.image_records.image_records_common import ImageCategory, ResourceOrigin
|
||||
from invokeai.app.shared.fields import FieldDescriptions
|
||||
from invokeai.backend.image_util.depth_anything import DepthAnythingDetector
|
||||
|
||||
from ...backend.model_management import BaseModelType
|
||||
from .baseinvocation import (
|
||||
@ -602,3 +603,33 @@ class ColorMapImageProcessorInvocation(ImageProcessorInvocation):
|
||||
color_map = cv2.resize(color_map, (width, height), interpolation=cv2.INTER_NEAREST)
|
||||
color_map = Image.fromarray(color_map)
|
||||
return color_map
|
||||
|
||||
|
||||
DEPTH_ANYTHING_MODEL_SIZES = Literal["large", "base", "small"]
|
||||
|
||||
|
||||
@invocation(
|
||||
"depth_anything_image_processor",
|
||||
title="Depth Anything Processor",
|
||||
tags=["controlnet", "depth", "depth anything"],
|
||||
category="controlnet",
|
||||
version="1.0.0",
|
||||
)
|
||||
class DepthAnythingImageProcessorInvocation(ImageProcessorInvocation):
|
||||
"""Generates a depth map based on the Depth Anything algorithm"""
|
||||
|
||||
model_size: DEPTH_ANYTHING_MODEL_SIZES = InputField(
|
||||
default="small", description="The size of the depth model to use"
|
||||
)
|
||||
resolution: int = InputField(default=512, ge=64, multiple_of=64, description=FieldDescriptions.image_res)
|
||||
offload: bool = InputField(default=False)
|
||||
|
||||
def run_processor(self, image):
|
||||
depth_anything_detector = DepthAnythingDetector()
|
||||
depth_anything_detector.load_model(model_size=self.model_size)
|
||||
|
||||
if image.mode == "RGBA":
|
||||
image = image.convert("RGB")
|
||||
|
||||
processed_image = depth_anything_detector(image=image, resolution=self.resolution, offload=self.offload)
|
||||
return processed_image
|
||||
|
@ -31,6 +31,7 @@ class WorkflowRecordOrderBy(str, Enum, metaclass=MetaEnum):
|
||||
class WorkflowCategory(str, Enum, metaclass=MetaEnum):
|
||||
User = "user"
|
||||
Default = "default"
|
||||
Project = "project"
|
||||
|
||||
|
||||
class WorkflowMeta(BaseModel):
|
||||
|
109
invokeai/backend/image_util/depth_anything/__init__.py
Normal file
109
invokeai/backend/image_util/depth_anything/__init__.py
Normal file
@ -0,0 +1,109 @@
|
||||
import pathlib
|
||||
from typing import Literal, Union
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
import torch
|
||||
import torch.nn.functional as F
|
||||
from einops import repeat
|
||||
from PIL import Image
|
||||
from torchvision.transforms import Compose
|
||||
|
||||
from invokeai.app.services.config.config_default import InvokeAIAppConfig
|
||||
from invokeai.backend.image_util.depth_anything.model.dpt import DPT_DINOv2
|
||||
from invokeai.backend.image_util.depth_anything.utilities.util import NormalizeImage, PrepareForNet, Resize
|
||||
from invokeai.backend.util.devices import choose_torch_device
|
||||
from invokeai.backend.util.util import download_with_progress_bar
|
||||
|
||||
config = InvokeAIAppConfig.get_config()
|
||||
|
||||
DEPTH_ANYTHING_MODELS = {
|
||||
"large": {
|
||||
"url": "https://huggingface.co/spaces/LiheYoung/Depth-Anything/resolve/main/checkpoints/depth_anything_vitl14.pth?download=true",
|
||||
"local": "any/annotators/depth_anything/depth_anything_vitl14.pth",
|
||||
},
|
||||
"base": {
|
||||
"url": "https://huggingface.co/spaces/LiheYoung/Depth-Anything/resolve/main/checkpoints/depth_anything_vitb14.pth?download=true",
|
||||
"local": "any/annotators/depth_anything/depth_anything_vitb14.pth",
|
||||
},
|
||||
"small": {
|
||||
"url": "https://huggingface.co/spaces/LiheYoung/Depth-Anything/resolve/main/checkpoints/depth_anything_vits14.pth?download=true",
|
||||
"local": "any/annotators/depth_anything/depth_anything_vits14.pth",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
transform = Compose(
|
||||
[
|
||||
Resize(
|
||||
width=518,
|
||||
height=518,
|
||||
resize_target=False,
|
||||
keep_aspect_ratio=True,
|
||||
ensure_multiple_of=14,
|
||||
resize_method="lower_bound",
|
||||
image_interpolation_method=cv2.INTER_CUBIC,
|
||||
),
|
||||
NormalizeImage(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
|
||||
PrepareForNet(),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class DepthAnythingDetector:
|
||||
def __init__(self) -> None:
|
||||
self.model = None
|
||||
self.model_size: Union[Literal["large", "base", "small"], None] = None
|
||||
|
||||
def load_model(self, model_size=Literal["large", "base", "small"]):
|
||||
DEPTH_ANYTHING_MODEL_PATH = pathlib.Path(config.models_path / DEPTH_ANYTHING_MODELS[model_size]["local"])
|
||||
if not DEPTH_ANYTHING_MODEL_PATH.exists():
|
||||
download_with_progress_bar(DEPTH_ANYTHING_MODELS[model_size]["url"], DEPTH_ANYTHING_MODEL_PATH)
|
||||
|
||||
if not self.model or model_size != self.model_size:
|
||||
del self.model
|
||||
self.model_size = model_size
|
||||
|
||||
match self.model_size:
|
||||
case "small":
|
||||
self.model = DPT_DINOv2(encoder="vits", features=64, out_channels=[48, 96, 192, 384])
|
||||
case "base":
|
||||
self.model = DPT_DINOv2(encoder="vitb", features=128, out_channels=[96, 192, 384, 768])
|
||||
case "large":
|
||||
self.model = DPT_DINOv2(encoder="vitl", features=256, out_channels=[256, 512, 1024, 1024])
|
||||
case _:
|
||||
raise TypeError("Not a supported model")
|
||||
|
||||
self.model.load_state_dict(torch.load(DEPTH_ANYTHING_MODEL_PATH.as_posix(), map_location="cpu"))
|
||||
self.model.eval()
|
||||
|
||||
self.model.to(choose_torch_device())
|
||||
return self.model
|
||||
|
||||
def to(self, device):
|
||||
self.model.to(device)
|
||||
return self
|
||||
|
||||
def __call__(self, image, resolution=512, offload=False):
|
||||
image = np.array(image, dtype=np.uint8)
|
||||
image = image[:, :, ::-1] / 255.0
|
||||
|
||||
image_height, image_width = image.shape[:2]
|
||||
image = transform({"image": image})["image"]
|
||||
image = torch.from_numpy(image).unsqueeze(0).to(choose_torch_device())
|
||||
|
||||
with torch.no_grad():
|
||||
depth = self.model(image)
|
||||
depth = F.interpolate(depth[None], (image_height, image_width), mode="bilinear", align_corners=False)[0, 0]
|
||||
depth = (depth - depth.min()) / (depth.max() - depth.min()) * 255.0
|
||||
|
||||
depth_map = repeat(depth, "h w -> h w 3").cpu().numpy().astype(np.uint8)
|
||||
depth_map = Image.fromarray(depth_map)
|
||||
|
||||
new_height = int(image_height * (resolution / image_width))
|
||||
depth_map = depth_map.resize((resolution, new_height))
|
||||
|
||||
if offload:
|
||||
del self.model
|
||||
|
||||
return depth_map
|
145
invokeai/backend/image_util/depth_anything/model/blocks.py
Normal file
145
invokeai/backend/image_util/depth_anything/model/blocks.py
Normal file
@ -0,0 +1,145 @@
|
||||
import torch.nn as nn
|
||||
|
||||
|
||||
def _make_scratch(in_shape, out_shape, groups=1, expand=False):
|
||||
scratch = nn.Module()
|
||||
|
||||
out_shape1 = out_shape
|
||||
out_shape2 = out_shape
|
||||
out_shape3 = out_shape
|
||||
if len(in_shape) >= 4:
|
||||
out_shape4 = out_shape
|
||||
|
||||
if expand:
|
||||
out_shape1 = out_shape
|
||||
out_shape2 = out_shape * 2
|
||||
out_shape3 = out_shape * 4
|
||||
if len(in_shape) >= 4:
|
||||
out_shape4 = out_shape * 8
|
||||
|
||||
scratch.layer1_rn = nn.Conv2d(
|
||||
in_shape[0], out_shape1, kernel_size=3, stride=1, padding=1, bias=False, groups=groups
|
||||
)
|
||||
scratch.layer2_rn = nn.Conv2d(
|
||||
in_shape[1], out_shape2, kernel_size=3, stride=1, padding=1, bias=False, groups=groups
|
||||
)
|
||||
scratch.layer3_rn = nn.Conv2d(
|
||||
in_shape[2], out_shape3, kernel_size=3, stride=1, padding=1, bias=False, groups=groups
|
||||
)
|
||||
if len(in_shape) >= 4:
|
||||
scratch.layer4_rn = nn.Conv2d(
|
||||
in_shape[3], out_shape4, kernel_size=3, stride=1, padding=1, bias=False, groups=groups
|
||||
)
|
||||
|
||||
return scratch
|
||||
|
||||
|
||||
class ResidualConvUnit(nn.Module):
|
||||
"""Residual convolution module."""
|
||||
|
||||
def __init__(self, features, activation, bn):
|
||||
"""Init.
|
||||
|
||||
Args:
|
||||
features (int): number of features
|
||||
"""
|
||||
super().__init__()
|
||||
|
||||
self.bn = bn
|
||||
|
||||
self.groups = 1
|
||||
|
||||
self.conv1 = nn.Conv2d(features, features, kernel_size=3, stride=1, padding=1, bias=True, groups=self.groups)
|
||||
|
||||
self.conv2 = nn.Conv2d(features, features, kernel_size=3, stride=1, padding=1, bias=True, groups=self.groups)
|
||||
|
||||
if self.bn:
|
||||
self.bn1 = nn.BatchNorm2d(features)
|
||||
self.bn2 = nn.BatchNorm2d(features)
|
||||
|
||||
self.activation = activation
|
||||
|
||||
self.skip_add = nn.quantized.FloatFunctional()
|
||||
|
||||
def forward(self, x):
|
||||
"""Forward pass.
|
||||
|
||||
Args:
|
||||
x (tensor): input
|
||||
|
||||
Returns:
|
||||
tensor: output
|
||||
"""
|
||||
|
||||
out = self.activation(x)
|
||||
out = self.conv1(out)
|
||||
if self.bn:
|
||||
out = self.bn1(out)
|
||||
|
||||
out = self.activation(out)
|
||||
out = self.conv2(out)
|
||||
if self.bn:
|
||||
out = self.bn2(out)
|
||||
|
||||
if self.groups > 1:
|
||||
out = self.conv_merge(out)
|
||||
|
||||
return self.skip_add.add(out, x)
|
||||
|
||||
|
||||
class FeatureFusionBlock(nn.Module):
|
||||
"""Feature fusion block."""
|
||||
|
||||
def __init__(self, features, activation, deconv=False, bn=False, expand=False, align_corners=True, size=None):
|
||||
"""Init.
|
||||
|
||||
Args:
|
||||
features (int): number of features
|
||||
"""
|
||||
super(FeatureFusionBlock, self).__init__()
|
||||
|
||||
self.deconv = deconv
|
||||
self.align_corners = align_corners
|
||||
|
||||
self.groups = 1
|
||||
|
||||
self.expand = expand
|
||||
out_features = features
|
||||
if self.expand:
|
||||
out_features = features // 2
|
||||
|
||||
self.out_conv = nn.Conv2d(features, out_features, kernel_size=1, stride=1, padding=0, bias=True, groups=1)
|
||||
|
||||
self.resConfUnit1 = ResidualConvUnit(features, activation, bn)
|
||||
self.resConfUnit2 = ResidualConvUnit(features, activation, bn)
|
||||
|
||||
self.skip_add = nn.quantized.FloatFunctional()
|
||||
|
||||
self.size = size
|
||||
|
||||
def forward(self, *xs, size=None):
|
||||
"""Forward pass.
|
||||
|
||||
Returns:
|
||||
tensor: output
|
||||
"""
|
||||
output = xs[0]
|
||||
|
||||
if len(xs) == 2:
|
||||
res = self.resConfUnit1(xs[1])
|
||||
output = self.skip_add.add(output, res)
|
||||
|
||||
output = self.resConfUnit2(output)
|
||||
|
||||
if (size is None) and (self.size is None):
|
||||
modifier = {"scale_factor": 2}
|
||||
elif size is None:
|
||||
modifier = {"size": self.size}
|
||||
else:
|
||||
modifier = {"size": size}
|
||||
|
||||
output = nn.functional.interpolate(output, **modifier, mode="bilinear", align_corners=self.align_corners)
|
||||
|
||||
output = self.out_conv(output)
|
||||
|
||||
return output
|
183
invokeai/backend/image_util/depth_anything/model/dpt.py
Normal file
183
invokeai/backend/image_util/depth_anything/model/dpt.py
Normal file
@ -0,0 +1,183 @@
|
||||
from pathlib import Path
|
||||
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
import torch.nn.functional as F
|
||||
|
||||
from .blocks import FeatureFusionBlock, _make_scratch
|
||||
|
||||
torchhub_path = Path(__file__).parent.parent / "torchhub"
|
||||
|
||||
|
||||
def _make_fusion_block(features, use_bn, size=None):
|
||||
return FeatureFusionBlock(
|
||||
features,
|
||||
nn.ReLU(False),
|
||||
deconv=False,
|
||||
bn=use_bn,
|
||||
expand=False,
|
||||
align_corners=True,
|
||||
size=size,
|
||||
)
|
||||
|
||||
|
||||
class DPTHead(nn.Module):
|
||||
def __init__(self, nclass, in_channels, features, out_channels, use_bn=False, use_clstoken=False):
|
||||
super(DPTHead, self).__init__()
|
||||
|
||||
self.nclass = nclass
|
||||
self.use_clstoken = use_clstoken
|
||||
|
||||
self.projects = nn.ModuleList(
|
||||
[
|
||||
nn.Conv2d(
|
||||
in_channels=in_channels,
|
||||
out_channels=out_channel,
|
||||
kernel_size=1,
|
||||
stride=1,
|
||||
padding=0,
|
||||
)
|
||||
for out_channel in out_channels
|
||||
]
|
||||
)
|
||||
|
||||
self.resize_layers = nn.ModuleList(
|
||||
[
|
||||
nn.ConvTranspose2d(
|
||||
in_channels=out_channels[0], out_channels=out_channels[0], kernel_size=4, stride=4, padding=0
|
||||
),
|
||||
nn.ConvTranspose2d(
|
||||
in_channels=out_channels[1], out_channels=out_channels[1], kernel_size=2, stride=2, padding=0
|
||||
),
|
||||
nn.Identity(),
|
||||
nn.Conv2d(
|
||||
in_channels=out_channels[3], out_channels=out_channels[3], kernel_size=3, stride=2, padding=1
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
if use_clstoken:
|
||||
self.readout_projects = nn.ModuleList()
|
||||
for _ in range(len(self.projects)):
|
||||
self.readout_projects.append(nn.Sequential(nn.Linear(2 * in_channels, in_channels), nn.GELU()))
|
||||
|
||||
self.scratch = _make_scratch(
|
||||
out_channels,
|
||||
features,
|
||||
groups=1,
|
||||
expand=False,
|
||||
)
|
||||
|
||||
self.scratch.stem_transpose = None
|
||||
|
||||
self.scratch.refinenet1 = _make_fusion_block(features, use_bn)
|
||||
self.scratch.refinenet2 = _make_fusion_block(features, use_bn)
|
||||
self.scratch.refinenet3 = _make_fusion_block(features, use_bn)
|
||||
self.scratch.refinenet4 = _make_fusion_block(features, use_bn)
|
||||
|
||||
head_features_1 = features
|
||||
head_features_2 = 32
|
||||
|
||||
if nclass > 1:
|
||||
self.scratch.output_conv = nn.Sequential(
|
||||
nn.Conv2d(head_features_1, head_features_1, kernel_size=3, stride=1, padding=1),
|
||||
nn.ReLU(True),
|
||||
nn.Conv2d(head_features_1, nclass, kernel_size=1, stride=1, padding=0),
|
||||
)
|
||||
else:
|
||||
self.scratch.output_conv1 = nn.Conv2d(
|
||||
head_features_1, head_features_1 // 2, kernel_size=3, stride=1, padding=1
|
||||
)
|
||||
|
||||
self.scratch.output_conv2 = nn.Sequential(
|
||||
nn.Conv2d(head_features_1 // 2, head_features_2, kernel_size=3, stride=1, padding=1),
|
||||
nn.ReLU(True),
|
||||
nn.Conv2d(head_features_2, 1, kernel_size=1, stride=1, padding=0),
|
||||
nn.ReLU(True),
|
||||
nn.Identity(),
|
||||
)
|
||||
|
||||
def forward(self, out_features, patch_h, patch_w):
|
||||
out = []
|
||||
for i, x in enumerate(out_features):
|
||||
if self.use_clstoken:
|
||||
x, cls_token = x[0], x[1]
|
||||
readout = cls_token.unsqueeze(1).expand_as(x)
|
||||
x = self.readout_projects[i](torch.cat((x, readout), -1))
|
||||
else:
|
||||
x = x[0]
|
||||
|
||||
x = x.permute(0, 2, 1).reshape((x.shape[0], x.shape[-1], patch_h, patch_w))
|
||||
|
||||
x = self.projects[i](x)
|
||||
x = self.resize_layers[i](x)
|
||||
|
||||
out.append(x)
|
||||
|
||||
layer_1, layer_2, layer_3, layer_4 = out
|
||||
|
||||
layer_1_rn = self.scratch.layer1_rn(layer_1)
|
||||
layer_2_rn = self.scratch.layer2_rn(layer_2)
|
||||
layer_3_rn = self.scratch.layer3_rn(layer_3)
|
||||
layer_4_rn = self.scratch.layer4_rn(layer_4)
|
||||
|
||||
path_4 = self.scratch.refinenet4(layer_4_rn, size=layer_3_rn.shape[2:])
|
||||
path_3 = self.scratch.refinenet3(path_4, layer_3_rn, size=layer_2_rn.shape[2:])
|
||||
path_2 = self.scratch.refinenet2(path_3, layer_2_rn, size=layer_1_rn.shape[2:])
|
||||
path_1 = self.scratch.refinenet1(path_2, layer_1_rn)
|
||||
|
||||
out = self.scratch.output_conv1(path_1)
|
||||
out = F.interpolate(out, (int(patch_h * 14), int(patch_w * 14)), mode="bilinear", align_corners=True)
|
||||
out = self.scratch.output_conv2(out)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
class DPT_DINOv2(nn.Module):
|
||||
def __init__(
|
||||
self,
|
||||
features,
|
||||
out_channels,
|
||||
encoder="vitl",
|
||||
use_bn=False,
|
||||
use_clstoken=False,
|
||||
):
|
||||
super(DPT_DINOv2, self).__init__()
|
||||
|
||||
assert encoder in ["vits", "vitb", "vitl"]
|
||||
|
||||
# # in case the Internet connection is not stable, please load the DINOv2 locally
|
||||
# if use_local:
|
||||
# self.pretrained = torch.hub.load(
|
||||
# torchhub_path / "facebookresearch_dinov2_main",
|
||||
# "dinov2_{:}14".format(encoder),
|
||||
# source="local",
|
||||
# pretrained=False,
|
||||
# )
|
||||
# else:
|
||||
# self.pretrained = torch.hub.load(
|
||||
# "facebookresearch/dinov2",
|
||||
# "dinov2_{:}14".format(encoder),
|
||||
# )
|
||||
|
||||
self.pretrained = torch.hub.load(
|
||||
"facebookresearch/dinov2",
|
||||
"dinov2_{:}14".format(encoder),
|
||||
)
|
||||
|
||||
dim = self.pretrained.blocks[0].attn.qkv.in_features
|
||||
|
||||
self.depth_head = DPTHead(1, dim, features, out_channels=out_channels, use_bn=use_bn, use_clstoken=use_clstoken)
|
||||
|
||||
def forward(self, x):
|
||||
h, w = x.shape[-2:]
|
||||
|
||||
features = self.pretrained.get_intermediate_layers(x, 4, return_class_token=True)
|
||||
|
||||
patch_h, patch_w = h // 14, w // 14
|
||||
|
||||
depth = self.depth_head(features, patch_h, patch_w)
|
||||
depth = F.interpolate(depth, size=(h, w), mode="bilinear", align_corners=True)
|
||||
depth = F.relu(depth)
|
||||
|
||||
return depth.squeeze(1)
|
227
invokeai/backend/image_util/depth_anything/utilities/util.py
Normal file
227
invokeai/backend/image_util/depth_anything/utilities/util.py
Normal file
@ -0,0 +1,227 @@
|
||||
import math
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
import torch
|
||||
import torch.nn.functional as F
|
||||
|
||||
|
||||
def apply_min_size(sample, size, image_interpolation_method=cv2.INTER_AREA):
|
||||
"""Rezise the sample to ensure the given size. Keeps aspect ratio.
|
||||
|
||||
Args:
|
||||
sample (dict): sample
|
||||
size (tuple): image size
|
||||
|
||||
Returns:
|
||||
tuple: new size
|
||||
"""
|
||||
shape = list(sample["disparity"].shape)
|
||||
|
||||
if shape[0] >= size[0] and shape[1] >= size[1]:
|
||||
return sample
|
||||
|
||||
scale = [0, 0]
|
||||
scale[0] = size[0] / shape[0]
|
||||
scale[1] = size[1] / shape[1]
|
||||
|
||||
scale = max(scale)
|
||||
|
||||
shape[0] = math.ceil(scale * shape[0])
|
||||
shape[1] = math.ceil(scale * shape[1])
|
||||
|
||||
# resize
|
||||
sample["image"] = cv2.resize(sample["image"], tuple(shape[::-1]), interpolation=image_interpolation_method)
|
||||
|
||||
sample["disparity"] = cv2.resize(sample["disparity"], tuple(shape[::-1]), interpolation=cv2.INTER_NEAREST)
|
||||
sample["mask"] = cv2.resize(
|
||||
sample["mask"].astype(np.float32),
|
||||
tuple(shape[::-1]),
|
||||
interpolation=cv2.INTER_NEAREST,
|
||||
)
|
||||
sample["mask"] = sample["mask"].astype(bool)
|
||||
|
||||
return tuple(shape)
|
||||
|
||||
|
||||
class Resize(object):
|
||||
"""Resize sample to given size (width, height)."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
width,
|
||||
height,
|
||||
resize_target=True,
|
||||
keep_aspect_ratio=False,
|
||||
ensure_multiple_of=1,
|
||||
resize_method="lower_bound",
|
||||
image_interpolation_method=cv2.INTER_AREA,
|
||||
):
|
||||
"""Init.
|
||||
|
||||
Args:
|
||||
width (int): desired output width
|
||||
height (int): desired output height
|
||||
resize_target (bool, optional):
|
||||
True: Resize the full sample (image, mask, target).
|
||||
False: Resize image only.
|
||||
Defaults to True.
|
||||
keep_aspect_ratio (bool, optional):
|
||||
True: Keep the aspect ratio of the input sample.
|
||||
Output sample might not have the given width and height, and
|
||||
resize behaviour depends on the parameter 'resize_method'.
|
||||
Defaults to False.
|
||||
ensure_multiple_of (int, optional):
|
||||
Output width and height is constrained to be multiple of this parameter.
|
||||
Defaults to 1.
|
||||
resize_method (str, optional):
|
||||
"lower_bound": Output will be at least as large as the given size.
|
||||
"upper_bound": Output will be at max as large as the given size. (Output size might be smaller
|
||||
than given size.)
|
||||
"minimal": Scale as least as possible. (Output size might be smaller than given size.)
|
||||
Defaults to "lower_bound".
|
||||
"""
|
||||
self.__width = width
|
||||
self.__height = height
|
||||
|
||||
self.__resize_target = resize_target
|
||||
self.__keep_aspect_ratio = keep_aspect_ratio
|
||||
self.__multiple_of = ensure_multiple_of
|
||||
self.__resize_method = resize_method
|
||||
self.__image_interpolation_method = image_interpolation_method
|
||||
|
||||
def constrain_to_multiple_of(self, x, min_val=0, max_val=None):
|
||||
y = (np.round(x / self.__multiple_of) * self.__multiple_of).astype(int)
|
||||
|
||||
if max_val is not None and y > max_val:
|
||||
y = (np.floor(x / self.__multiple_of) * self.__multiple_of).astype(int)
|
||||
|
||||
if y < min_val:
|
||||
y = (np.ceil(x / self.__multiple_of) * self.__multiple_of).astype(int)
|
||||
|
||||
return y
|
||||
|
||||
def get_size(self, width, height):
|
||||
# determine new height and width
|
||||
scale_height = self.__height / height
|
||||
scale_width = self.__width / width
|
||||
|
||||
if self.__keep_aspect_ratio:
|
||||
if self.__resize_method == "lower_bound":
|
||||
# scale such that output size is lower bound
|
||||
if scale_width > scale_height:
|
||||
# fit width
|
||||
scale_height = scale_width
|
||||
else:
|
||||
# fit height
|
||||
scale_width = scale_height
|
||||
elif self.__resize_method == "upper_bound":
|
||||
# scale such that output size is upper bound
|
||||
if scale_width < scale_height:
|
||||
# fit width
|
||||
scale_height = scale_width
|
||||
else:
|
||||
# fit height
|
||||
scale_width = scale_height
|
||||
elif self.__resize_method == "minimal":
|
||||
# scale as least as possbile
|
||||
if abs(1 - scale_width) < abs(1 - scale_height):
|
||||
# fit width
|
||||
scale_height = scale_width
|
||||
else:
|
||||
# fit height
|
||||
scale_width = scale_height
|
||||
else:
|
||||
raise ValueError(f"resize_method {self.__resize_method} not implemented")
|
||||
|
||||
if self.__resize_method == "lower_bound":
|
||||
new_height = self.constrain_to_multiple_of(scale_height * height, min_val=self.__height)
|
||||
new_width = self.constrain_to_multiple_of(scale_width * width, min_val=self.__width)
|
||||
elif self.__resize_method == "upper_bound":
|
||||
new_height = self.constrain_to_multiple_of(scale_height * height, max_val=self.__height)
|
||||
new_width = self.constrain_to_multiple_of(scale_width * width, max_val=self.__width)
|
||||
elif self.__resize_method == "minimal":
|
||||
new_height = self.constrain_to_multiple_of(scale_height * height)
|
||||
new_width = self.constrain_to_multiple_of(scale_width * width)
|
||||
else:
|
||||
raise ValueError(f"resize_method {self.__resize_method} not implemented")
|
||||
|
||||
return (new_width, new_height)
|
||||
|
||||
def __call__(self, sample):
|
||||
width, height = self.get_size(sample["image"].shape[1], sample["image"].shape[0])
|
||||
|
||||
# resize sample
|
||||
sample["image"] = cv2.resize(
|
||||
sample["image"],
|
||||
(width, height),
|
||||
interpolation=self.__image_interpolation_method,
|
||||
)
|
||||
|
||||
if self.__resize_target:
|
||||
if "disparity" in sample:
|
||||
sample["disparity"] = cv2.resize(
|
||||
sample["disparity"],
|
||||
(width, height),
|
||||
interpolation=cv2.INTER_NEAREST,
|
||||
)
|
||||
|
||||
if "depth" in sample:
|
||||
sample["depth"] = cv2.resize(sample["depth"], (width, height), interpolation=cv2.INTER_NEAREST)
|
||||
|
||||
if "semseg_mask" in sample:
|
||||
# sample["semseg_mask"] = cv2.resize(
|
||||
# sample["semseg_mask"], (width, height), interpolation=cv2.INTER_NEAREST
|
||||
# )
|
||||
sample["semseg_mask"] = F.interpolate(
|
||||
torch.from_numpy(sample["semseg_mask"]).float()[None, None, ...], (height, width), mode="nearest"
|
||||
).numpy()[0, 0]
|
||||
|
||||
if "mask" in sample:
|
||||
sample["mask"] = cv2.resize(
|
||||
sample["mask"].astype(np.float32),
|
||||
(width, height),
|
||||
interpolation=cv2.INTER_NEAREST,
|
||||
)
|
||||
# sample["mask"] = sample["mask"].astype(bool)
|
||||
|
||||
# print(sample['image'].shape, sample['depth'].shape)
|
||||
return sample
|
||||
|
||||
|
||||
class NormalizeImage(object):
|
||||
"""Normlize image by given mean and std."""
|
||||
|
||||
def __init__(self, mean, std):
|
||||
self.__mean = mean
|
||||
self.__std = std
|
||||
|
||||
def __call__(self, sample):
|
||||
sample["image"] = (sample["image"] - self.__mean) / self.__std
|
||||
|
||||
return sample
|
||||
|
||||
|
||||
class PrepareForNet(object):
|
||||
"""Prepare sample for usage as network input."""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def __call__(self, sample):
|
||||
image = np.transpose(sample["image"], (2, 0, 1))
|
||||
sample["image"] = np.ascontiguousarray(image).astype(np.float32)
|
||||
|
||||
if "mask" in sample:
|
||||
sample["mask"] = sample["mask"].astype(np.float32)
|
||||
sample["mask"] = np.ascontiguousarray(sample["mask"])
|
||||
|
||||
if "depth" in sample:
|
||||
depth = sample["depth"].astype(np.float32)
|
||||
sample["depth"] = np.ascontiguousarray(depth)
|
||||
|
||||
if "semseg_mask" in sample:
|
||||
sample["semseg_mask"] = sample["semseg_mask"].astype(np.float32)
|
||||
sample["semseg_mask"] = np.ascontiguousarray(sample["semseg_mask"])
|
||||
|
||||
return sample
|
@ -6,7 +6,6 @@ import { Provider } from 'react-redux';
|
||||
import ThemeLocaleProvider from '../src/app/components/ThemeLocaleProvider';
|
||||
import { $baseUrl } from '../src/app/store/nanostores/baseUrl';
|
||||
import { createStore } from '../src/app/store/store';
|
||||
import { Container } from '@chakra-ui/react';
|
||||
// TODO: Disabled for IDE performance issues with our translation JSON
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
|
@ -52,21 +52,12 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@chakra-ui/anatomy": "^2.2.2",
|
||||
"@chakra-ui/icons": "^2.1.1",
|
||||
"@chakra-ui/layout": "^2.3.1",
|
||||
"@chakra-ui/portal": "^2.1.0",
|
||||
"@chakra-ui/react": "^2.8.2",
|
||||
"@chakra-ui/react-use-size": "^2.1.0",
|
||||
"@chakra-ui/styled-system": "^2.9.2",
|
||||
"@chakra-ui/theme-tools": "^2.1.2",
|
||||
"@dagrejs/graphlib": "^2.1.13",
|
||||
"@dnd-kit/core": "^6.1.0",
|
||||
"@dnd-kit/utilities": "^3.2.2",
|
||||
"@emotion/react": "^11.11.3",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@fontsource-variable/inter": "^5.0.16",
|
||||
"@invoke-ai/ui": "0.0.10",
|
||||
"@invoke-ai/ui": "0.0.13",
|
||||
"@mantine/form": "6.0.21",
|
||||
"@nanostores/react": "^0.7.1",
|
||||
"@reduxjs/toolkit": "2.0.1",
|
||||
|
@ -10,30 +10,12 @@ patchedDependencies:
|
||||
path: patches/reselect@5.0.1.patch
|
||||
|
||||
dependencies:
|
||||
'@chakra-ui/anatomy':
|
||||
specifier: ^2.2.2
|
||||
version: 2.2.2
|
||||
'@chakra-ui/icons':
|
||||
specifier: ^2.1.1
|
||||
version: 2.1.1(@chakra-ui/system@2.6.2)(react@18.2.0)
|
||||
'@chakra-ui/layout':
|
||||
specifier: ^2.3.1
|
||||
version: 2.3.1(@chakra-ui/system@2.6.2)(react@18.2.0)
|
||||
'@chakra-ui/portal':
|
||||
specifier: ^2.1.0
|
||||
version: 2.1.0(react-dom@18.2.0)(react@18.2.0)
|
||||
'@chakra-ui/react':
|
||||
specifier: ^2.8.2
|
||||
version: 2.8.2(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@types/react@18.2.48)(framer-motion@10.18.0)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@chakra-ui/react-use-size':
|
||||
specifier: ^2.1.0
|
||||
version: 2.1.0(react@18.2.0)
|
||||
'@chakra-ui/styled-system':
|
||||
specifier: ^2.9.2
|
||||
version: 2.9.2
|
||||
'@chakra-ui/theme-tools':
|
||||
specifier: ^2.1.2
|
||||
version: 2.1.2(@chakra-ui/styled-system@2.9.2)
|
||||
'@dagrejs/graphlib':
|
||||
specifier: ^2.1.13
|
||||
version: 2.1.13
|
||||
@ -43,18 +25,12 @@ dependencies:
|
||||
'@dnd-kit/utilities':
|
||||
specifier: ^3.2.2
|
||||
version: 3.2.2(react@18.2.0)
|
||||
'@emotion/react':
|
||||
specifier: ^11.11.3
|
||||
version: 11.11.3(@types/react@18.2.48)(react@18.2.0)
|
||||
'@emotion/styled':
|
||||
specifier: ^11.11.0
|
||||
version: 11.11.0(@emotion/react@11.11.3)(@types/react@18.2.48)(react@18.2.0)
|
||||
'@fontsource-variable/inter':
|
||||
specifier: ^5.0.16
|
||||
version: 5.0.16
|
||||
'@invoke-ai/ui':
|
||||
specifier: 0.0.10
|
||||
version: 0.0.10(@chakra-ui/anatomy@2.2.2)(@chakra-ui/icons@2.1.1)(@chakra-ui/layout@2.3.1)(@chakra-ui/portal@2.1.0)(@chakra-ui/react@2.8.2)(@chakra-ui/styled-system@2.9.2)(@chakra-ui/theme-tools@2.1.2)(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@fontsource-variable/inter@5.0.16)(@nanostores/react@0.7.1)(chakra-react-select@4.7.6)(framer-motion@10.18.0)(lodash-es@4.17.21)(nanostores@0.9.5)(overlayscrollbars-react@0.5.3)(overlayscrollbars@2.4.6)(react-dom@18.2.0)(react-i18next@14.0.0)(react-select@5.8.0)(react@18.2.0)
|
||||
specifier: 0.0.13
|
||||
version: 0.0.13(@chakra-ui/form-control@2.2.0)(@chakra-ui/icon@3.2.0)(@chakra-ui/media-query@3.3.0)(@chakra-ui/menu@2.2.1)(@chakra-ui/spinner@2.1.0)(@chakra-ui/system@2.6.2)(@fontsource-variable/inter@5.0.16)(@internationalized/date@3.5.1)(@types/react@18.2.48)(i18next@23.7.16)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@mantine/form':
|
||||
specifier: 6.0.21
|
||||
version: 6.0.21(react@18.2.0)
|
||||
@ -356,6 +332,92 @@ packages:
|
||||
'@jridgewell/trace-mapping': 0.3.21
|
||||
dev: true
|
||||
|
||||
/@ark-ui/anatomy@1.3.0(@internationalized/date@3.5.1):
|
||||
resolution: {integrity: sha512-1yG2MrzUlix6KthjQMCNiHnkXrWwEdFAX6D+HqGJaNu0XvaGul2J+wDNtjsdX+gxiWu1nXXEEOAWlFVYMUf65w==}
|
||||
dependencies:
|
||||
'@zag-js/accordion': 0.32.1
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/avatar': 0.32.1
|
||||
'@zag-js/carousel': 0.32.1
|
||||
'@zag-js/checkbox': 0.32.1
|
||||
'@zag-js/color-picker': 0.32.1
|
||||
'@zag-js/color-utils': 0.32.1
|
||||
'@zag-js/combobox': 0.32.1
|
||||
'@zag-js/date-picker': 0.32.1
|
||||
'@zag-js/date-utils': 0.32.1(@internationalized/date@3.5.1)
|
||||
'@zag-js/dialog': 0.32.1
|
||||
'@zag-js/editable': 0.32.1
|
||||
'@zag-js/file-upload': 0.32.1
|
||||
'@zag-js/hover-card': 0.32.1
|
||||
'@zag-js/menu': 0.32.1
|
||||
'@zag-js/number-input': 0.32.1
|
||||
'@zag-js/pagination': 0.32.1
|
||||
'@zag-js/pin-input': 0.32.1
|
||||
'@zag-js/popover': 0.32.1
|
||||
'@zag-js/presence': 0.32.1
|
||||
'@zag-js/progress': 0.32.1
|
||||
'@zag-js/radio-group': 0.32.1
|
||||
'@zag-js/rating-group': 0.32.1
|
||||
'@zag-js/select': 0.32.1
|
||||
'@zag-js/slider': 0.32.1
|
||||
'@zag-js/splitter': 0.32.1
|
||||
'@zag-js/switch': 0.32.1
|
||||
'@zag-js/tabs': 0.32.1
|
||||
'@zag-js/tags-input': 0.32.1
|
||||
'@zag-js/toast': 0.32.1
|
||||
'@zag-js/toggle-group': 0.32.1
|
||||
'@zag-js/tooltip': 0.32.1
|
||||
transitivePeerDependencies:
|
||||
- '@internationalized/date'
|
||||
dev: false
|
||||
|
||||
/@ark-ui/react@1.3.0(@internationalized/date@3.5.1)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-JHjNoIX50+mUCTaEGMjfGQWGGi31pKsV646jZJlR/1xohpYJigzg8BvO97cTsVk8fwtur+cm11gz3Nf7f5QUnA==}
|
||||
peerDependencies:
|
||||
react: '>=18.0.0'
|
||||
react-dom: '>=18.0.0'
|
||||
dependencies:
|
||||
'@ark-ui/anatomy': 1.3.0(@internationalized/date@3.5.1)
|
||||
'@zag-js/accordion': 0.32.1
|
||||
'@zag-js/avatar': 0.32.1
|
||||
'@zag-js/carousel': 0.32.1
|
||||
'@zag-js/checkbox': 0.32.1
|
||||
'@zag-js/color-picker': 0.32.1
|
||||
'@zag-js/color-utils': 0.32.1
|
||||
'@zag-js/combobox': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/date-picker': 0.32.1
|
||||
'@zag-js/date-utils': 0.32.1(@internationalized/date@3.5.1)
|
||||
'@zag-js/dialog': 0.32.1
|
||||
'@zag-js/editable': 0.32.1
|
||||
'@zag-js/file-upload': 0.32.1
|
||||
'@zag-js/hover-card': 0.32.1
|
||||
'@zag-js/menu': 0.32.1
|
||||
'@zag-js/number-input': 0.32.1
|
||||
'@zag-js/pagination': 0.32.1
|
||||
'@zag-js/pin-input': 0.32.1
|
||||
'@zag-js/popover': 0.32.1
|
||||
'@zag-js/presence': 0.32.1
|
||||
'@zag-js/progress': 0.32.1
|
||||
'@zag-js/radio-group': 0.32.1
|
||||
'@zag-js/rating-group': 0.32.1
|
||||
'@zag-js/react': 0.32.1(react-dom@18.2.0)(react@18.2.0)
|
||||
'@zag-js/select': 0.32.1
|
||||
'@zag-js/slider': 0.32.1
|
||||
'@zag-js/splitter': 0.32.1
|
||||
'@zag-js/switch': 0.32.1
|
||||
'@zag-js/tabs': 0.32.1
|
||||
'@zag-js/tags-input': 0.32.1
|
||||
'@zag-js/toast': 0.32.1
|
||||
'@zag-js/toggle-group': 0.32.1
|
||||
'@zag-js/tooltip': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
transitivePeerDependencies:
|
||||
- '@internationalized/date'
|
||||
dev: false
|
||||
|
||||
/@arthurgeron/eslint-plugin-react-usememo@2.2.3:
|
||||
resolution: {integrity: sha512-YJG+8hULmhHAxztaANswpa9hWNqEOSvbZcbd6R/JQzyNlEZ49Xh97kqZGuJGZ74rrmULckEO1m3Jh5ctqrGA2A==}
|
||||
dependencies:
|
||||
@ -2940,7 +3002,7 @@ packages:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.6
|
||||
'@babel/runtime': 7.23.8
|
||||
'@emotion/babel-plugin': 11.11.0
|
||||
'@emotion/is-prop-valid': 1.2.1
|
||||
'@emotion/react': 11.11.3(@types/react@18.2.48)(react@18.2.0)
|
||||
@ -3629,7 +3691,6 @@ packages:
|
||||
resolution: {integrity: sha512-O0WKDOo0yhJuugCx6trZQj5jVJ9yR0ystG2JaNAemYUWce+pmM6WUEFIibnWyEJKdrDxhm75NoSRME35FNaM/Q==}
|
||||
dependencies:
|
||||
'@floating-ui/utils': 0.2.1
|
||||
dev: true
|
||||
|
||||
/@floating-ui/dom@1.5.3:
|
||||
resolution: {integrity: sha512-ClAbQnEqJAKCJOEbbLo5IUlZHkNszqhuxS4fHAVxRPXPya6Ysf2G8KypnYcOTpx6I8xcgF9bbHb6g/2KpbV8qA==}
|
||||
@ -3643,7 +3704,6 @@ packages:
|
||||
dependencies:
|
||||
'@floating-ui/core': 1.5.3
|
||||
'@floating-ui/utils': 0.2.1
|
||||
dev: true
|
||||
|
||||
/@floating-ui/react-dom@2.0.6(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-IB8aCRFxr8nFkdYZgH+Otd9EVQPJoynxeFRGTB8voPoZMRWo8XjYuCRgpI1btvuKY69XMiLnW+ym7zoBHM90Rw==}
|
||||
@ -3662,7 +3722,6 @@ packages:
|
||||
|
||||
/@floating-ui/utils@0.2.1:
|
||||
resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==}
|
||||
dev: true
|
||||
|
||||
/@fontsource-variable/inter@5.0.16:
|
||||
resolution: {integrity: sha512-k+BUNqksTL+AN+o+OV7ILeiE9B5M5X+/jA7LWvCwjbV9ovXTqZyKRhA/x7uYv/ml8WQ0XNLBM7cRFIx4jW0/hg==}
|
||||
@ -3688,31 +3747,26 @@ packages:
|
||||
resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==}
|
||||
dev: true
|
||||
|
||||
/@invoke-ai/ui@0.0.10(@chakra-ui/anatomy@2.2.2)(@chakra-ui/icons@2.1.1)(@chakra-ui/layout@2.3.1)(@chakra-ui/portal@2.1.0)(@chakra-ui/react@2.8.2)(@chakra-ui/styled-system@2.9.2)(@chakra-ui/theme-tools@2.1.2)(@emotion/react@11.11.3)(@emotion/styled@11.11.0)(@fontsource-variable/inter@5.0.16)(@nanostores/react@0.7.1)(chakra-react-select@4.7.6)(framer-motion@10.18.0)(lodash-es@4.17.21)(nanostores@0.9.5)(overlayscrollbars-react@0.5.3)(overlayscrollbars@2.4.6)(react-dom@18.2.0)(react-i18next@14.0.0)(react-select@5.8.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-e3cX3g1xap57mkMfjsNznN6V9YS8qUTpSiyjSSr80HEsD3NjXxCoL+Ik6y/Na/KwXgcK00jM6H+xF6ahJFobvw==}
|
||||
/@internationalized/date@3.5.1:
|
||||
resolution: {integrity: sha512-LUQIfwU9e+Fmutc/DpRTGXSdgYZLBegi4wygCWDSVmUdLTaMHsQyASDiJtREwanwKuQLq0hY76fCJ9J/9I2xOQ==}
|
||||
dependencies:
|
||||
'@swc/helpers': 0.5.3
|
||||
dev: false
|
||||
|
||||
/@internationalized/number@3.5.0:
|
||||
resolution: {integrity: sha512-ZY1BW8HT9WKYvaubbuqXbbDdHhOUMfE2zHHFJeTppid0S+pc8HtdIxFxaYMsGjCb4UsF+MEJ4n2TfU7iHnUK8w==}
|
||||
dependencies:
|
||||
'@swc/helpers': 0.5.3
|
||||
dev: false
|
||||
|
||||
/@invoke-ai/ui@0.0.13(@chakra-ui/form-control@2.2.0)(@chakra-ui/icon@3.2.0)(@chakra-ui/media-query@3.3.0)(@chakra-ui/menu@2.2.1)(@chakra-ui/spinner@2.1.0)(@chakra-ui/system@2.6.2)(@fontsource-variable/inter@5.0.16)(@internationalized/date@3.5.1)(@types/react@18.2.48)(i18next@23.7.16)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-X4Txij2dMnzPUXTPhorBHezByJQ/ceyHxCM+zZ0gpFsSyXUieOFWjaSu+dAVpghS9y0dxFQGayHvNyX6VsX/PA==}
|
||||
peerDependencies:
|
||||
'@chakra-ui/anatomy': ^2.2.2
|
||||
'@chakra-ui/icons': ^2.1.1
|
||||
'@chakra-ui/layout': ^2.3.1
|
||||
'@chakra-ui/portal': ^2.1.0
|
||||
'@chakra-ui/react': ^2.8.2
|
||||
'@chakra-ui/styled-system': ^2.9.2
|
||||
'@chakra-ui/theme-tools': ^2.1.2
|
||||
'@emotion/react': ^11.11.3
|
||||
'@emotion/styled': ^11.11.0
|
||||
'@fontsource-variable/inter': ^5.0.16
|
||||
'@nanostores/react': ^0.7.1
|
||||
chakra-react-select: ^4.7.6
|
||||
framer-motion: ^10.18.0
|
||||
lodash-es: ^4.17.21
|
||||
nanostores: ^0.9.5
|
||||
overlayscrollbars: ^2.4.6
|
||||
overlayscrollbars-react: ^0.5.3
|
||||
react: ^18.2.0
|
||||
react-dom: ^18.2.0
|
||||
react-i18next: ^14.0.0
|
||||
react-select: ^5.8.0
|
||||
dependencies:
|
||||
'@ark-ui/react': 1.3.0(@internationalized/date@3.5.1)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@chakra-ui/anatomy': 2.2.2
|
||||
'@chakra-ui/icons': 2.1.1(@chakra-ui/system@2.6.2)(react@18.2.0)
|
||||
'@chakra-ui/layout': 2.3.1(@chakra-ui/system@2.6.2)(react@18.2.0)
|
||||
@ -3734,6 +3788,17 @@ packages:
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
react-i18next: 14.0.0(i18next@23.7.16)(react-dom@18.2.0)(react@18.2.0)
|
||||
react-select: 5.8.0(@types/react@18.2.48)(react-dom@18.2.0)(react@18.2.0)
|
||||
transitivePeerDependencies:
|
||||
- '@chakra-ui/form-control'
|
||||
- '@chakra-ui/icon'
|
||||
- '@chakra-ui/media-query'
|
||||
- '@chakra-ui/menu'
|
||||
- '@chakra-ui/spinner'
|
||||
- '@chakra-ui/system'
|
||||
- '@internationalized/date'
|
||||
- '@types/react'
|
||||
- i18next
|
||||
- react-native
|
||||
dev: false
|
||||
|
||||
/@isaacs/cliui@8.0.2:
|
||||
@ -5719,6 +5784,12 @@ packages:
|
||||
resolution: {integrity: sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==}
|
||||
dev: true
|
||||
|
||||
/@swc/helpers@0.5.3:
|
||||
resolution: {integrity: sha512-FaruWX6KdudYloq1AHD/4nU+UsMTdNE8CKyrseXWEcgjDAbvkwJg2QGPAnfIJLIWsjZOSPLOAykK6fuYp4vp4A==}
|
||||
dependencies:
|
||||
tslib: 2.6.2
|
||||
dev: false
|
||||
|
||||
/@swc/types@0.1.5:
|
||||
resolution: {integrity: sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==}
|
||||
dev: true
|
||||
@ -6679,20 +6750,567 @@ packages:
|
||||
tslib: 1.14.1
|
||||
dev: true
|
||||
|
||||
/@zag-js/accordion@0.32.1:
|
||||
resolution: {integrity: sha512-16beDVpEhXFQsQRMZLmHFruhGphSprJ5XrRu6+OM2U7aTulo1w3ENUd9uI+mIs4oTVO66lYI4Lp+dFcT2UUIYA==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/anatomy@0.32.1:
|
||||
resolution: {integrity: sha512-bR+tfFfkbxwhBzGGjEQG+RUnbeCjMx7tWJxykGnGdVLwAh0wKTQBEfHEOCOQh5qU8RhKUieqemAdvc7oP3Tp4w==}
|
||||
dev: false
|
||||
|
||||
/@zag-js/aria-hidden@0.32.1:
|
||||
resolution: {integrity: sha512-kznwxvUUHDax8Kd7YNVVCzQcwGARTRaZNOcIkw7MTLE8g/pU+C4pYkwR9iqA7/8imGfjYrZfSsQqZRTb4bkS0g==}
|
||||
dependencies:
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/auto-resize@0.32.1:
|
||||
resolution: {integrity: sha512-MO6N5gPs2xDKbFgrakn6LDWv1GgN8uhfwpsqchLJX+EaZVvLIz8cXFD+jDv3RjK+5GRWV4mIF+26SXuHRSt9Ug==}
|
||||
dependencies:
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/avatar@0.32.1:
|
||||
resolution: {integrity: sha512-5P+95pkMX2Na4yljN1etdgYyA+3HPORjWKn0Y3JamkYIAqJwRFO+taEdSm/xcRkuT6aGA3luheUowjt8wZssyA==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/mutation-observer': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/carousel@0.32.1:
|
||||
resolution: {integrity: sha512-S7dUrPtiLr42Fa+S3O18kqKVqSu2yuk67bqGDtppIZSaFOugYHK4feBkZqjKw+eF12NVRRVO2j+A40d3MvxbSA==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/checkbox@0.32.1:
|
||||
resolution: {integrity: sha512-5reRreGyDZ5IlBNd5m1QrYXCehVIl/pmfKMEcAfad5DcgCaHGv5j76eahxbKln/8TEdwz4eWzBrqNtwSkKL5+w==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/form-utils': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
'@zag-js/visually-hidden': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/collection@0.32.1:
|
||||
resolution: {integrity: sha512-dAzcVQ/n+xAYoxWB/65/CQinv66RNVuq5ig0fEYszBqP+HjFnOpeGkIrEvP+bFI38hFEViiGtfr6oGAsVByOVQ==}
|
||||
dev: false
|
||||
|
||||
/@zag-js/color-picker@0.32.1:
|
||||
resolution: {integrity: sha512-ov3FC+c2WBYmEGRXWFVb2jih2Ecejj5JqBjDL9iMLBs2KNY9jnpvtH7WnZbijNY+RMDBj+C/DNI7K2NVaamSIA==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/color-utils': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dismissable': 0.32.1
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/form-utils': 0.32.1
|
||||
'@zag-js/popper': 0.32.1
|
||||
'@zag-js/tabbable': 0.32.1
|
||||
'@zag-js/text-selection': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
'@zag-js/visually-hidden': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/color-utils@0.32.1:
|
||||
resolution: {integrity: sha512-AzupfOD7oD0mE+H9roTzwnLqtw1wYiJGOQKLPAwdwPQdznJUQD6sMOpxR/6RBuITVTm8Bl12Mr4+7s29LVJruw==}
|
||||
dependencies:
|
||||
'@zag-js/numeric-range': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/combobox@0.32.1:
|
||||
resolution: {integrity: sha512-skz2C5UxLD5JoYNP4hcPaQJu2cW7vycKqjDNI9ZtygSkZHOHx+JxpYiACBnr1vqzXatIOuDQm/HUuWW9yOT4eA==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/aria-hidden': 0.32.1
|
||||
'@zag-js/collection': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dismissable': 0.32.1
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/mutation-observer': 0.32.1
|
||||
'@zag-js/popper': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/core@0.32.1:
|
||||
resolution: {integrity: sha512-F9F7920/CisoLWALQACIhqbMvemgbv86qBULJ+UEe+a/9XgGwPh9UGn/H/q5EWkNpgEapz2b3pl3ONgKmXsK1A==}
|
||||
dependencies:
|
||||
'@zag-js/store': 0.32.1
|
||||
klona: 2.0.6
|
||||
dev: false
|
||||
|
||||
/@zag-js/date-picker@0.32.1:
|
||||
resolution: {integrity: sha512-n/hYmF+/R4+NuyfPRzCgeuLT6LJihKSuKzK29STPWy3sC/tBBHiqhNv1/4UKbatHUJXdBW2XF+N8Rw08RffcFQ==}
|
||||
dependencies:
|
||||
'@internationalized/date': 3.5.1
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/date-utils': 0.32.1(@internationalized/date@3.5.1)
|
||||
'@zag-js/dismissable': 0.32.1
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/form-utils': 0.32.1
|
||||
'@zag-js/live-region': 0.32.1
|
||||
'@zag-js/popper': 0.32.1
|
||||
'@zag-js/text-selection': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/date-utils@0.32.1(@internationalized/date@3.5.1):
|
||||
resolution: {integrity: sha512-dbBDRSVr5pRUw3rXndyGuSshZiWqQI5JQO4D2KIFGkXzorj6WzoOpcO910Z7AdM/9cCAMpCjUrka8d8o9BpJBg==}
|
||||
peerDependencies:
|
||||
'@internationalized/date': '>=3.0.0'
|
||||
dependencies:
|
||||
'@internationalized/date': 3.5.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/dialog@0.32.1:
|
||||
resolution: {integrity: sha512-czp+qXcdAOM70SrvDo4gBpYZx6gS6HXyrpiptW3+EHa2eiCfc/Z2w+Nu+ZadOTEQGgNWlKlCLW7Ery0i9mMDsw==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/aria-hidden': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dismissable': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/remove-scroll': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
focus-trap: 7.5.4
|
||||
dev: false
|
||||
|
||||
/@zag-js/dismissable@0.32.1:
|
||||
resolution: {integrity: sha512-UIkG+9Eb5wrus2F2Dy4zqk0pwCV53sdnMYBxk9dpvDzBJHzW+InhVeg3UeKmPL8ELcYlhH/Bap99XCRJvxsXow==}
|
||||
dependencies:
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/interact-outside': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/dom-event@0.32.1:
|
||||
resolution: {integrity: sha512-wN6f5Kkf7C/YFN3wbEG3gUockSebyy1fPNL2BuL4C8PIP8vOD14hnHTzZWg5yYfO+veybIAL38r8I46C+bOVBQ==}
|
||||
dependencies:
|
||||
'@zag-js/text-selection': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/dom-query@0.16.0:
|
||||
resolution: {integrity: sha512-Oqhd6+biWyKnhKwFFuZrrf6lxBz2tX2pRQe6grUnYwO6HJ8BcbqZomy2lpOdr+3itlaUqx+Ywj5E5ZZDr/LBfQ==}
|
||||
dev: false
|
||||
|
||||
/@zag-js/dom-query@0.32.1:
|
||||
resolution: {integrity: sha512-u6hrQHQ0/dcUi6xJn8d2Mu1ClN4KZpPqOKrJFSaxadWjSy+x0qp48WY2CBQ6gZ3j8IwR/XjzU9bu9wY5jJfHgA==}
|
||||
dev: false
|
||||
|
||||
/@zag-js/editable@0.32.1:
|
||||
resolution: {integrity: sha512-QEGnfp2P9nWVp9vGNWtszspvQcF3KtBRToZrv5/DT30Mpo/uPDKtqijLs0SnB/W60ELzcIRhK4J9taGoK8O8uw==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/form-utils': 0.32.1
|
||||
'@zag-js/interact-outside': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/element-rect@0.32.1:
|
||||
resolution: {integrity: sha512-tAmxgxU2LsByK8PIs/Cj6cBJ8xZCVXE9RoStxthhuPL7xKYUfZvFGuhHVOHTHd6sDKEqbj6K1ds/TGPuglIh4w==}
|
||||
dev: false
|
||||
|
||||
/@zag-js/element-size@0.10.5:
|
||||
resolution: {integrity: sha512-uQre5IidULANvVkNOBQ1tfgwTQcGl4hliPSe69Fct1VfYb2Fd0jdAcGzqQgPhfrXFpR62MxLPB7erxJ/ngtL8w==}
|
||||
dev: false
|
||||
|
||||
/@zag-js/element-size@0.32.1:
|
||||
resolution: {integrity: sha512-ACklufmJQpah2UqwZUlYFaKi6uWfZBeTghtbfYHcDfzRbg2Hni612v8L1JeS4vAgjeDpcdHQpXXR4AZSpGZgNw==}
|
||||
dev: false
|
||||
|
||||
/@zag-js/file-upload@0.32.1:
|
||||
resolution: {integrity: sha512-cD0NRIDof9Vv2DemmnYe9ZPZxOZ6b8XZl8eq4G0e8+WLYtnRXyEURl8Dw0QJpfdDPQaHnnD4CNxPTQcLgP+9Sg==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/file-utils': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
'@zag-js/visually-hidden': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/file-utils@0.32.1:
|
||||
resolution: {integrity: sha512-0PxTrljW51Lf9OCuYNlZuaLgF0v1NoVRzXa/osZ9HGceQjfo77R5G9u+/TP3u53W2PTxajEZ4eNzTibgpzNXFg==}
|
||||
dev: false
|
||||
|
||||
/@zag-js/focus-visible@0.16.0:
|
||||
resolution: {integrity: sha512-a7U/HSopvQbrDU4GLerpqiMcHKEkQkNPeDZJWz38cw/6Upunh41GjHetq5TB84hxyCaDzJ6q2nEdNoBQfC0FKA==}
|
||||
dependencies:
|
||||
'@zag-js/dom-query': 0.16.0
|
||||
dev: false
|
||||
|
||||
/@zag-js/form-utils@0.32.1:
|
||||
resolution: {integrity: sha512-OemLBlHCHHm7t8wNcf78FRudRA7FegSgsNEzAjrRTyx+lJztDyHRLaoyI1gCEIg+0Kzl2nMxjOl4MStGsDj8iw==}
|
||||
dependencies:
|
||||
'@zag-js/mutation-observer': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/hover-card@0.32.1:
|
||||
resolution: {integrity: sha512-k66YK0z0P4LuK78+jnRoUPxJiM9GA0sbEEz3oPlvcFVXMMwnRTPNIw1OjksfAPI+Nvgg7H6D3A+7HCdRI/oBjw==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dismissable': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/popper': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/interact-outside@0.32.1:
|
||||
resolution: {integrity: sha512-8zHuswfTAgfMCaQnp3N4WStvnL32VyxURafb21+mE4neAF/DaKfJHWnJpeUMG1Qh/eXsrMRBxVoX+nBMhHj9bg==}
|
||||
dependencies:
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/tabbable': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/live-region@0.32.1:
|
||||
resolution: {integrity: sha512-6/9QMLVZbTRh/G6MoJc/auN8r5vjdY9vUgNT680C2LOa2vnRR5/y0DkIpVgttNh1rSenQ/eLEYxp8hQF1rIYNw==}
|
||||
dependencies:
|
||||
'@zag-js/visually-hidden': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/menu@0.32.1:
|
||||
resolution: {integrity: sha512-IPsTljVF0N9xTwub1cpGl3GAG5ttAq3h38PdZERREzT3qRgw4v3K/I1TG2vIiDXgJz8UZzUKox6ZYdU7UIAkRA==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dismissable': 0.32.1
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/mutation-observer': 0.32.1
|
||||
'@zag-js/popper': 0.32.1
|
||||
'@zag-js/rect-utils': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/mutation-observer@0.32.1:
|
||||
resolution: {integrity: sha512-/hlObxGnhAaYYVnwRJC227md0M3kSE6mO24vkqVGwq2GglS+u4zbVcBBUuWgHdMML+ZjIQrZuVycCBMfVlHq0g==}
|
||||
dev: false
|
||||
|
||||
/@zag-js/number-input@0.32.1:
|
||||
resolution: {integrity: sha512-atyIOvoMITb4hZtQym7yD6I7grvPW83UeMFO8hCQg3HWwd2zR4+63mouWuyMoWb4QrzVFRVQBaU8OG5xGlknEw==}
|
||||
dependencies:
|
||||
'@internationalized/number': 3.5.0
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/form-utils': 0.32.1
|
||||
'@zag-js/mutation-observer': 0.32.1
|
||||
'@zag-js/number-utils': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/number-utils@0.32.1:
|
||||
resolution: {integrity: sha512-x/nttU31TtFVTqFBM8e3ZH/0MCc+u15WAfk0rT6ESkoZcdb80rTzZVMokCKCUdpi/JdB1vjEeCLSnj+ig8oAIQ==}
|
||||
dev: false
|
||||
|
||||
/@zag-js/numeric-range@0.32.1:
|
||||
resolution: {integrity: sha512-1Qe2URTenlrdsWuArlnQ+v5bBH2mHZD3XsK6jYV+C2lgatVzdcoN4GCSNTiF7w+So6J+NTeLMkVHMGCW1Kzx1g==}
|
||||
dev: false
|
||||
|
||||
/@zag-js/pagination@0.32.1:
|
||||
resolution: {integrity: sha512-lhogzKxJnx5D2Xoni/xm5rkOuy15KWSxqBHVwe8+j5aSNqMy7+aRtEN2F2VQCDVL/v1fdciQvOCA9udm37kZ4w==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/pin-input@0.32.1:
|
||||
resolution: {integrity: sha512-d18cCXKUr7INL0Xm5KyIoiTRSNsPXfIlIEMl2HrAvM3r70wtEag0PmiDNA5NS2tB4LnnX0XowchGB4HsdFS/ng==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/form-utils': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
'@zag-js/visually-hidden': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/popover@0.32.1:
|
||||
resolution: {integrity: sha512-B01if49v3crCjkvtSvIX4CBdT/475nj3DttOObc36s0YOxCEt3UihMITBD5JvIKwEqjZ6oU5t0sLcUYOqQ4f2A==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/aria-hidden': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dismissable': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/popper': 0.32.1
|
||||
'@zag-js/remove-scroll': 0.32.1
|
||||
'@zag-js/tabbable': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
focus-trap: 7.5.4
|
||||
dev: false
|
||||
|
||||
/@zag-js/popper@0.32.1:
|
||||
resolution: {integrity: sha512-aQgogW1N4VreNACSQhXQoZeXtQQtB//FXUvt1CBnW2DtmZ6YkNnaAfn186Q2lkw2/T0chITRy3eYeviwMmMrqg==}
|
||||
dependencies:
|
||||
'@floating-ui/dom': 1.5.4
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/element-rect': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/presence@0.32.1:
|
||||
resolution: {integrity: sha512-8189QMUf/L1dztAZdurx18ZwPyWlq58Mrd+GdATSaf8JstgrI1ovzVs606inQghWptKHMsH7dUIaV9UkhbSx3Q==}
|
||||
dependencies:
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/progress@0.32.1:
|
||||
resolution: {integrity: sha512-ClkQvNYnuIpKfAPUceZXY5E2m/3NnIm21cvHe4gAoJ88YdqEHd5rIRoHP63g8ET8Ct/2KkBRkgR+LrQnGQOomA==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/radio-group@0.32.1:
|
||||
resolution: {integrity: sha512-NvdSjwRF38qIh0oM68jERf71uiwV2JFTrGeQEs3EIqONzULwL6jR2p4P1wm3JJNBAkSYBKZMER5cVUUcqM3kjQ==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/element-rect': 0.32.1
|
||||
'@zag-js/form-utils': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
'@zag-js/visually-hidden': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/rating-group@0.32.1:
|
||||
resolution: {integrity: sha512-RBaFRCw7P00bgTrEjUHT3h/OGRO8XmXKkQYqqhm1tsVbeTsT47iwHoc6XnMEiGBonaJDwN/J0oFasw7GNg5sow==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/form-utils': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/react@0.32.1(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-b1SB7hXXv1K6CmXkcy5Y7mb0YRWkyvulyhK8VW5O5hIAPuGxOTx70psmVeZbmVzhjdORCiro9jKx8Ec0LfolFg==}
|
||||
peerDependencies:
|
||||
react: '>=18.0.0'
|
||||
react-dom: '>=18.0.0'
|
||||
dependencies:
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/store': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
proxy-compare: 2.5.1
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@zag-js/rect-utils@0.32.1:
|
||||
resolution: {integrity: sha512-cI07kgldjUZP+SLhXeG9VSl47nrENlC96Fs7jWcTfHj62rhdY8WsBJ0tiTztvwar9m1chwxXZwJowHN+nPIgDQ==}
|
||||
dev: false
|
||||
|
||||
/@zag-js/remove-scroll@0.32.1:
|
||||
resolution: {integrity: sha512-LyXt2rNMSKb9MKeJRyKTgpk4R7jdA+9kEQTSG5qyA94jo1og7FVgA1W/E+pNkdxDEk1VplL768VU6y7E/L3DHg==}
|
||||
dependencies:
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/select@0.32.1:
|
||||
resolution: {integrity: sha512-jSzmTKCN1Fk/ZDDWM8TVGOtwgpYUDgyceegjYT+hW1mmEetu4tQcEvAr0557NOzh8akqLvcVFbg/kMj0IriKAA==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/collection': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dismissable': 0.32.1
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/form-utils': 0.32.1
|
||||
'@zag-js/mutation-observer': 0.32.1
|
||||
'@zag-js/popper': 0.32.1
|
||||
'@zag-js/tabbable': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
'@zag-js/visually-hidden': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/slider@0.32.1:
|
||||
resolution: {integrity: sha512-iZSB3Y8/Maakxem0Ha3rBRa8AyAplhN5K50Bgz+wsv0VEzNNUmK4QgaTWReWd6SfeTRpnC5ftKCcfM2aQrLm6g==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/element-size': 0.32.1
|
||||
'@zag-js/form-utils': 0.32.1
|
||||
'@zag-js/numeric-range': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/splitter@0.32.1:
|
||||
resolution: {integrity: sha512-NdHLUXtQAlnz6QpdPwcqZCqYul7LaVqsp0hgtXR2PN4HbH+VAaDfY76pUk6LBerUcykChGZvtM9U0A5FCo1x4A==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/number-utils': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/store@0.32.1:
|
||||
resolution: {integrity: sha512-hKwzpqAPljw06oOI+eO+Is2udpmY9GsGfmdoqvZVYoK4f5sawpZY9EC/84tbK9QKWUDTbFS+0Ujc254GUThmDA==}
|
||||
dependencies:
|
||||
proxy-compare: 2.5.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/switch@0.32.1:
|
||||
resolution: {integrity: sha512-+5w/AtINA+jpORX1cuUrnyIFXrfjhqV7667EKK/zbPi0Pf1E10+TEihpfFjY6bgms9CSNWZVEb6w2f2C0PNBDA==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/form-utils': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
'@zag-js/visually-hidden': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/tabbable@0.32.1:
|
||||
resolution: {integrity: sha512-fMXtVgBiX7z3Qmdv+McrfihiSkqsDbNX2nn3e63L7jdy9ZpgnR3jG9BwUZvv7hvzkuOAFhhdKgBYYT+fkBavGg==}
|
||||
dependencies:
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/tabs@0.32.1:
|
||||
resolution: {integrity: sha512-5l8/k2Pw9Kbfsvvx6HWcVqK7Ns7ca+nyPGLSZtZLMp/Zn2q3xSG32C1U3oDaYtQVIQSiEHdnMjw0C2v+CxGDMA==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/element-rect': 0.32.1
|
||||
'@zag-js/tabbable': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/tags-input@0.32.1:
|
||||
resolution: {integrity: sha512-oliLhiMpRNbWFixHF+Oe7hySQBp7NKtL/s8rN5dLT1G1GFRMzuuht/QnmL1h8EoGGpTwaaokMo4zl4uVzHbwyw==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/auto-resize': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/form-utils': 0.32.1
|
||||
'@zag-js/interact-outside': 0.32.1
|
||||
'@zag-js/live-region': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/text-selection@0.32.1:
|
||||
resolution: {integrity: sha512-aK1uswWYF76PFoxGL+3HW/kth9uldFWSW4lOh89NfEcc6Ym7qS5B+P0HKJVM9DuQbihvQX9dyc9PvM7/LJTSRA==}
|
||||
dependencies:
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/toast@0.32.1:
|
||||
resolution: {integrity: sha512-HrfVzFX7ANS9qOewCr8qOCbgko635bZxYKMv+ojjo4U/TtwkGb43+lVU7/qwZj0z18/OtXBH5YQjFwQZXg5x8g==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/toggle-group@0.32.1:
|
||||
resolution: {integrity: sha512-MM1XI4J45rRCZiDHcMtZWud0+bWMu6IcMnrbd9oig330YAF3RzcjTlxX93YRY35F04OUMBq5el9qe3qc2vyMuw==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/tooltip@0.32.1:
|
||||
resolution: {integrity: sha512-+rsmDYTELFBHoYKg5iKShGfRD3H9FJDaZRq915Uc9YnyePMXCnWRgnVp+lk3zI+FDgysQm67SDLRJsR24Iioqg==}
|
||||
dependencies:
|
||||
'@zag-js/anatomy': 0.32.1
|
||||
'@zag-js/core': 0.32.1
|
||||
'@zag-js/dom-event': 0.32.1
|
||||
'@zag-js/dom-query': 0.32.1
|
||||
'@zag-js/popper': 0.32.1
|
||||
'@zag-js/types': 0.32.1
|
||||
'@zag-js/utils': 0.32.1
|
||||
dev: false
|
||||
|
||||
/@zag-js/types@0.32.1:
|
||||
resolution: {integrity: sha512-BLfqb+im4vtXXJqhd2ZUg/4LquEd1qPt9XN56XVjudGDTftN8n3EDpuail7VKxdL59W4jR7wW8lvl4sSgrQKWw==}
|
||||
dependencies:
|
||||
csstype: 3.1.3
|
||||
dev: false
|
||||
|
||||
/@zag-js/utils@0.32.1:
|
||||
resolution: {integrity: sha512-jrcmWYcA3L6TO4fZbPFvpSGEy2Z/mbWt6bPQbmcVgq/BltSS0YxxfPl+eD+S/rZI9aneszwsr04Z5TpladFiVA==}
|
||||
dev: false
|
||||
|
||||
/@zag-js/visually-hidden@0.32.1:
|
||||
resolution: {integrity: sha512-Vzieo4vNulzY/0zqmVfeYW/LcFJp5xtEoyUgR1FBctH8uBPBRhTIEXxKtoMablW6/vccOVo7zcu0UrR5Vx+eYQ==}
|
||||
dev: false
|
||||
|
||||
/accepts@1.3.8:
|
||||
resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
@ -9074,6 +9692,12 @@ packages:
|
||||
tslib: 2.6.2
|
||||
dev: false
|
||||
|
||||
/focus-trap@7.5.4:
|
||||
resolution: {integrity: sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==}
|
||||
dependencies:
|
||||
tabbable: 6.2.0
|
||||
dev: false
|
||||
|
||||
/for-each@0.3.3:
|
||||
resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
|
||||
dependencies:
|
||||
@ -11307,6 +11931,10 @@ packages:
|
||||
ipaddr.js: 1.9.1
|
||||
dev: true
|
||||
|
||||
/proxy-compare@2.5.1:
|
||||
resolution: {integrity: sha512-oyfc0Tx87Cpwva5ZXezSp5V9vht1c7dZBhvuV/y3ctkgMVUmiAGDVeeB0dKhGSyT0v1ZTEQYpe/RXlBVBNuCLA==}
|
||||
dev: false
|
||||
|
||||
/proxy-from-env@1.1.0:
|
||||
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
||||
dev: true
|
||||
@ -11435,7 +12063,7 @@ packages:
|
||||
peerDependencies:
|
||||
react: ^15.3.0 || ^16.0.0 || ^17.0.0 || ^18.0.0
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.7
|
||||
'@babel/runtime': 7.23.8
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
@ -11530,7 +12158,7 @@ packages:
|
||||
'@types/react':
|
||||
optional: true
|
||||
dependencies:
|
||||
'@babel/runtime': 7.23.7
|
||||
'@babel/runtime': 7.23.8
|
||||
'@types/react': 18.2.48
|
||||
focus-lock: 1.0.0
|
||||
prop-types: 15.8.1
|
||||
@ -12777,6 +13405,10 @@ packages:
|
||||
resolution: {integrity: sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g==}
|
||||
dev: true
|
||||
|
||||
/tabbable@6.2.0:
|
||||
resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==}
|
||||
dev: false
|
||||
|
||||
/tapable@2.2.1:
|
||||
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
|
||||
engines: {node: '>=6'}
|
||||
|
@ -110,7 +110,28 @@
|
||||
"somethingWentWrong": "Etwas ist schief gelaufen",
|
||||
"copyError": "$t(gallery.copy) Fehler",
|
||||
"input": "Eingabe",
|
||||
"notInstalled": "Nicht $t(common.installed)"
|
||||
"notInstalled": "Nicht $t(common.installed)",
|
||||
"advancedOptions": "Erweiterte Einstellungen",
|
||||
"alpha": "Alpha",
|
||||
"red": "Rot",
|
||||
"green": "Grün",
|
||||
"blue": "Blau",
|
||||
"delete": "Löschen",
|
||||
"or": "oder",
|
||||
"direction": "Richtung",
|
||||
"free": "Frei",
|
||||
"save": "Speichern",
|
||||
"preferencesLabel": "Präferenzen",
|
||||
"created": "Erstellt",
|
||||
"prevPage": "Vorherige Seite",
|
||||
"nextPage": "Nächste Seite",
|
||||
"unknownError": "Unbekannter Fehler",
|
||||
"unsaved": "Nicht gespeichert",
|
||||
"aboutDesc": "Verwenden Sie Invoke für die Arbeit? Dann siehe hier:",
|
||||
"localSystem": "Lokales System",
|
||||
"orderBy": "Ordnen nach",
|
||||
"saveAs": "Speicher als",
|
||||
"updated": "Aktualisiert"
|
||||
},
|
||||
"gallery": {
|
||||
"generations": "Erzeugungen",
|
||||
@ -701,7 +722,8 @@
|
||||
"invokeProgressBar": "Invoke Fortschrittsanzeige",
|
||||
"mode": "Modus",
|
||||
"resetUI": "$t(accessibility.reset) von UI",
|
||||
"createIssue": "Ticket erstellen"
|
||||
"createIssue": "Ticket erstellen",
|
||||
"about": "Über"
|
||||
},
|
||||
"boards": {
|
||||
"autoAddBoard": "Automatisches Hinzufügen zum Ordner",
|
||||
@ -809,7 +831,8 @@
|
||||
"canny": "Canny",
|
||||
"hedDescription": "Ganzheitlich verschachtelte Kantenerkennung",
|
||||
"scribble": "Scribble",
|
||||
"maxFaces": "Maximal Anzahl Gesichter"
|
||||
"maxFaces": "Maximal Anzahl Gesichter",
|
||||
"resizeSimple": "Größe ändern (einfach)"
|
||||
},
|
||||
"queue": {
|
||||
"status": "Status",
|
||||
@ -999,5 +1022,27 @@
|
||||
"selectLoRA": "Wählen ein LoRA aus",
|
||||
"esrganModel": "ESRGAN Modell",
|
||||
"addLora": "LoRA hinzufügen"
|
||||
},
|
||||
"accordions": {
|
||||
"generation": {
|
||||
"title": "Erstellung",
|
||||
"modelTab": "Modell",
|
||||
"conceptsTab": "Konzepte"
|
||||
},
|
||||
"image": {
|
||||
"title": "Bild"
|
||||
},
|
||||
"advanced": {
|
||||
"title": "Erweitert"
|
||||
},
|
||||
"control": {
|
||||
"title": "Kontrolle",
|
||||
"controlAdaptersTab": "Kontroll Adapter",
|
||||
"ipTab": "Bild Beschreibung"
|
||||
},
|
||||
"compositing": {
|
||||
"coherenceTab": "Kohärenzpass",
|
||||
"infillTab": "Füllung"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -224,6 +224,7 @@
|
||||
"amult": "a_mult",
|
||||
"autoConfigure": "Auto configure processor",
|
||||
"balanced": "Balanced",
|
||||
"base": "Base",
|
||||
"beginEndStepPercent": "Begin / End Step Percentage",
|
||||
"bgth": "bg_th",
|
||||
"canny": "Canny",
|
||||
@ -237,6 +238,8 @@
|
||||
"controlMode": "Control Mode",
|
||||
"crop": "Crop",
|
||||
"delete": "Delete",
|
||||
"depthAnything": "Depth Anything",
|
||||
"depthAnythingDescription": "Depth map generation using the Depth Anything technique",
|
||||
"depthMidas": "Depth (Midas)",
|
||||
"depthMidasDescription": "Depth map generation using Midas",
|
||||
"depthZoe": "Depth (Zoe)",
|
||||
@ -256,6 +259,7 @@
|
||||
"colorMapTileSize": "Tile Size",
|
||||
"importImageFromCanvas": "Import Image From Canvas",
|
||||
"importMaskFromCanvas": "Import Mask From Canvas",
|
||||
"large": "Large",
|
||||
"lineart": "Lineart",
|
||||
"lineartAnime": "Lineart Anime",
|
||||
"lineartAnimeDescription": "Anime-style lineart processing",
|
||||
@ -268,6 +272,7 @@
|
||||
"minConfidence": "Min Confidence",
|
||||
"mlsd": "M-LSD",
|
||||
"mlsdDescription": "Minimalist Line Segment Detector",
|
||||
"modelSize": "Model Size",
|
||||
"none": "None",
|
||||
"noneDescription": "No processing applied",
|
||||
"normalBae": "Normal BAE",
|
||||
@ -288,6 +293,7 @@
|
||||
"selectModel": "Select a model",
|
||||
"setControlImageDimensions": "Set Control Image Dimensions To W/H",
|
||||
"showAdvanced": "Show Advanced",
|
||||
"small": "Small",
|
||||
"toggleControlNet": "Toggle this ControlNet",
|
||||
"w": "W",
|
||||
"weight": "Weight",
|
||||
@ -600,6 +606,10 @@
|
||||
"desc": "Send current image to Image to Image",
|
||||
"title": "Send To Image To Image"
|
||||
},
|
||||
"remixImage": {
|
||||
"desc": "Use all parameters except seed from the current image",
|
||||
"title": "Remix image"
|
||||
},
|
||||
"setParameters": {
|
||||
"desc": "Use all parameters of the current image",
|
||||
"title": "Set Parameters"
|
||||
@ -1216,6 +1226,7 @@
|
||||
"useCpuNoise": "Use CPU Noise",
|
||||
"cpuNoise": "CPU Noise",
|
||||
"gpuNoise": "GPU Noise",
|
||||
"remixImage": "Remix Image",
|
||||
"useInitImg": "Use Initial Image",
|
||||
"usePrompt": "Use Prompt",
|
||||
"useSeed": "Use Seed",
|
||||
@ -1697,6 +1708,7 @@
|
||||
"workflowLibrary": "Library",
|
||||
"userWorkflows": "My Workflows",
|
||||
"defaultWorkflows": "Default Workflows",
|
||||
"projectWorkflows": "Project Workflows",
|
||||
"openWorkflow": "Open Workflow",
|
||||
"uploadWorkflow": "Load from File",
|
||||
"deleteWorkflow": "Delete Workflow",
|
||||
@ -1709,6 +1721,7 @@
|
||||
"workflowSaved": "Workflow Saved",
|
||||
"noRecentWorkflows": "No Recent Workflows",
|
||||
"noUserWorkflows": "No User Workflows",
|
||||
"noWorkflows": "No Workflows",
|
||||
"noSystemWorkflows": "No System Workflows",
|
||||
"problemLoading": "Problem Loading Workflows",
|
||||
"loading": "Loading Workflows",
|
||||
|
@ -118,7 +118,14 @@
|
||||
"advancedOptions": "Opzioni avanzate",
|
||||
"free": "Libero",
|
||||
"or": "o",
|
||||
"preferencesLabel": "Preferenze"
|
||||
"preferencesLabel": "Preferenze",
|
||||
"red": "Rosso",
|
||||
"aboutHeading": "Possiedi il tuo potere creativo",
|
||||
"aboutDesc": "Utilizzi Invoke per lavoro? Guarda qui:",
|
||||
"localSystem": "Sistema locale",
|
||||
"green": "Verde",
|
||||
"blue": "Blu",
|
||||
"alpha": "Alfa"
|
||||
},
|
||||
"gallery": {
|
||||
"generations": "Generazioni",
|
||||
@ -521,7 +528,8 @@
|
||||
"customConfigFileLocation": "Posizione del file di configurazione personalizzato",
|
||||
"vaePrecision": "Precisione VAE",
|
||||
"noModelSelected": "Nessun modello selezionato",
|
||||
"conversionNotSupported": "Conversione non supportata"
|
||||
"conversionNotSupported": "Conversione non supportata",
|
||||
"configFile": "File di configurazione"
|
||||
},
|
||||
"parameters": {
|
||||
"images": "Immagini",
|
||||
@ -660,7 +668,9 @@
|
||||
"lockAspectRatio": "Blocca proporzioni",
|
||||
"swapDimensions": "Scambia dimensioni",
|
||||
"aspect": "Aspetto",
|
||||
"setToOptimalSizeTooLarge": "$t(parameters.setToOptimalSize) (potrebbe essere troppo grande)"
|
||||
"setToOptimalSizeTooLarge": "$t(parameters.setToOptimalSize) (potrebbe essere troppo grande)",
|
||||
"boxBlur": "Box",
|
||||
"gaussianBlur": "Gaussian"
|
||||
},
|
||||
"settings": {
|
||||
"models": "Modelli",
|
||||
@ -794,7 +804,9 @@
|
||||
"invalidUpload": "Caricamento non valido",
|
||||
"problemDeletingWorkflow": "Problema durante l'eliminazione del flusso di lavoro",
|
||||
"workflowDeleted": "Flusso di lavoro eliminato",
|
||||
"problemRetrievingWorkflow": "Problema nel recupero del flusso di lavoro"
|
||||
"problemRetrievingWorkflow": "Problema nel recupero del flusso di lavoro",
|
||||
"resetInitialImage": "Reimposta l'immagine iniziale",
|
||||
"uploadInitialImage": "Carica l'immagine iniziale"
|
||||
},
|
||||
"tooltip": {
|
||||
"feature": {
|
||||
@ -899,7 +911,8 @@
|
||||
"loadMore": "Carica altro",
|
||||
"mode": "Modalità",
|
||||
"resetUI": "$t(accessibility.reset) l'Interfaccia Utente",
|
||||
"createIssue": "Segnala un problema"
|
||||
"createIssue": "Segnala un problema",
|
||||
"about": "Informazioni"
|
||||
},
|
||||
"ui": {
|
||||
"hideProgressImages": "Nascondi avanzamento immagini",
|
||||
|
@ -36,9 +36,9 @@ export const addModelSelectedListener = () => {
|
||||
|
||||
const newModel = result.data;
|
||||
|
||||
const { base_model } = newModel;
|
||||
const newBaseModel = newModel.base_model;
|
||||
const didBaseModelChange =
|
||||
state.generation.model?.base_model !== base_model;
|
||||
state.generation.model?.base_model !== newBaseModel;
|
||||
|
||||
if (didBaseModelChange) {
|
||||
// we may need to reset some incompatible submodels
|
||||
@ -46,7 +46,7 @@ export const addModelSelectedListener = () => {
|
||||
|
||||
// handle incompatible loras
|
||||
forEach(state.lora.loras, (lora, id) => {
|
||||
if (lora.base_model !== base_model) {
|
||||
if (lora.base_model !== newBaseModel) {
|
||||
dispatch(loraRemoved(id));
|
||||
modelsCleared += 1;
|
||||
}
|
||||
@ -54,14 +54,14 @@ export const addModelSelectedListener = () => {
|
||||
|
||||
// handle incompatible vae
|
||||
const { vae } = state.generation;
|
||||
if (vae && vae.base_model !== base_model) {
|
||||
if (vae && vae.base_model !== newBaseModel) {
|
||||
dispatch(vaeSelected(null));
|
||||
modelsCleared += 1;
|
||||
}
|
||||
|
||||
// handle incompatible controlnets
|
||||
selectControlAdapterAll(state.controlAdapters).forEach((ca) => {
|
||||
if (ca.model?.base_model !== base_model) {
|
||||
if (ca.model?.base_model !== newBaseModel) {
|
||||
dispatch(
|
||||
controlAdapterIsEnabledChanged({ id: ca.id, isEnabled: false })
|
||||
);
|
||||
|
@ -46,14 +46,14 @@ export const addDynamicPromptsListener = () => {
|
||||
|
||||
if (cachedPrompts) {
|
||||
dispatch(promptsChanged(cachedPrompts.prompts));
|
||||
dispatch(parsingErrorChanged(cachedPrompts.error));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!getShouldProcessPrompt(state.generation.positivePrompt)) {
|
||||
if (state.dynamicPrompts.isLoading) {
|
||||
dispatch(isLoadingChanged(false));
|
||||
}
|
||||
dispatch(promptsChanged([state.generation.positivePrompt]));
|
||||
dispatch(parsingErrorChanged(undefined));
|
||||
dispatch(isErrorChanged(false));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -78,7 +78,6 @@ export const addDynamicPromptsListener = () => {
|
||||
dispatch(promptsChanged(res.prompts));
|
||||
dispatch(parsingErrorChanged(res.error));
|
||||
dispatch(isErrorChanged(false));
|
||||
dispatch(isLoadingChanged(false));
|
||||
} catch {
|
||||
dispatch(isErrorChanged(true));
|
||||
dispatch(isLoadingChanged(false));
|
||||
|
@ -1,24 +1,35 @@
|
||||
import type { ChakraProps } from '@invoke-ai/ui';
|
||||
import { Box, Flex } from '@invoke-ai/ui';
|
||||
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
|
||||
import { getOverlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
|
||||
import type { CSSProperties, PropsWithChildren } from 'react';
|
||||
import { memo } from 'react';
|
||||
import { memo, useMemo } from 'react';
|
||||
|
||||
type Props = PropsWithChildren & {
|
||||
maxHeight?: ChakraProps['maxHeight'];
|
||||
overflowX?: 'hidden' | 'scroll';
|
||||
overflowY?: 'hidden' | 'scroll';
|
||||
};
|
||||
|
||||
const styles: CSSProperties = { height: '100%', width: '100%' };
|
||||
|
||||
const ScrollableContent = ({ children, maxHeight }: Props) => {
|
||||
const ScrollableContent = ({
|
||||
children,
|
||||
maxHeight,
|
||||
overflowX = 'hidden',
|
||||
overflowY = 'scroll',
|
||||
}: Props) => {
|
||||
const overlayscrollbarsOptions = useMemo(
|
||||
() => getOverlayScrollbarsParams(overflowX, overflowY).options,
|
||||
[overflowX, overflowY]
|
||||
);
|
||||
return (
|
||||
<Flex w="full" h="full" maxHeight={maxHeight} position="relative">
|
||||
<Box position="absolute" top={0} left={0} right={0} bottom={0}>
|
||||
<OverlayScrollbarsComponent
|
||||
defer
|
||||
style={styles}
|
||||
options={overlayScrollbarsParams.options}
|
||||
options={overlayscrollbarsOptions}
|
||||
>
|
||||
{children}
|
||||
</OverlayScrollbarsComponent>
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { cloneDeep, merge } from 'lodash-es';
|
||||
import { ClickScrollPlugin, OverlayScrollbars } from 'overlayscrollbars';
|
||||
import type { UseOverlayScrollbarsParams } from 'overlayscrollbars-react';
|
||||
|
||||
@ -16,3 +17,12 @@ export const overlayScrollbarsParams: UseOverlayScrollbarsParams = {
|
||||
overflow: { x: 'hidden' },
|
||||
},
|
||||
};
|
||||
|
||||
export const getOverlayScrollbarsParams = (
|
||||
overflowX: 'hidden' | 'scroll' = 'hidden',
|
||||
overflowY: 'hidden' | 'scroll' = 'scroll'
|
||||
) => {
|
||||
const params = cloneDeep(overlayScrollbarsParams);
|
||||
merge(params, { options: { overflow: { y: overflowY, x: overflowX } } });
|
||||
return params;
|
||||
};
|
||||
|
@ -1,9 +1,12 @@
|
||||
import type { FormLabelProps } from '@invoke-ai/ui';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
ButtonGroup,
|
||||
Checkbox,
|
||||
Flex,
|
||||
FormControl,
|
||||
FormControlGroup,
|
||||
FormLabel,
|
||||
IconButton,
|
||||
Popover,
|
||||
@ -33,6 +36,10 @@ import {
|
||||
PiTrashSimpleFill,
|
||||
} from 'react-icons/pi';
|
||||
|
||||
const formLabelProps: FormLabelProps = {
|
||||
flexGrow: 1,
|
||||
};
|
||||
|
||||
const IAICanvasMaskOptions = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
@ -124,40 +131,44 @@ const IAICanvasMaskOptions = () => {
|
||||
<PopoverContent>
|
||||
<PopoverBody>
|
||||
<Flex direction="column" gap={2}>
|
||||
<FormControl>
|
||||
<FormLabel>{`${t('unifiedCanvas.enableMask')} (H)`}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={isMaskEnabled}
|
||||
onChange={handleToggleEnableMask}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.preserveMaskedArea')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldPreserveMaskedArea}
|
||||
onChange={handleChangePreserveMaskedArea}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControlGroup formLabelProps={formLabelProps}>
|
||||
<FormControl>
|
||||
<FormLabel>{`${t('unifiedCanvas.enableMask')} (H)`}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={isMaskEnabled}
|
||||
onChange={handleToggleEnableMask}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.preserveMaskedArea')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldPreserveMaskedArea}
|
||||
onChange={handleChangePreserveMaskedArea}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormControlGroup>
|
||||
<Box pt={2} pb={2}>
|
||||
<IAIColorPicker
|
||||
color={maskColor}
|
||||
onChange={handleChangeMaskColor}
|
||||
/>
|
||||
</Box>
|
||||
<Button
|
||||
size="sm"
|
||||
leftIcon={<PiFloppyDiskBackFill />}
|
||||
onClick={handleSaveMask}
|
||||
>
|
||||
{t('unifiedCanvas.saveMask')}
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
leftIcon={<PiTrashSimpleFill />}
|
||||
onClick={handleClearMask}
|
||||
>
|
||||
{t('unifiedCanvas.clearMask')}
|
||||
</Button>
|
||||
<ButtonGroup isAttached={false}>
|
||||
<Button
|
||||
size="sm"
|
||||
leftIcon={<PiFloppyDiskBackFill />}
|
||||
onClick={handleSaveMask}
|
||||
>
|
||||
{t('unifiedCanvas.saveMask')}
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
leftIcon={<PiTrashSimpleFill />}
|
||||
onClick={handleClearMask}
|
||||
>
|
||||
{t('unifiedCanvas.clearMask')}
|
||||
</Button>
|
||||
</ButtonGroup>
|
||||
</Flex>
|
||||
</PopoverBody>
|
||||
</PopoverContent>
|
||||
|
@ -1,7 +1,9 @@
|
||||
import type { FormLabelProps } from '@invoke-ai/ui';
|
||||
import {
|
||||
Checkbox,
|
||||
Flex,
|
||||
FormControl,
|
||||
FormControlGroup,
|
||||
FormLabel,
|
||||
IconButton,
|
||||
Popover,
|
||||
@ -28,6 +30,10 @@ import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiGearSixBold } from 'react-icons/pi';
|
||||
|
||||
const formLabelProps: FormLabelProps = {
|
||||
flexGrow: 1,
|
||||
};
|
||||
|
||||
const IAICanvasSettingsButtonPopover = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
@ -122,69 +128,73 @@ const IAICanvasSettingsButtonPopover = () => {
|
||||
<PopoverContent>
|
||||
<PopoverBody>
|
||||
<Flex direction="column" gap={2}>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.showIntermediates')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldShowIntermediates}
|
||||
onChange={handleChangeShouldShowIntermediates}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.showGrid')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldShowGrid}
|
||||
onChange={handleChangeShouldShowGrid}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.snapToGrid')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldSnapToGrid}
|
||||
onChange={handleChangeShouldSnapToGrid}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.darkenOutsideSelection')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldDarkenOutsideBoundingBox}
|
||||
onChange={handleChangeShouldDarkenOutsideBoundingBox}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.autoSaveToGallery')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldAutoSave}
|
||||
onChange={handleChangeShouldAutoSave}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.saveBoxRegionOnly')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldCropToBoundingBoxOnSave}
|
||||
onChange={handleChangeShouldCropToBoundingBoxOnSave}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.limitStrokesToBox')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldRestrictStrokesToBox}
|
||||
onChange={handleChangeShouldRestrictStrokesToBox}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.showCanvasDebugInfo')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldShowCanvasDebugInfo}
|
||||
onChange={handleChangeShouldShowCanvasDebugInfo}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.antialiasing')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldAntialias}
|
||||
onChange={handleChangeShouldAntialias}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControlGroup formLabelProps={formLabelProps}>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.showIntermediates')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldShowIntermediates}
|
||||
onChange={handleChangeShouldShowIntermediates}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.showGrid')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldShowGrid}
|
||||
onChange={handleChangeShouldShowGrid}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.snapToGrid')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldSnapToGrid}
|
||||
onChange={handleChangeShouldSnapToGrid}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>
|
||||
{t('unifiedCanvas.darkenOutsideSelection')}
|
||||
</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldDarkenOutsideBoundingBox}
|
||||
onChange={handleChangeShouldDarkenOutsideBoundingBox}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.autoSaveToGallery')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldAutoSave}
|
||||
onChange={handleChangeShouldAutoSave}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.saveBoxRegionOnly')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldCropToBoundingBoxOnSave}
|
||||
onChange={handleChangeShouldCropToBoundingBoxOnSave}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.limitStrokesToBox')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldRestrictStrokesToBox}
|
||||
onChange={handleChangeShouldRestrictStrokesToBox}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.showCanvasDebugInfo')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldShowCanvasDebugInfo}
|
||||
onChange={handleChangeShouldShowCanvasDebugInfo}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('unifiedCanvas.antialiasing')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={shouldAntialias}
|
||||
onChange={handleChangeShouldAntialias}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormControlGroup>
|
||||
<ClearCanvasHistoryButtonModal />
|
||||
</Flex>
|
||||
</PopoverBody>
|
||||
|
@ -276,9 +276,9 @@ const IAICanvasToolChooserOptions = () => {
|
||||
</Flex>
|
||||
<Box w="full" pt={2} pb={2}>
|
||||
<IAIColorPicker
|
||||
withNumberInput={true}
|
||||
color={brushColor}
|
||||
onChange={handleChangeBrushColor}
|
||||
withNumberInput
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { ChevronUpIcon } from '@chakra-ui/icons';
|
||||
import {
|
||||
Box,
|
||||
Flex,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
Icon,
|
||||
IconButton,
|
||||
Switch,
|
||||
} from '@invoke-ai/ui';
|
||||
@ -19,7 +19,7 @@ import { activeTabNameSelector } from 'features/ui/store/uiSelectors';
|
||||
import type { ChangeEvent } from 'react';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiCopyBold, PiTrashSimpleBold } from 'react-icons/pi';
|
||||
import { PiCaretUpBold, PiCopyBold, PiTrashSimpleBold } from 'react-icons/pi';
|
||||
import { useToggle } from 'react-use';
|
||||
|
||||
import ControlAdapterImagePreview from './ControlAdapterImagePreview';
|
||||
@ -130,7 +130,9 @@ const ControlAdapterConfig = (props: { id: string; number: number }) => {
|
||||
onClick={toggleIsExpanded}
|
||||
variant="ghost"
|
||||
icon={
|
||||
<ChevronUpIcon
|
||||
<Icon
|
||||
boxSize={4}
|
||||
as={PiCaretUpBold}
|
||||
transform={isExpanded ? 'rotate(0deg)' : 'rotate(180deg)'}
|
||||
transitionProperty="common"
|
||||
transitionDuration="normal"
|
||||
|
@ -5,6 +5,7 @@ import { memo } from 'react';
|
||||
import CannyProcessor from './processors/CannyProcessor';
|
||||
import ColorMapProcessor from './processors/ColorMapProcessor';
|
||||
import ContentShuffleProcessor from './processors/ContentShuffleProcessor';
|
||||
import DepthAnyThingProcessor from './processors/DepthAnyThingProcessor';
|
||||
import HedProcessor from './processors/HedProcessor';
|
||||
import LineartAnimeProcessor from './processors/LineartAnimeProcessor';
|
||||
import LineartProcessor from './processors/LineartProcessor';
|
||||
@ -48,6 +49,16 @@ const ControlAdapterProcessorComponent = ({ id }: Props) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (processorNode.type === 'depth_anything_image_processor') {
|
||||
return (
|
||||
<DepthAnyThingProcessor
|
||||
controlNetId={id}
|
||||
processorNode={processorNode}
|
||||
isEnabled={isEnabled}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (processorNode.type === 'hed_image_processor') {
|
||||
return (
|
||||
<HedProcessor
|
||||
|
@ -0,0 +1,110 @@
|
||||
import type { ComboboxOnChange } from '@invoke-ai/ui';
|
||||
import {
|
||||
Combobox,
|
||||
CompositeNumberInput,
|
||||
CompositeSlider,
|
||||
FormControl,
|
||||
FormLabel,
|
||||
} from '@invoke-ai/ui';
|
||||
import { useProcessorNodeChanged } from 'features/controlAdapters/components/hooks/useProcessorNodeChanged';
|
||||
import { CONTROLNET_PROCESSORS } from 'features/controlAdapters/store/constants';
|
||||
import type {
|
||||
DepthAnythingModelSize,
|
||||
RequiredDepthAnythingImageProcessorInvocation,
|
||||
} from 'features/controlAdapters/store/types';
|
||||
import { isDepthAnythingModelSize } from 'features/controlAdapters/store/types';
|
||||
import { memo, useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import ProcessorWrapper from './common/ProcessorWrapper';
|
||||
|
||||
const DEFAULTS = CONTROLNET_PROCESSORS.midas_depth_image_processor
|
||||
.default as RequiredDepthAnythingImageProcessorInvocation;
|
||||
|
||||
type Props = {
|
||||
controlNetId: string;
|
||||
processorNode: RequiredDepthAnythingImageProcessorInvocation;
|
||||
isEnabled: boolean;
|
||||
};
|
||||
|
||||
const DepthAnythingProcessor = (props: Props) => {
|
||||
const { controlNetId, processorNode, isEnabled } = props;
|
||||
const { model_size, resolution } = processorNode;
|
||||
const processorChanged = useProcessorNodeChanged();
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const handleModelSizeChange = useCallback<ComboboxOnChange>(
|
||||
(v) => {
|
||||
if (!isDepthAnythingModelSize(v?.value)) {
|
||||
return;
|
||||
}
|
||||
processorChanged(controlNetId, {
|
||||
model_size: v.value,
|
||||
});
|
||||
},
|
||||
[controlNetId, processorChanged]
|
||||
);
|
||||
|
||||
const options: { label: string; value: DepthAnythingModelSize }[] = useMemo(
|
||||
() => [
|
||||
{ label: t('controlnet.small'), value: 'small' },
|
||||
{ label: t('controlnet.base'), value: 'base' },
|
||||
{ label: t('controlnet.large'), value: 'large' },
|
||||
],
|
||||
[t]
|
||||
);
|
||||
|
||||
const value = useMemo(
|
||||
() => options.filter((o) => o.value === model_size)[0],
|
||||
[options, model_size]
|
||||
);
|
||||
|
||||
const handleResolutionChange = useCallback(
|
||||
(v: number) => {
|
||||
processorChanged(controlNetId, { resolution: v });
|
||||
},
|
||||
[controlNetId, processorChanged]
|
||||
);
|
||||
|
||||
const handleResolutionDefaultChange = useCallback(() => {
|
||||
processorChanged(controlNetId, { resolution: 512 });
|
||||
}, [controlNetId, processorChanged]);
|
||||
|
||||
return (
|
||||
<ProcessorWrapper>
|
||||
<FormControl isDisabled={!isEnabled}>
|
||||
<FormLabel>{t('controlnet.modelSize')}</FormLabel>
|
||||
<Combobox
|
||||
value={value}
|
||||
defaultInputValue={DEFAULTS.model_size}
|
||||
options={options}
|
||||
onChange={handleModelSizeChange}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl isDisabled={!isEnabled}>
|
||||
<FormLabel>{t('controlnet.imageResolution')}</FormLabel>
|
||||
<CompositeSlider
|
||||
value={resolution}
|
||||
onChange={handleResolutionChange}
|
||||
defaultValue={DEFAULTS.resolution}
|
||||
min={64}
|
||||
max={4096}
|
||||
step={64}
|
||||
marks
|
||||
onReset={handleResolutionDefaultChange}
|
||||
/>
|
||||
<CompositeNumberInput
|
||||
value={resolution}
|
||||
onChange={handleResolutionChange}
|
||||
defaultValue={DEFAULTS.resolution}
|
||||
min={64}
|
||||
max={4096}
|
||||
step={64}
|
||||
/>
|
||||
</FormControl>
|
||||
</ProcessorWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export default memo(DepthAnythingProcessor);
|
@ -83,6 +83,22 @@ export const CONTROLNET_PROCESSORS: ControlNetProcessorsDict = {
|
||||
f: 256,
|
||||
},
|
||||
},
|
||||
depth_anything_image_processor: {
|
||||
type: 'depth_anything_image_processor',
|
||||
get label() {
|
||||
return i18n.t('controlnet.depthAnything');
|
||||
},
|
||||
get description() {
|
||||
return i18n.t('controlnet.depthAnythingDescription');
|
||||
},
|
||||
default: {
|
||||
id: 'depth_anything_image_processor',
|
||||
type: 'depth_anything_image_processor',
|
||||
model_size: 'small',
|
||||
resolution: 512,
|
||||
offload: false,
|
||||
},
|
||||
},
|
||||
hed_image_processor: {
|
||||
type: 'hed_image_processor',
|
||||
get label() {
|
||||
@ -245,7 +261,7 @@ export const CONTROLNET_MODEL_DEFAULT_PROCESSORS: {
|
||||
} = {
|
||||
canny: 'canny_image_processor',
|
||||
mlsd: 'mlsd_image_processor',
|
||||
depth: 'midas_depth_image_processor',
|
||||
depth: 'depth_anything_image_processor',
|
||||
bae: 'normalbae_image_processor',
|
||||
sketch: 'pidi_image_processor',
|
||||
scribble: 'lineart_image_processor',
|
||||
|
@ -10,6 +10,7 @@ import type {
|
||||
CannyImageProcessorInvocation,
|
||||
ColorMapImageProcessorInvocation,
|
||||
ContentShuffleImageProcessorInvocation,
|
||||
DepthAnythingImageProcessorInvocation,
|
||||
HedImageProcessorInvocation,
|
||||
LineartAnimeImageProcessorInvocation,
|
||||
LineartImageProcessorInvocation,
|
||||
@ -31,6 +32,7 @@ export type ControlAdapterProcessorNode =
|
||||
| CannyImageProcessorInvocation
|
||||
| ColorMapImageProcessorInvocation
|
||||
| ContentShuffleImageProcessorInvocation
|
||||
| DepthAnythingImageProcessorInvocation
|
||||
| HedImageProcessorInvocation
|
||||
| LineartAnimeImageProcessorInvocation
|
||||
| LineartImageProcessorInvocation
|
||||
@ -73,6 +75,20 @@ export type RequiredContentShuffleImageProcessorInvocation = O.Required<
|
||||
'type' | 'detect_resolution' | 'image_resolution' | 'w' | 'h' | 'f'
|
||||
>;
|
||||
|
||||
/**
|
||||
* The DepthAnything processor node, with parameters flagged as required
|
||||
*/
|
||||
export type RequiredDepthAnythingImageProcessorInvocation = O.Required<
|
||||
DepthAnythingImageProcessorInvocation,
|
||||
'type' | 'model_size' | 'resolution' | 'offload'
|
||||
>;
|
||||
|
||||
export const zDepthAnythingModelSize = z.enum(['large', 'base', 'small']);
|
||||
export type DepthAnythingModelSize = z.infer<typeof zDepthAnythingModelSize>;
|
||||
export const isDepthAnythingModelSize = (
|
||||
v: unknown
|
||||
): v is DepthAnythingModelSize => zDepthAnythingModelSize.safeParse(v).success;
|
||||
|
||||
/**
|
||||
* The HED processor node, with parameters flagged as required
|
||||
*/
|
||||
@ -161,6 +177,7 @@ export type RequiredControlAdapterProcessorNode =
|
||||
| RequiredCannyImageProcessorInvocation
|
||||
| RequiredColorMapImageProcessorInvocation
|
||||
| RequiredContentShuffleImageProcessorInvocation
|
||||
| RequiredDepthAnythingImageProcessorInvocation
|
||||
| RequiredHedImageProcessorInvocation
|
||||
| RequiredLineartAnimeImageProcessorInvocation
|
||||
| RequiredLineartImageProcessorInvocation
|
||||
@ -219,6 +236,22 @@ export const isContentShuffleImageProcessorInvocation = (
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Type guard for DepthAnythingImageProcessorInvocation
|
||||
*/
|
||||
export const isDepthAnythingImageProcessorInvocation = (
|
||||
obj: unknown
|
||||
): obj is DepthAnythingImageProcessorInvocation => {
|
||||
if (
|
||||
isObject(obj) &&
|
||||
'type' in obj &&
|
||||
obj.type === 'depth_anything_image_processor'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Type guard for HedImageprocessorInvocation
|
||||
*/
|
||||
|
@ -61,7 +61,12 @@ const ParamDynamicPromptsPreview = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<FormControl orientation="vertical" w="full" h="full">
|
||||
<FormControl
|
||||
orientation="vertical"
|
||||
w="full"
|
||||
h="full"
|
||||
isInvalid={Boolean(parsingError || isError)}
|
||||
>
|
||||
<InformationalPopover feature="dynamicPrompts" inPortal={false}>
|
||||
<FormLabel>{label}</FormLabel>
|
||||
</InformationalPopover>
|
||||
|
@ -13,7 +13,11 @@ const loadingStyles: SystemStyleObject = {
|
||||
export const ShowDynamicPromptsPreviewButton = memo(() => {
|
||||
const { t } = useTranslation();
|
||||
const isLoading = useAppSelector((s) => s.dynamicPrompts.isLoading);
|
||||
const isError = useAppSelector((s) =>
|
||||
Boolean(s.dynamicPrompts.isError || s.dynamicPrompts.parsingError)
|
||||
);
|
||||
const { isOpen, onOpen } = useDynamicPromptsModal();
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
label={
|
||||
@ -30,6 +34,7 @@ export const ShowDynamicPromptsPreviewButton = memo(() => {
|
||||
icon={<BsBracesAsterisk />}
|
||||
onClick={onOpen}
|
||||
sx={isLoading ? loadingStyles : undefined}
|
||||
colorScheme={isError && !isLoading ? 'error' : 'base'}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
|
@ -47,6 +47,7 @@ export const dynamicPromptsSlice = createSlice({
|
||||
},
|
||||
promptsChanged: (state, action: PayloadAction<string[]>) => {
|
||||
state.prompts = action.payload;
|
||||
state.isLoading = false;
|
||||
},
|
||||
parsingErrorChanged: (
|
||||
state,
|
||||
|
@ -1,3 +1,3 @@
|
||||
const hasOpenCloseCurlyBracesRegex = /.*\{.*\}.*/;
|
||||
const hasOpenCloseCurlyBracesRegex = /.*\{[\s\S]*\}.*/;
|
||||
export const getShouldProcessPrompt = (prompt: string): boolean =>
|
||||
hasOpenCloseCurlyBracesRegex.test(prompt);
|
||||
|
@ -58,7 +58,7 @@ const BoardsSearch = () => {
|
||||
<IconButton
|
||||
onClick={clearBoardSearch}
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
variant="link"
|
||||
aria-label={t('boards.clearSearch')}
|
||||
icon={<PiXBold />}
|
||||
/>
|
||||
|
@ -32,6 +32,7 @@ import { memo, useCallback } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
PiArrowsCounterClockwiseBold,
|
||||
PiAsteriskBold,
|
||||
PiDotsThreeOutlineFill,
|
||||
PiFlowArrowBold,
|
||||
@ -129,6 +130,16 @@ const CurrentImageButtons = () => {
|
||||
|
||||
useHotkeys('p', handleUsePrompt, [metadata]);
|
||||
|
||||
const handleRemixImage = useCallback(() => {
|
||||
// Recalls all metadata parameters except seed
|
||||
recallAllParameters({
|
||||
...metadata,
|
||||
seed: undefined,
|
||||
});
|
||||
}, [metadata, recallAllParameters]);
|
||||
|
||||
useHotkeys('r', handleRemixImage, [metadata]);
|
||||
|
||||
const handleUseSize = useCallback(() => {
|
||||
recallWidthAndHeight(metadata?.width, metadata?.height);
|
||||
}, [metadata?.width, metadata?.height, recallWidthAndHeight]);
|
||||
@ -231,6 +242,14 @@ const CurrentImageButtons = () => {
|
||||
onClick={handleLoadWorkflow}
|
||||
isLoading={getAndLoadEmbeddedWorkflowResult.isLoading}
|
||||
/>
|
||||
<IconButton
|
||||
isLoading={isLoadingMetadata}
|
||||
icon={<PiArrowsCounterClockwiseBold />}
|
||||
tooltip={`${t('parameters.remixImage')} (R)`}
|
||||
aria-label={`${t('parameters.remixImage')} (R)`}
|
||||
isDisabled={!metadata?.positive_prompt}
|
||||
onClick={handleRemixImage}
|
||||
/>
|
||||
<IconButton
|
||||
isLoading={isLoadingMetadata}
|
||||
icon={<PiQuotesBold />}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ChevronUpIcon } from '@chakra-ui/icons';
|
||||
import { Button, Flex, Spacer } from '@invoke-ai/ui';
|
||||
import { Button, Flex, Icon, Spacer } from '@invoke-ai/ui';
|
||||
import { useAppSelector } from 'app/store/storeHooks';
|
||||
import { memo, useMemo } from 'react';
|
||||
import { PiCaretUpBold } from 'react-icons/pi';
|
||||
import { useBoardName } from 'services/api/hooks/useBoardName';
|
||||
|
||||
type Props = {
|
||||
@ -36,7 +36,9 @@ const GalleryBoardName = (props: Props) => {
|
||||
<Spacer />
|
||||
{formattedBoardName}
|
||||
<Spacer />
|
||||
<ChevronUpIcon
|
||||
<Icon
|
||||
as={PiCaretUpBold}
|
||||
boxSize={4}
|
||||
transform={isOpen ? 'rotate(0deg)' : 'rotate(180deg)'}
|
||||
transitionProperty="common"
|
||||
transitionDuration="normal"
|
||||
|
@ -1,8 +1,10 @@
|
||||
import type { FormLabelProps } from '@invoke-ai/ui';
|
||||
import {
|
||||
Checkbox,
|
||||
CompositeSlider,
|
||||
Flex,
|
||||
FormControl,
|
||||
FormControlGroup,
|
||||
FormLabel,
|
||||
IconButton,
|
||||
Popover,
|
||||
@ -24,6 +26,10 @@ import { RiSettings4Fill } from 'react-icons/ri';
|
||||
|
||||
import BoardAutoAddSelect from './Boards/BoardAutoAddSelect';
|
||||
|
||||
const formLabelProps: FormLabelProps = {
|
||||
flexGrow: 1,
|
||||
};
|
||||
|
||||
const GallerySettingsPopover = () => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { t } = useTranslation();
|
||||
@ -78,20 +84,22 @@ const GallerySettingsPopover = () => {
|
||||
defaultValue={90}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('gallery.autoSwitchNewImages')}</FormLabel>
|
||||
<Switch
|
||||
isChecked={shouldAutoSwitch}
|
||||
onChange={handleChangeAutoSwitch}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('gallery.autoAssignBoardOnClick')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={autoAssignBoardOnClick}
|
||||
onChange={handleChangeAutoAssignBoardOnClick}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControlGroup formLabelProps={formLabelProps}>
|
||||
<FormControl>
|
||||
<FormLabel>{t('gallery.autoSwitchNewImages')}</FormLabel>
|
||||
<Switch
|
||||
isChecked={shouldAutoSwitch}
|
||||
onChange={handleChangeAutoSwitch}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('gallery.autoAssignBoardOnClick')}</FormLabel>
|
||||
<Checkbox
|
||||
isChecked={autoAssignBoardOnClick}
|
||||
onChange={handleChangeAutoAssignBoardOnClick}
|
||||
/>
|
||||
</FormControl>
|
||||
</FormControlGroup>
|
||||
<BoardAutoAddSelect />
|
||||
</Flex>
|
||||
</PopoverBody>
|
||||
|
@ -24,6 +24,7 @@ import { memo, useCallback } from 'react';
|
||||
import { flushSync } from 'react-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
PiArrowsCounterClockwiseBold,
|
||||
PiAsteriskBold,
|
||||
PiCopyBold,
|
||||
PiDownloadSimpleBold,
|
||||
@ -127,6 +128,14 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
|
||||
recallAllParameters(metadata);
|
||||
}, [metadata, recallAllParameters]);
|
||||
|
||||
const handleRemixImage = useCallback(() => {
|
||||
// Recalls all metadata parameters except seed
|
||||
recallAllParameters({
|
||||
...metadata,
|
||||
seed: undefined,
|
||||
});
|
||||
}, [metadata, recallAllParameters]);
|
||||
|
||||
const handleChangeBoard = useCallback(() => {
|
||||
dispatch(imagesToChangeSelected([imageDTO]));
|
||||
dispatch(isModalOpenChanged(true));
|
||||
@ -187,6 +196,19 @@ const SingleSelectionMenuItems = (props: SingleSelectionMenuItemsProps) => {
|
||||
>
|
||||
{t('nodes.loadWorkflow')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
icon={
|
||||
isLoadingMetadata ? <SpinnerIcon /> : <PiArrowsCounterClockwiseBold />
|
||||
}
|
||||
onClickCapture={handleRemixImage}
|
||||
isDisabled={
|
||||
isLoadingMetadata ||
|
||||
(metadata?.positive_prompt === undefined &&
|
||||
metadata?.negative_prompt === undefined)
|
||||
}
|
||||
>
|
||||
{t('parameters.remixImage')}
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
icon={isLoadingMetadata ? <SpinnerIcon /> : <PiQuotesBold />}
|
||||
onClickCapture={handleRecallPrompt}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Box, Flex, IconButton, Tooltip } from '@invoke-ai/ui';
|
||||
import { overlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
|
||||
import { getOverlayScrollbarsParams } from 'common/components/OverlayScrollbars/constants';
|
||||
import { isString } from 'lodash-es';
|
||||
import { OverlayScrollbarsComponent } from 'overlayscrollbars-react';
|
||||
import type { CSSProperties } from 'react';
|
||||
@ -15,6 +15,11 @@ type Props = {
|
||||
withCopy?: boolean;
|
||||
};
|
||||
|
||||
const overlayscrollbarsOptions = getOverlayScrollbarsParams(
|
||||
'scroll',
|
||||
'scroll'
|
||||
).options;
|
||||
|
||||
const DataViewer = (props: Props) => {
|
||||
const { label, data, fileName, withDownload = true, withCopy = true } = props;
|
||||
const dataString = useMemo(
|
||||
@ -60,7 +65,7 @@ const DataViewer = (props: Props) => {
|
||||
<OverlayScrollbarsComponent
|
||||
defer
|
||||
style={overlayScrollbarsStyles}
|
||||
options={overlayScrollbarsParams.options}
|
||||
options={overlayscrollbarsOptions}
|
||||
>
|
||||
<pre>{dataString}</pre>
|
||||
</OverlayScrollbarsComponent>
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { ExternalLinkIcon } from '@chakra-ui/icons';
|
||||
import { Flex, IconButton, Link, Text, Tooltip } from '@invoke-ai/ui';
|
||||
import { ExternalLink, Flex, IconButton, Text, Tooltip } from '@invoke-ai/ui';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { IoArrowUndoCircleOutline } from 'react-icons/io5';
|
||||
@ -67,9 +66,7 @@ const ImageMetadataItem = ({
|
||||
{label}:
|
||||
</Text>
|
||||
{isLink ? (
|
||||
<Link href={value.toString()} isExternal wordBreak="break-all">
|
||||
{value.toString()} <ExternalLinkIcon mx="2px" />
|
||||
</Link>
|
||||
<ExternalLink href={value.toString()} label={value.toString()} />
|
||||
) : (
|
||||
<Text overflowY="scroll" wordBreak="break-all">
|
||||
{value.toString()}
|
||||
|
@ -1,13 +1,11 @@
|
||||
import { ExternalLinkIcon } from '@chakra-ui/icons';
|
||||
import {
|
||||
ExternalLink,
|
||||
Flex,
|
||||
Link,
|
||||
Tab,
|
||||
TabList,
|
||||
TabPanel,
|
||||
TabPanels,
|
||||
Tabs,
|
||||
Text,
|
||||
} from '@invoke-ai/ui';
|
||||
import { IAINoContentFallback } from 'common/components/IAIImageFallback';
|
||||
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
||||
@ -46,13 +44,7 @@ const ImageMetadataViewer = ({ image }: ImageMetadataViewerProps) => {
|
||||
position="absolute"
|
||||
overflow="hidden"
|
||||
>
|
||||
<Flex gap={2}>
|
||||
<Text fontWeight="semibold">{t('common.file')}:</Text>
|
||||
<Link href={image.image_url} isExternal maxW="calc(100% - 3rem)">
|
||||
{image.image_name}
|
||||
<ExternalLinkIcon mx="2px" />
|
||||
</Link>
|
||||
</Flex>
|
||||
<ExternalLink href={image.image_url} label={image.image_name} />
|
||||
|
||||
<Tabs
|
||||
variant="line"
|
||||
|
@ -122,13 +122,10 @@ const AdvancedAddDiffusers = (props: AdvancedAddDiffusersProps) => {
|
||||
<FormErrorMessage>{errors.model_name?.message}</FormErrorMessage>
|
||||
)}
|
||||
</FormControl>
|
||||
<FormControl>
|
||||
<FormLabel>{t('modelManager.baseModel')}</FormLabel>
|
||||
<BaseModelSelect<DiffusersModelConfig>
|
||||
control={control}
|
||||
name="base_model"
|
||||
/>
|
||||
</FormControl>
|
||||
<BaseModelSelect<DiffusersModelConfig>
|
||||
control={control}
|
||||
name="base_model"
|
||||
/>
|
||||
<FormControl isInvalid={Boolean(errors.path)}>
|
||||
<FormLabel>{t('modelManager.modelLocation')}</FormLabel>
|
||||
<Input
|
||||
@ -137,7 +134,7 @@ const AdvancedAddDiffusers = (props: AdvancedAddDiffusersProps) => {
|
||||
value.trim().length > 0 || 'Must provide a path',
|
||||
onBlur,
|
||||
})}
|
||||
/>{' '}
|
||||
/>
|
||||
{errors.path?.message && (
|
||||
<FormErrorMessage>{errors.path?.message}</FormErrorMessage>
|
||||
)}
|
||||
|
@ -109,28 +109,28 @@ const InputField = ({ nodeId, fieldName }: Props) => {
|
||||
|
||||
return (
|
||||
<InputFieldWrapper shouldDim={shouldDim}>
|
||||
<FieldContextMenu nodeId={nodeId} fieldName={fieldName} kind="input">
|
||||
{(ref) => (
|
||||
<FormControl
|
||||
ref={ref}
|
||||
isInvalid={isMissingInput}
|
||||
isDisabled={isConnected}
|
||||
orientation="vertical"
|
||||
px={2}
|
||||
>
|
||||
<Flex flexDir="column" w="full" gap={1}>
|
||||
<FormControl
|
||||
isInvalid={isMissingInput}
|
||||
isDisabled={isConnected}
|
||||
orientation="vertical"
|
||||
px={2}
|
||||
>
|
||||
<Flex flexDir="column" w="full" gap={1}>
|
||||
<FieldContextMenu nodeId={nodeId} fieldName={fieldName} kind="input">
|
||||
{(ref) => (
|
||||
<EditableFieldTitle
|
||||
ref={ref}
|
||||
nodeId={nodeId}
|
||||
fieldName={fieldName}
|
||||
kind="input"
|
||||
isMissingInput={isMissingInput}
|
||||
withTooltip
|
||||
/>
|
||||
<InputFieldRenderer nodeId={nodeId} fieldName={fieldName} />
|
||||
</Flex>
|
||||
</FormControl>
|
||||
)}
|
||||
</FieldContextMenu>
|
||||
)}
|
||||
</FieldContextMenu>
|
||||
<InputFieldRenderer nodeId={nodeId} fieldName={fieldName} />
|
||||
</Flex>
|
||||
</FormControl>
|
||||
|
||||
{fieldTemplate.input !== 'direct' && (
|
||||
<FieldHandle
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { ChevronUpIcon } from '@chakra-ui/icons';
|
||||
import { IconButton } from '@invoke-ai/ui';
|
||||
import { Icon, IconButton } from '@invoke-ai/ui';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { nodeIsOpenChanged } from 'features/nodes/store/nodesSlice';
|
||||
import { memo, useCallback } from 'react';
|
||||
import { PiCaretUpBold } from 'react-icons/pi';
|
||||
import { useUpdateNodeInternals } from 'reactflow';
|
||||
|
||||
interface Props {
|
||||
@ -29,7 +29,8 @@ const NodeCollapseButton = ({ nodeId, isOpen }: Props) => {
|
||||
h={8}
|
||||
variant="link"
|
||||
icon={
|
||||
<ChevronUpIcon
|
||||
<Icon
|
||||
as={PiCaretUpBold}
|
||||
transform={isOpen ? 'rotate(0deg)' : 'rotate(180deg)'}
|
||||
transitionProperty="common"
|
||||
transitionDuration="normal"
|
||||
|
@ -65,7 +65,7 @@ export const zModelType = z.enum([
|
||||
'controlnet',
|
||||
'embedding',
|
||||
]);
|
||||
export const zModelName = z.string().trim().min(1);
|
||||
export const zModelName = z.string().min(3);
|
||||
export const zModelIdentifier = z.object({
|
||||
model_name: zModelName,
|
||||
base_model: zBaseModel,
|
||||
|
@ -15,7 +15,7 @@ export type XYPosition = z.infer<typeof zXYPosition>;
|
||||
export const zDimension = z.number().gt(0).nullish();
|
||||
export type Dimension = z.infer<typeof zDimension>;
|
||||
|
||||
export const zWorkflowCategory = z.enum(['user', 'default']);
|
||||
export const zWorkflowCategory = z.enum(['user', 'default', 'project']);
|
||||
export type WorkflowCategory = z.infer<typeof zWorkflowCategory>;
|
||||
// #endregion
|
||||
|
||||
|
@ -34,7 +34,7 @@ import {
|
||||
modelSelected,
|
||||
} from 'features/parameters/store/actions';
|
||||
import {
|
||||
heightChanged,
|
||||
heightRecalled,
|
||||
selectGenerationSlice,
|
||||
setCfgRescaleMultiplier,
|
||||
setCfgScale,
|
||||
@ -45,8 +45,9 @@ import {
|
||||
setSeed,
|
||||
setSteps,
|
||||
vaeSelected,
|
||||
widthChanged,
|
||||
widthRecalled,
|
||||
} from 'features/parameters/store/generationSlice';
|
||||
import type { ParameterModel } from 'features/parameters/types/parameterSchemas';
|
||||
import {
|
||||
isParameterCFGRescaleMultiplier,
|
||||
isParameterCFGScale,
|
||||
@ -372,7 +373,7 @@ export const useRecallParameters = () => {
|
||||
parameterNotSetToast();
|
||||
return;
|
||||
}
|
||||
dispatch(widthChanged(width));
|
||||
dispatch(widthRecalled(width));
|
||||
parameterSetToast();
|
||||
},
|
||||
[dispatch, parameterSetToast, parameterNotSetToast]
|
||||
@ -387,7 +388,7 @@ export const useRecallParameters = () => {
|
||||
parameterNotSetToast();
|
||||
return;
|
||||
}
|
||||
dispatch(heightChanged(height));
|
||||
dispatch(heightRecalled(height));
|
||||
parameterSetToast();
|
||||
},
|
||||
[dispatch, parameterSetToast, parameterNotSetToast]
|
||||
@ -406,8 +407,8 @@ export const useRecallParameters = () => {
|
||||
allParameterNotSetToast();
|
||||
return;
|
||||
}
|
||||
dispatch(heightChanged(height));
|
||||
dispatch(widthChanged(width));
|
||||
dispatch(heightRecalled(height));
|
||||
dispatch(widthRecalled(width));
|
||||
allParameterSetToast();
|
||||
},
|
||||
[dispatch, allParameterSetToast, allParameterNotSetToast]
|
||||
@ -480,7 +481,7 @@ export const useRecallParameters = () => {
|
||||
const { data: loraModels } = useGetLoRAModelsQuery(undefined);
|
||||
|
||||
const prepareLoRAMetadataItem = useCallback(
|
||||
(loraMetadataItem: LoRAMetadataItem) => {
|
||||
(loraMetadataItem: LoRAMetadataItem, newModel?: ParameterModel) => {
|
||||
if (!isParameterLoRAModel(loraMetadataItem.lora)) {
|
||||
return { lora: null, error: 'Invalid LoRA model' };
|
||||
}
|
||||
@ -499,7 +500,7 @@ export const useRecallParameters = () => {
|
||||
}
|
||||
|
||||
const isCompatibleBaseModel =
|
||||
matchingLoRA?.base_model === model?.base_model;
|
||||
matchingLoRA?.base_model === (newModel ?? model)?.base_model;
|
||||
|
||||
if (!isCompatibleBaseModel) {
|
||||
return {
|
||||
@ -510,7 +511,7 @@ export const useRecallParameters = () => {
|
||||
|
||||
return { lora: matchingLoRA, error: null };
|
||||
},
|
||||
[loraModels, model?.base_model]
|
||||
[loraModels, model]
|
||||
);
|
||||
|
||||
const recallLoRA = useCallback(
|
||||
@ -538,7 +539,10 @@ export const useRecallParameters = () => {
|
||||
const { data: controlNetModels } = useGetControlNetModelsQuery(undefined);
|
||||
|
||||
const prepareControlNetMetadataItem = useCallback(
|
||||
(controlnetMetadataItem: ControlNetMetadataItem) => {
|
||||
(
|
||||
controlnetMetadataItem: ControlNetMetadataItem,
|
||||
newModel?: ParameterModel
|
||||
) => {
|
||||
if (!isParameterControlNetModel(controlnetMetadataItem.control_model)) {
|
||||
return { controlnet: null, error: 'Invalid ControlNet model' };
|
||||
}
|
||||
@ -565,7 +569,7 @@ export const useRecallParameters = () => {
|
||||
}
|
||||
|
||||
const isCompatibleBaseModel =
|
||||
matchingControlNetModel?.base_model === model?.base_model;
|
||||
matchingControlNetModel?.base_model === (newModel ?? model)?.base_model;
|
||||
|
||||
if (!isCompatibleBaseModel) {
|
||||
return {
|
||||
@ -600,7 +604,7 @@ export const useRecallParameters = () => {
|
||||
|
||||
return { controlnet, error: null };
|
||||
},
|
||||
[controlNetModels, model?.base_model]
|
||||
[controlNetModels, model]
|
||||
);
|
||||
|
||||
const recallControlNet = useCallback(
|
||||
@ -631,7 +635,10 @@ export const useRecallParameters = () => {
|
||||
const { data: t2iAdapterModels } = useGetT2IAdapterModelsQuery(undefined);
|
||||
|
||||
const prepareT2IAdapterMetadataItem = useCallback(
|
||||
(t2iAdapterMetadataItem: T2IAdapterMetadataItem) => {
|
||||
(
|
||||
t2iAdapterMetadataItem: T2IAdapterMetadataItem,
|
||||
newModel?: ParameterModel
|
||||
) => {
|
||||
if (
|
||||
!isParameterControlNetModel(t2iAdapterMetadataItem.t2i_adapter_model)
|
||||
) {
|
||||
@ -659,7 +666,7 @@ export const useRecallParameters = () => {
|
||||
}
|
||||
|
||||
const isCompatibleBaseModel =
|
||||
matchingT2IAdapterModel?.base_model === model?.base_model;
|
||||
matchingT2IAdapterModel?.base_model === (newModel ?? model)?.base_model;
|
||||
|
||||
if (!isCompatibleBaseModel) {
|
||||
return {
|
||||
@ -690,7 +697,7 @@ export const useRecallParameters = () => {
|
||||
|
||||
return { t2iAdapter, error: null };
|
||||
},
|
||||
[model?.base_model, t2iAdapterModels]
|
||||
[model, t2iAdapterModels]
|
||||
);
|
||||
|
||||
const recallT2IAdapter = useCallback(
|
||||
@ -721,7 +728,10 @@ export const useRecallParameters = () => {
|
||||
const { data: ipAdapterModels } = useGetIPAdapterModelsQuery(undefined);
|
||||
|
||||
const prepareIPAdapterMetadataItem = useCallback(
|
||||
(ipAdapterMetadataItem: IPAdapterMetadataItem) => {
|
||||
(
|
||||
ipAdapterMetadataItem: IPAdapterMetadataItem,
|
||||
newModel?: ParameterModel
|
||||
) => {
|
||||
if (!isParameterIPAdapterModel(ipAdapterMetadataItem?.ip_adapter_model)) {
|
||||
return { ipAdapter: null, error: 'Invalid IP Adapter model' };
|
||||
}
|
||||
@ -746,7 +756,7 @@ export const useRecallParameters = () => {
|
||||
}
|
||||
|
||||
const isCompatibleBaseModel =
|
||||
matchingIPAdapterModel?.base_model === model?.base_model;
|
||||
matchingIPAdapterModel?.base_model === (newModel ?? model)?.base_model;
|
||||
|
||||
if (!isCompatibleBaseModel) {
|
||||
return {
|
||||
@ -768,7 +778,7 @@ export const useRecallParameters = () => {
|
||||
|
||||
return { ipAdapter, error: null };
|
||||
},
|
||||
[ipAdapterModels, model?.base_model]
|
||||
[ipAdapterModels, model]
|
||||
);
|
||||
|
||||
const recallIPAdapter = useCallback(
|
||||
@ -840,6 +850,13 @@ export const useRecallParameters = () => {
|
||||
t2iAdapters,
|
||||
} = metadata;
|
||||
|
||||
let newModel: ParameterModel | undefined = undefined;
|
||||
|
||||
if (isParameterModel(model)) {
|
||||
newModel = model;
|
||||
dispatch(modelSelected(model));
|
||||
}
|
||||
|
||||
if (isParameterCFGScale(cfg_scale)) {
|
||||
dispatch(setCfgScale(cfg_scale));
|
||||
}
|
||||
@ -848,10 +865,6 @@ export const useRecallParameters = () => {
|
||||
dispatch(setCfgRescaleMultiplier(cfg_rescale_multiplier));
|
||||
}
|
||||
|
||||
if (isParameterModel(model)) {
|
||||
dispatch(modelSelected(model));
|
||||
}
|
||||
|
||||
if (isParameterPositivePrompt(positive_prompt)) {
|
||||
dispatch(setPositivePrompt(positive_prompt));
|
||||
}
|
||||
@ -880,11 +893,11 @@ export const useRecallParameters = () => {
|
||||
}
|
||||
|
||||
if (isParameterWidth(width)) {
|
||||
dispatch(widthChanged(width));
|
||||
dispatch(widthRecalled(width));
|
||||
}
|
||||
|
||||
if (isParameterHeight(height)) {
|
||||
dispatch(heightChanged(height));
|
||||
dispatch(heightRecalled(height));
|
||||
}
|
||||
|
||||
if (isParameterStrength(strength)) {
|
||||
@ -953,7 +966,7 @@ export const useRecallParameters = () => {
|
||||
|
||||
dispatch(lorasCleared());
|
||||
loras?.forEach((lora) => {
|
||||
const result = prepareLoRAMetadataItem(lora);
|
||||
const result = prepareLoRAMetadataItem(lora, newModel);
|
||||
if (result.lora) {
|
||||
dispatch(loraRecalled({ ...result.lora, weight: lora.weight }));
|
||||
}
|
||||
@ -961,21 +974,21 @@ export const useRecallParameters = () => {
|
||||
|
||||
dispatch(controlAdaptersReset());
|
||||
controlnets?.forEach((controlnet) => {
|
||||
const result = prepareControlNetMetadataItem(controlnet);
|
||||
const result = prepareControlNetMetadataItem(controlnet, newModel);
|
||||
if (result.controlnet) {
|
||||
dispatch(controlAdapterRecalled(result.controlnet));
|
||||
}
|
||||
});
|
||||
|
||||
ipAdapters?.forEach((ipAdapter) => {
|
||||
const result = prepareIPAdapterMetadataItem(ipAdapter);
|
||||
const result = prepareIPAdapterMetadataItem(ipAdapter, newModel);
|
||||
if (result.ipAdapter) {
|
||||
dispatch(controlAdapterRecalled(result.ipAdapter));
|
||||
}
|
||||
});
|
||||
|
||||
t2iAdapters?.forEach((t2iAdapter) => {
|
||||
const result = prepareT2IAdapterMetadataItem(t2iAdapter);
|
||||
const result = prepareT2IAdapterMetadataItem(t2iAdapter, newModel);
|
||||
if (result.t2iAdapter) {
|
||||
dispatch(controlAdapterRecalled(result.t2iAdapter));
|
||||
}
|
||||
|
@ -175,8 +175,15 @@ export const generationSlice = createSlice({
|
||||
}
|
||||
|
||||
// Clamp ClipSkip Based On Selected Model
|
||||
const { maxClip } = CLIP_SKIP_MAP[newModel.base_model];
|
||||
state.clipSkip = clamp(state.clipSkip, 0, maxClip);
|
||||
// TODO(psyche): remove this special handling when https://github.com/invoke-ai/InvokeAI/issues/4583 is resolved
|
||||
// WIP PR here: https://github.com/invoke-ai/InvokeAI/pull/4624
|
||||
if (newModel.base_model === 'sdxl') {
|
||||
// We don't support clip skip for SDXL yet - it's not in the graphs
|
||||
state.clipSkip = 0;
|
||||
} else {
|
||||
const { maxClip } = CLIP_SKIP_MAP[newModel.base_model];
|
||||
state.clipSkip = clamp(state.clipSkip, 0, maxClip);
|
||||
}
|
||||
|
||||
if (action.meta.previousModel?.base_model === newModel.base_model) {
|
||||
// The base model hasn't changed, we don't need to optimize the size
|
||||
@ -223,6 +230,18 @@ export const generationSlice = createSlice({
|
||||
heightChanged: (state, action: PayloadAction<number>) => {
|
||||
state.height = action.payload;
|
||||
},
|
||||
widthRecalled: (state, action: PayloadAction<number>) => {
|
||||
state.width = action.payload;
|
||||
state.aspectRatio.value = action.payload / state.height;
|
||||
state.aspectRatio.id = 'Free';
|
||||
state.aspectRatio.isLocked = false;
|
||||
},
|
||||
heightRecalled: (state, action: PayloadAction<number>) => {
|
||||
state.height = action.payload;
|
||||
state.aspectRatio.value = state.width / action.payload;
|
||||
state.aspectRatio.id = 'Free';
|
||||
state.aspectRatio.isLocked = false;
|
||||
},
|
||||
aspectRatioChanged: (state, action: PayloadAction<AspectRatioState>) => {
|
||||
state.aspectRatio = action.payload;
|
||||
},
|
||||
@ -299,6 +318,8 @@ export const {
|
||||
aspectRatioChanged,
|
||||
widthChanged,
|
||||
heightChanged,
|
||||
widthRecalled,
|
||||
heightRecalled,
|
||||
} = generationSlice.actions;
|
||||
|
||||
export const { selectOptimalDimension } = generationSlice.selectors;
|
||||
|
@ -6,7 +6,6 @@ import {
|
||||
Spinner,
|
||||
Text,
|
||||
} from '@invoke-ai/ui';
|
||||
import ScrollableContent from 'common/components/OverlayScrollbars/ScrollableContent';
|
||||
import DataViewer from 'features/gallery/components/ImageMetadataViewer/DataViewer';
|
||||
import { useCancelBatch } from 'features/queue/hooks/useCancelBatch';
|
||||
import { useCancelQueueItem } from 'features/queue/hooks/useCancelQueueItem';
|
||||
@ -127,9 +126,7 @@ const QueueItemComponent = ({ queueItemDTO }: Props) => {
|
||||
justifyContent="center"
|
||||
>
|
||||
{queueItem ? (
|
||||
<ScrollableContent>
|
||||
<DataViewer label="Queue Item" data={queueItem} />
|
||||
</ScrollableContent>
|
||||
<DataViewer label="Queue Item" data={queueItem} />
|
||||
) : (
|
||||
<Spinner opacity={0.5} />
|
||||
)}
|
||||
|
@ -1,23 +1,26 @@
|
||||
import { useDisclosure } from '@invoke-ai/ui';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { expanderToggled } from 'features/settingsAccordions/store/actions';
|
||||
import { useCallback } from 'react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import { expanderStateChanged, selectUiSlice } from 'features/ui/store/uiSlice';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
type UseExpanderToggleArg = {
|
||||
defaultIsOpen: boolean;
|
||||
id?: string;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export const useExpanderToggle = (arg: UseExpanderToggleArg) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { isOpen, onToggle: _onToggle } = useDisclosure({
|
||||
defaultIsOpen: arg.defaultIsOpen,
|
||||
});
|
||||
const selectIsOpen = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
selectUiSlice,
|
||||
(ui) => ui.expanders[arg.id] ?? arg.defaultIsOpen
|
||||
),
|
||||
[arg]
|
||||
);
|
||||
const isOpen = useAppSelector(selectIsOpen);
|
||||
const onToggle = useCallback(() => {
|
||||
if (arg.id) {
|
||||
dispatch(expanderToggled({ id: arg.id, isOpen }));
|
||||
}
|
||||
_onToggle();
|
||||
}, [_onToggle, dispatch, arg.id, isOpen]);
|
||||
dispatch(expanderStateChanged({ id: arg.id, isOpen: !isOpen }));
|
||||
}, [dispatch, arg.id, isOpen]);
|
||||
return { isOpen, onToggle };
|
||||
};
|
||||
|
@ -1,25 +1,31 @@
|
||||
import { useDisclosure } from '@invoke-ai/ui';
|
||||
import { useAppDispatch } from 'app/store/storeHooks';
|
||||
import { standaloneAccordionToggled } from 'features/settingsAccordions/store/actions';
|
||||
import { useCallback } from 'react';
|
||||
import { createSelector } from '@reduxjs/toolkit';
|
||||
import { useAppDispatch, useAppSelector } from 'app/store/storeHooks';
|
||||
import {
|
||||
accordionStateChanged,
|
||||
selectUiSlice,
|
||||
} from 'features/ui/store/uiSlice';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
type UseStandaloneAccordionToggleArg = {
|
||||
defaultIsOpen: boolean;
|
||||
id?: string;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export const useStandaloneAccordionToggle = (
|
||||
arg: UseStandaloneAccordionToggleArg
|
||||
) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const { isOpen, onToggle: _onToggle } = useDisclosure({
|
||||
defaultIsOpen: arg.defaultIsOpen,
|
||||
});
|
||||
const selectIsOpen = useMemo(
|
||||
() =>
|
||||
createSelector(
|
||||
selectUiSlice,
|
||||
(ui) => ui.accordions[arg.id] ?? arg.defaultIsOpen
|
||||
),
|
||||
[arg]
|
||||
);
|
||||
const isOpen = useAppSelector(selectIsOpen);
|
||||
const onToggle = useCallback(() => {
|
||||
if (arg.id) {
|
||||
dispatch(standaloneAccordionToggled({ id: arg.id, isOpen }));
|
||||
}
|
||||
_onToggle();
|
||||
}, [_onToggle, arg.id, dispatch, isOpen]);
|
||||
dispatch(accordionStateChanged({ id: arg.id, isOpen: !isOpen }));
|
||||
}, [arg.id, dispatch, isOpen]);
|
||||
return { isOpen, onToggle };
|
||||
};
|
||||
|
@ -1,10 +0,0 @@
|
||||
import { createAction } from '@reduxjs/toolkit';
|
||||
|
||||
export const expanderToggled = createAction<{ id: string; isOpen: boolean }>(
|
||||
'parameters/expanderToggled'
|
||||
);
|
||||
|
||||
export const standaloneAccordionToggled = createAction<{
|
||||
id: string;
|
||||
isOpen: boolean;
|
||||
}>('parameters/standaloneAccordionToggled');
|
@ -1,11 +1,10 @@
|
||||
import { ExternalLinkIcon } from '@chakra-ui/icons';
|
||||
import {
|
||||
ExternalLink,
|
||||
Flex,
|
||||
Grid,
|
||||
GridItem,
|
||||
Heading,
|
||||
Image,
|
||||
Link,
|
||||
Modal,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
@ -103,23 +102,21 @@ const AboutModal = ({ children }: AboutModalProps) => {
|
||||
{appVersion && <Text>{`v${appVersion?.version}`}</Text>}
|
||||
<Grid templateColumns="repeat(2, 1fr)" gap="3">
|
||||
<GridItem>
|
||||
<Link fontSize="sm" href={githubLink} isExternal>
|
||||
{t('common.githubLabel')}
|
||||
<ExternalLinkIcon mx="2px" />
|
||||
</Link>
|
||||
<ExternalLink
|
||||
href={githubLink}
|
||||
label={t('common.githubLabel')}
|
||||
/>
|
||||
</GridItem>
|
||||
<GridItem>
|
||||
<Link fontSize="sm" href={discordLink} isExternal>
|
||||
{t('common.discordLabel')}
|
||||
<ExternalLinkIcon mx="2px" />
|
||||
</Link>
|
||||
<ExternalLink
|
||||
href={discordLink}
|
||||
label={t('common.discordLabel')}
|
||||
/>
|
||||
</GridItem>
|
||||
</Grid>
|
||||
<Heading fontSize="large">{t('common.aboutHeading')}</Heading>
|
||||
<Text fontSize="sm">{t('common.aboutDesc')}</Text>
|
||||
<Link isExternal href={websiteLink} fontSize="sm">
|
||||
{websiteLink} <ExternalLinkIcon mx="2px" />
|
||||
</Link>
|
||||
<ExternalLink href={websiteLink} label={websiteLink} />
|
||||
</Flex>
|
||||
</GridItem>
|
||||
</Grid>
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { CloseIcon } from '@chakra-ui/icons';
|
||||
import {
|
||||
Divider,
|
||||
Flex,
|
||||
@ -30,6 +29,7 @@ import {
|
||||
useState,
|
||||
} from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiXBold } from 'react-icons/pi';
|
||||
|
||||
import HotkeyListItem from './HotkeyListItem';
|
||||
|
||||
@ -103,7 +103,8 @@ const HotkeysModal = ({ children }: HotkeysModalProps) => {
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
aria-label={t('hotkeys.clearSearch')}
|
||||
icon={<CloseIcon boxSize={3} />}
|
||||
boxSize={4}
|
||||
icon={<PiXBold />}
|
||||
/>
|
||||
</InputRightElement>
|
||||
)}
|
||||
|
@ -81,6 +81,11 @@ export const useHotkeyData = (): HotkeyGroup[] => {
|
||||
() => ({
|
||||
title: t('hotkeys.generalHotkeys'),
|
||||
hotkeyListItems: [
|
||||
{
|
||||
title: t('hotkeys.remixImage.title'),
|
||||
desc: t('hotkeys.remixImage.desc'),
|
||||
hotkeys: [['R']],
|
||||
},
|
||||
{
|
||||
title: t('hotkeys.setPrompt.title'),
|
||||
desc: t('hotkeys.setPrompt.desc'),
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { SpinnerIcon } from '@chakra-ui/icons';
|
||||
import type { SystemStyleObject } from '@invoke-ai/ui';
|
||||
import {
|
||||
ButtonGroup,
|
||||
Flex,
|
||||
Icon,
|
||||
IconButton,
|
||||
Portal,
|
||||
spinAnimation,
|
||||
@ -14,7 +14,7 @@ import { useQueueBack } from 'features/queue/hooks/useQueueBack';
|
||||
import type { UsePanelReturn } from 'features/ui/hooks/usePanel';
|
||||
import { memo, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiSlidersHorizontalBold } from 'react-icons/pi';
|
||||
import { PiCircleNotchBold, PiSlidersHorizontalBold } from 'react-icons/pi';
|
||||
import { RiSparklingFill } from 'react-icons/ri';
|
||||
import { useGetQueueStatusQuery } from 'services/api/endpoints/queue';
|
||||
|
||||
@ -35,7 +35,7 @@ const FloatingSidePanelButtons = (props: Props) => {
|
||||
const queueButtonIcon = useMemo(
|
||||
() =>
|
||||
!isDisabled && queueStatus?.processor.is_processing ? (
|
||||
<SpinnerIcon animation={spinAnimation} />
|
||||
<Icon boxSize={6} as={PiCircleNotchBold} animation={spinAnimation} />
|
||||
) : (
|
||||
<RiSparklingFill size="16px" />
|
||||
),
|
||||
|
@ -10,10 +10,10 @@ export const initialUIState: UIState = {
|
||||
_version: 1,
|
||||
activeTab: 'txt2img',
|
||||
shouldShowImageDetails: false,
|
||||
shouldShowExistingModelsInSearch: false,
|
||||
shouldHidePreview: false,
|
||||
shouldShowProgressInViewer: true,
|
||||
panels: {},
|
||||
accordions: {},
|
||||
expanders: {},
|
||||
};
|
||||
|
||||
export const uiSlice = createSlice({
|
||||
@ -26,15 +26,6 @@ export const uiSlice = createSlice({
|
||||
setShouldShowImageDetails: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldShowImageDetails = action.payload;
|
||||
},
|
||||
setShouldHidePreview: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldHidePreview = action.payload;
|
||||
},
|
||||
setShouldShowExistingModelsInSearch: (
|
||||
state,
|
||||
action: PayloadAction<boolean>
|
||||
) => {
|
||||
state.shouldShowExistingModelsInSearch = action.payload;
|
||||
},
|
||||
setShouldShowProgressInViewer: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldShowProgressInViewer = action.payload;
|
||||
},
|
||||
@ -44,6 +35,20 @@ export const uiSlice = createSlice({
|
||||
) => {
|
||||
state.panels[action.payload.name] = action.payload.value;
|
||||
},
|
||||
accordionStateChanged: (
|
||||
state,
|
||||
action: PayloadAction<{ id: string; isOpen: boolean }>
|
||||
) => {
|
||||
const { id, isOpen } = action.payload;
|
||||
state.accordions[id] = isOpen;
|
||||
},
|
||||
expanderStateChanged: (
|
||||
state,
|
||||
action: PayloadAction<{ id: string; isOpen: boolean }>
|
||||
) => {
|
||||
const { id, isOpen } = action.payload;
|
||||
state.expanders[id] = isOpen;
|
||||
},
|
||||
},
|
||||
extraReducers(builder) {
|
||||
builder.addCase(initialImageChanged, (state) => {
|
||||
@ -55,10 +60,10 @@ export const uiSlice = createSlice({
|
||||
export const {
|
||||
setActiveTab,
|
||||
setShouldShowImageDetails,
|
||||
setShouldShowExistingModelsInSearch,
|
||||
setShouldHidePreview,
|
||||
setShouldShowProgressInViewer,
|
||||
panelsChanged,
|
||||
accordionStateChanged,
|
||||
expanderStateChanged,
|
||||
} = uiSlice.actions;
|
||||
|
||||
export default uiSlice.reducer;
|
||||
|
@ -1,11 +1,32 @@
|
||||
import type { InvokeTabName } from './tabMap';
|
||||
|
||||
export interface UIState {
|
||||
/**
|
||||
* Slice schema version.
|
||||
*/
|
||||
_version: 1;
|
||||
/**
|
||||
* The currently active tab.
|
||||
*/
|
||||
activeTab: InvokeTabName;
|
||||
/**
|
||||
* Whether or not to show image details, e.g. metadata, workflow, etc.
|
||||
*/
|
||||
shouldShowImageDetails: boolean;
|
||||
shouldShowExistingModelsInSearch: boolean;
|
||||
shouldHidePreview: boolean;
|
||||
/**
|
||||
* Whether or not to show progress in the viewer.
|
||||
*/
|
||||
shouldShowProgressInViewer: boolean;
|
||||
/**
|
||||
* The react-resizable-panels state. The shape is managed by react-resizable-panels.
|
||||
*/
|
||||
panels: Record<string, string>;
|
||||
/**
|
||||
* The state of accordions. The key is the id of the accordion, and the value is a boolean representing the open state.
|
||||
*/
|
||||
accordions: Record<string, boolean>;
|
||||
/**
|
||||
* The state of expanders. The key is the id of the expander, and the value is a boolean representing the open state.
|
||||
*/
|
||||
expanders: Record<string, boolean>;
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { CloseIcon } from '@chakra-ui/icons';
|
||||
import type { ComboboxOnChange, ComboboxOption } from '@invoke-ai/ui';
|
||||
import {
|
||||
Button,
|
||||
@ -14,6 +13,8 @@ import {
|
||||
InputRightElement,
|
||||
Spacer,
|
||||
} from '@invoke-ai/ui';
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { $projectId } from 'app/store/nanostores/projectId';
|
||||
import {
|
||||
IAINoContentFallback,
|
||||
IAINoContentFallbackWithSpinner,
|
||||
@ -25,6 +26,7 @@ import WorkflowLibraryPagination from 'features/workflowLibrary/components/Workf
|
||||
import type { ChangeEvent, KeyboardEvent } from 'react';
|
||||
import { memo, useCallback, useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { PiXBold } from 'react-icons/pi';
|
||||
import { useListWorkflowsQuery } from 'services/api/endpoints/workflows';
|
||||
import type {
|
||||
SQLiteDirection,
|
||||
@ -62,6 +64,7 @@ const WorkflowLibraryList = () => {
|
||||
const [order_by, setOrderBy] = useState<WorkflowRecordOrderBy>('opened_at');
|
||||
const [direction, setDirection] = useState<SQLiteDirection>('ASC');
|
||||
const [debouncedQuery] = useDebounce(query, 500);
|
||||
const projectId = useStore($projectId);
|
||||
|
||||
const queryArg = useMemo<Parameters<typeof useListWorkflowsQuery>[0]>(() => {
|
||||
if (category === 'user') {
|
||||
@ -142,13 +145,8 @@ const WorkflowLibraryList = () => {
|
||||
[]
|
||||
);
|
||||
|
||||
const handleSetUserCategory = useCallback(() => {
|
||||
setCategory('user');
|
||||
setPage(0);
|
||||
}, []);
|
||||
|
||||
const handleSetDefaultCategory = useCallback(() => {
|
||||
setCategory('default');
|
||||
const handleSetCategory = useCallback((category: WorkflowCategory) => {
|
||||
setCategory(category);
|
||||
setPage(0);
|
||||
}, []);
|
||||
|
||||
@ -158,21 +156,31 @@ const WorkflowLibraryList = () => {
|
||||
<ButtonGroup>
|
||||
<Button
|
||||
variant={category === 'user' ? undefined : 'ghost'}
|
||||
onClick={handleSetUserCategory}
|
||||
onClick={handleSetCategory.bind(null, 'user')}
|
||||
isChecked={category === 'user'}
|
||||
>
|
||||
{t('workflows.userWorkflows')}
|
||||
</Button>
|
||||
<Button
|
||||
variant={category === 'default' ? undefined : 'ghost'}
|
||||
onClick={handleSetDefaultCategory}
|
||||
isChecked={category === 'default'}
|
||||
>
|
||||
{t('workflows.defaultWorkflows')}
|
||||
</Button>
|
||||
{projectId ? (
|
||||
<Button
|
||||
variant={category === 'project' ? undefined : 'ghost'}
|
||||
onClick={handleSetCategory.bind(null, 'project')}
|
||||
isChecked={category === 'project'}
|
||||
>
|
||||
{t('workflows.projectWorkflows')}
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
variant={category === 'default' ? undefined : 'ghost'}
|
||||
onClick={handleSetCategory.bind(null, 'default')}
|
||||
isChecked={category === 'default'}
|
||||
>
|
||||
{t('workflows.defaultWorkflows')}
|
||||
</Button>
|
||||
)}
|
||||
</ButtonGroup>
|
||||
<Spacer />
|
||||
{category === 'user' && (
|
||||
{category !== 'default' && (
|
||||
<>
|
||||
<FormControl isDisabled={isFetching} w={64} minW={56}>
|
||||
<FormLabel>{t('common.orderBy')}</FormLabel>
|
||||
@ -202,14 +210,13 @@ const WorkflowLibraryList = () => {
|
||||
minW={64}
|
||||
/>
|
||||
{query.trim().length && (
|
||||
<InputRightElement>
|
||||
<InputRightElement h="full" pe={2}>
|
||||
<IconButton
|
||||
onClick={resetFilterText}
|
||||
size="xs"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
variant="link"
|
||||
aria-label={t('workflows.clearWorkflowSearchFilter')}
|
||||
opacity={0.5}
|
||||
icon={<CloseIcon boxSize={2} />}
|
||||
icon={<PiXBold />}
|
||||
/>
|
||||
</InputRightElement>
|
||||
)}
|
||||
@ -229,7 +236,7 @@ const WorkflowLibraryList = () => {
|
||||
</Flex>
|
||||
</ScrollableContent>
|
||||
) : (
|
||||
<IAINoContentFallback label={t('workflows.noUserWorkflows')} />
|
||||
<IAINoContentFallback label={t('workflows.noWorkflows')} />
|
||||
)}
|
||||
<Divider />
|
||||
{data && (
|
||||
|
@ -52,7 +52,7 @@ const WorkflowLibraryListItem = ({ workflowDTO }: Props) => {
|
||||
{workflowDTO.name || t('workflows.unnamedWorkflow')}
|
||||
</Heading>
|
||||
<Spacer />
|
||||
{workflowDTO.category === 'user' && (
|
||||
{workflowDTO.category !== 'default' && (
|
||||
<Text
|
||||
fontSize="sm"
|
||||
variant="subtext"
|
||||
@ -81,7 +81,7 @@ const WorkflowLibraryListItem = ({ workflowDTO }: Props) => {
|
||||
</Text>
|
||||
)}
|
||||
<Spacer />
|
||||
{workflowDTO.category === 'user' && (
|
||||
{workflowDTO.category !== 'default' && (
|
||||
<Text
|
||||
fontSize="sm"
|
||||
variant="subtext"
|
||||
@ -104,7 +104,7 @@ const WorkflowLibraryListItem = ({ workflowDTO }: Props) => {
|
||||
>
|
||||
{t('common.load')}
|
||||
</Button>
|
||||
{workflowDTO.category === 'user' && (
|
||||
{workflowDTO.category !== 'default' && (
|
||||
<Button
|
||||
flexShrink={0}
|
||||
colorScheme="error"
|
||||
|
File diff suppressed because one or more lines are too long
@ -164,6 +164,8 @@ export type ColorMapImageProcessorInvocation =
|
||||
s['ColorMapImageProcessorInvocation'];
|
||||
export type ContentShuffleImageProcessorInvocation =
|
||||
s['ContentShuffleImageProcessorInvocation'];
|
||||
export type DepthAnythingImageProcessorInvocation =
|
||||
s['DepthAnythingImageProcessorInvocation'];
|
||||
export type HedImageProcessorInvocation = s['HedImageProcessorInvocation'];
|
||||
export type LineartAnimeImageProcessorInvocation =
|
||||
s['LineartAnimeImageProcessorInvocation'];
|
||||
|
@ -1 +1 @@
|
||||
__version__ = "3.6.0"
|
||||
__version__ = "3.6.1"
|
||||
|
@ -33,12 +33,12 @@ classifiers = [
|
||||
]
|
||||
dependencies = [
|
||||
# Core generation dependencies, pinned for reproducible builds.
|
||||
"accelerate==0.25.0",
|
||||
"accelerate==0.26.1",
|
||||
"basicsr==1.4.2",
|
||||
"clip_anytorch==2.5.2", # replacing "clip @ https://github.com/openai/CLIP/archive/eaa22acb90a5876642d0507623e859909230a52d.zip",
|
||||
"compel==2.0.2",
|
||||
"controlnet-aux==0.0.7",
|
||||
"diffusers[torch]==0.25.0",
|
||||
"diffusers[torch]==0.25.1",
|
||||
"invisible-watermark==0.2.0", # needed to install SDXL base and refiner using their repo_ids
|
||||
"mediapipe==0.10.7", # needed for "mediapipeface" controlnet model
|
||||
"numpy==1.26.3", # >1.24.0 is needed to use the 'strict' argument to np.testing.assert_array_equal()
|
||||
@ -52,7 +52,7 @@ dependencies = [
|
||||
"torchmetrics==0.11.4",
|
||||
"torchsde==0.2.6",
|
||||
"torchvision==0.16.2",
|
||||
"transformers==4.36.2",
|
||||
"transformers==4.37.0",
|
||||
|
||||
# Core application dependencies, pinned for reproducible builds.
|
||||
"fastapi-events==0.10.0",
|
||||
|
Loading…
Reference in New Issue
Block a user