mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
Merge branch 'main' into chore/accessability_various-additions
This commit is contained in:
commit
6b41127421
1
.git-blame-ignore-revs
Normal file
1
.git-blame-ignore-revs
Normal file
@ -0,0 +1 @@
|
||||
b3dccfaeb636599c02effc377cdd8a87d658256c
|
8
.github/workflows/lint-frontend.yml
vendored
8
.github/workflows/lint-frontend.yml
vendored
@ -4,9 +4,17 @@ on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'invokeai/frontend/web/**'
|
||||
types:
|
||||
- 'ready_for_review'
|
||||
- 'opened'
|
||||
- 'synchronize'
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
paths:
|
||||
- 'invokeai/frontend/web/**'
|
||||
merge_group:
|
||||
workflow_dispatch:
|
||||
|
||||
defaults:
|
||||
run:
|
||||
|
2
.github/workflows/test-invoke-pip-skip.yml
vendored
2
.github/workflows/test-invoke-pip-skip.yml
vendored
@ -6,7 +6,7 @@ on:
|
||||
- 'invokeai/**'
|
||||
- 'invokeai/backend/**'
|
||||
- 'invokeai/configs/**'
|
||||
- 'invokeai/frontend/dist/**'
|
||||
- 'invokeai/frontend/web/dist/**'
|
||||
merge_group:
|
||||
workflow_dispatch:
|
||||
|
||||
|
4
.github/workflows/test-invoke-pip.yml
vendored
4
.github/workflows/test-invoke-pip.yml
vendored
@ -8,14 +8,14 @@ on:
|
||||
- 'invokeai/**'
|
||||
- 'invokeai/backend/**'
|
||||
- 'invokeai/configs/**'
|
||||
- 'invokeai/frontend/dist/**'
|
||||
- 'invokeai/frontend/web/dist/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'pyproject.toml'
|
||||
- 'invokeai/**'
|
||||
- 'invokeai/backend/**'
|
||||
- 'invokeai/configs/**'
|
||||
- 'invokeai/frontend/dist/**'
|
||||
- 'invokeai/frontend/web/dist/**'
|
||||
types:
|
||||
- 'ready_for_review'
|
||||
- 'opened'
|
||||
|
0
invokeai/app/cli/__init__.py
Normal file
0
invokeai/app/cli/__init__.py
Normal file
202
invokeai/app/cli/commands.py
Normal file
202
invokeai/app/cli/commands.py
Normal file
@ -0,0 +1,202 @@
|
||||
# Copyright (c) 2023 Kyle Schouviller (https://github.com/kyle0654)
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
import argparse
|
||||
from typing import Any, Callable, Iterable, Literal, get_args, get_origin, get_type_hints
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from ..invocations.image import ImageField
|
||||
from ..services.graph import GraphExecutionState
|
||||
from ..services.invoker import Invoker
|
||||
|
||||
|
||||
def add_parsers(
|
||||
subparsers,
|
||||
commands: list[type],
|
||||
command_field: str = "type",
|
||||
exclude_fields: list[str] = ["id", "type"],
|
||||
add_arguments: Callable[[argparse.ArgumentParser], None]|None = None
|
||||
):
|
||||
"""Adds parsers for each command to the subparsers"""
|
||||
|
||||
# Create subparsers for each command
|
||||
for command in commands:
|
||||
hints = get_type_hints(command)
|
||||
cmd_name = get_args(hints[command_field])[0]
|
||||
command_parser = subparsers.add_parser(cmd_name, help=command.__doc__)
|
||||
|
||||
if add_arguments is not None:
|
||||
add_arguments(command_parser)
|
||||
|
||||
# Convert all fields to arguments
|
||||
fields = command.__fields__ # type: ignore
|
||||
for name, field in fields.items():
|
||||
if name in exclude_fields:
|
||||
continue
|
||||
|
||||
if get_origin(field.type_) == Literal:
|
||||
allowed_values = get_args(field.type_)
|
||||
allowed_types = set()
|
||||
for val in allowed_values:
|
||||
allowed_types.add(type(val))
|
||||
allowed_types_list = list(allowed_types)
|
||||
field_type = allowed_types_list[0] if len(allowed_types) == 1 else Union[allowed_types_list] # type: ignore
|
||||
|
||||
command_parser.add_argument(
|
||||
f"--{name}",
|
||||
dest=name,
|
||||
type=field_type,
|
||||
default=field.default,
|
||||
choices=allowed_values,
|
||||
help=field.field_info.description,
|
||||
)
|
||||
else:
|
||||
command_parser.add_argument(
|
||||
f"--{name}",
|
||||
dest=name,
|
||||
type=field.type_,
|
||||
default=field.default,
|
||||
help=field.field_info.description,
|
||||
)
|
||||
|
||||
|
||||
class CliContext:
|
||||
invoker: Invoker
|
||||
session: GraphExecutionState
|
||||
parser: argparse.ArgumentParser
|
||||
defaults: dict[str, Any]
|
||||
|
||||
def __init__(self, invoker: Invoker, session: GraphExecutionState, parser: argparse.ArgumentParser):
|
||||
self.invoker = invoker
|
||||
self.session = session
|
||||
self.parser = parser
|
||||
self.defaults = dict()
|
||||
|
||||
def get_session(self):
|
||||
self.session = self.invoker.services.graph_execution_manager.get(self.session.id)
|
||||
return self.session
|
||||
|
||||
|
||||
class ExitCli(Exception):
|
||||
"""Exception to exit the CLI"""
|
||||
pass
|
||||
|
||||
|
||||
class BaseCommand(ABC, BaseModel):
|
||||
"""A CLI command"""
|
||||
|
||||
# All commands must include a type name like this:
|
||||
# type: Literal['your_command_name'] = 'your_command_name'
|
||||
|
||||
@classmethod
|
||||
def get_all_subclasses(cls):
|
||||
subclasses = []
|
||||
toprocess = [cls]
|
||||
while len(toprocess) > 0:
|
||||
next = toprocess.pop(0)
|
||||
next_subclasses = next.__subclasses__()
|
||||
subclasses.extend(next_subclasses)
|
||||
toprocess.extend(next_subclasses)
|
||||
return subclasses
|
||||
|
||||
@classmethod
|
||||
def get_commands(cls):
|
||||
return tuple(BaseCommand.get_all_subclasses())
|
||||
|
||||
@classmethod
|
||||
def get_commands_map(cls):
|
||||
# Get the type strings out of the literals and into a dictionary
|
||||
return dict(map(lambda t: (get_args(get_type_hints(t)['type'])[0], t),BaseCommand.get_all_subclasses()))
|
||||
|
||||
@abstractmethod
|
||||
def run(self, context: CliContext) -> None:
|
||||
"""Run the command. Raise ExitCli to exit."""
|
||||
pass
|
||||
|
||||
|
||||
class ExitCommand(BaseCommand):
|
||||
"""Exits the CLI"""
|
||||
type: Literal['exit'] = 'exit'
|
||||
|
||||
def run(self, context: CliContext) -> None:
|
||||
raise ExitCli()
|
||||
|
||||
|
||||
class HelpCommand(BaseCommand):
|
||||
"""Shows help"""
|
||||
type: Literal['help'] = 'help'
|
||||
|
||||
def run(self, context: CliContext) -> None:
|
||||
context.parser.print_help()
|
||||
|
||||
|
||||
def get_graph_execution_history(
|
||||
graph_execution_state: GraphExecutionState,
|
||||
) -> Iterable[str]:
|
||||
"""Gets the history of fully-executed invocations for a graph execution"""
|
||||
return (
|
||||
n
|
||||
for n in reversed(graph_execution_state.executed_history)
|
||||
if n in graph_execution_state.graph.nodes
|
||||
)
|
||||
|
||||
|
||||
def get_invocation_command(invocation) -> str:
|
||||
fields = invocation.__fields__.items()
|
||||
type_hints = get_type_hints(type(invocation))
|
||||
command = [invocation.type]
|
||||
for name, field in fields:
|
||||
if name in ["id", "type"]:
|
||||
continue
|
||||
|
||||
# TODO: add links
|
||||
|
||||
# Skip image fields when serializing command
|
||||
type_hint = type_hints.get(name) or None
|
||||
if type_hint is ImageField or ImageField in get_args(type_hint):
|
||||
continue
|
||||
|
||||
field_value = getattr(invocation, name)
|
||||
field_default = field.default
|
||||
if field_value != field_default:
|
||||
if type_hint is str or str in get_args(type_hint):
|
||||
command.append(f'--{name} "{field_value}"')
|
||||
else:
|
||||
command.append(f"--{name} {field_value}")
|
||||
|
||||
return " ".join(command)
|
||||
|
||||
|
||||
class HistoryCommand(BaseCommand):
|
||||
"""Shows the invocation history"""
|
||||
type: Literal['history'] = 'history'
|
||||
|
||||
# Inputs
|
||||
# fmt: off
|
||||
count: int = Field(default=5, gt=0, description="The number of history entries to show")
|
||||
# fmt: on
|
||||
|
||||
def run(self, context: CliContext) -> None:
|
||||
history = list(get_graph_execution_history(context.get_session()))
|
||||
for i in range(min(self.count, len(history))):
|
||||
entry_id = history[-1 - i]
|
||||
entry = context.get_session().graph.get_node(entry_id)
|
||||
print(f"{entry_id}: {get_invocation_command(entry)}")
|
||||
|
||||
|
||||
class SetDefaultCommand(BaseCommand):
|
||||
"""Sets a default value for a field"""
|
||||
type: Literal['default'] = 'default'
|
||||
|
||||
# Inputs
|
||||
# fmt: off
|
||||
field: str = Field(description="The field to set the default for")
|
||||
value: str = Field(description="The value to set the default to, or None to clear the default")
|
||||
# fmt: on
|
||||
|
||||
def run(self, context: CliContext) -> None:
|
||||
if self.value is None:
|
||||
if self.field in context.defaults:
|
||||
del context.defaults[self.field]
|
||||
else:
|
||||
context.defaults[self.field] = self.value
|
@ -5,13 +5,7 @@ import os
|
||||
import shlex
|
||||
import time
|
||||
from typing import (
|
||||
Any,
|
||||
Dict,
|
||||
Iterable,
|
||||
Literal,
|
||||
Union,
|
||||
get_args,
|
||||
get_origin,
|
||||
get_type_hints,
|
||||
)
|
||||
|
||||
@ -19,9 +13,9 @@ from pydantic import BaseModel
|
||||
from pydantic.fields import Field
|
||||
|
||||
from ..backend import Args
|
||||
from .cli.commands import BaseCommand, CliContext, ExitCli, add_parsers, get_graph_execution_history
|
||||
from .invocations import *
|
||||
from .invocations.baseinvocation import BaseInvocation
|
||||
from .invocations.image import ImageField
|
||||
from .services.events import EventServiceBase
|
||||
from .services.generate_initializer import get_generate
|
||||
from .services.graph import EdgeConnection, GraphExecutionState
|
||||
@ -33,15 +27,33 @@ from .services.processor import DefaultInvocationProcessor
|
||||
from .services.sqlite import SqliteItemStorage
|
||||
|
||||
|
||||
class InvocationCommand(BaseModel):
|
||||
invocation: Union[BaseInvocation.get_invocations()] = Field(discriminator="type") # type: ignore
|
||||
class CliCommand(BaseModel):
|
||||
command: Union[BaseCommand.get_commands() + BaseInvocation.get_invocations()] = Field(discriminator="type") # type: ignore
|
||||
|
||||
|
||||
class InvalidArgs(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def get_invocation_parser() -> argparse.ArgumentParser:
|
||||
def add_invocation_args(command_parser):
|
||||
# Add linking capability
|
||||
command_parser.add_argument(
|
||||
"--link",
|
||||
"-l",
|
||||
action="append",
|
||||
nargs=3,
|
||||
help="A link in the format 'dest_field source_node source_field'. source_node can be relative to history (e.g. -1)",
|
||||
)
|
||||
|
||||
command_parser.add_argument(
|
||||
"--link_node",
|
||||
"-ln",
|
||||
action="append",
|
||||
help="A link from all fields in the specified node. Node can be relative to history (e.g. -1)",
|
||||
)
|
||||
|
||||
|
||||
def get_command_parser() -> argparse.ArgumentParser:
|
||||
# Create invocation parser
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
@ -49,129 +61,19 @@ def get_invocation_parser() -> argparse.ArgumentParser:
|
||||
raise InvalidArgs
|
||||
|
||||
parser.exit = exit
|
||||
|
||||
subparsers = parser.add_subparsers(dest="type")
|
||||
invocation_parsers = dict()
|
||||
|
||||
# Add history parser
|
||||
history_parser = subparsers.add_parser(
|
||||
"history", help="Shows the invocation history"
|
||||
)
|
||||
history_parser.add_argument(
|
||||
"count",
|
||||
nargs="?",
|
||||
default=5,
|
||||
type=int,
|
||||
help="The number of history entries to show",
|
||||
)
|
||||
|
||||
# Add default parser
|
||||
default_parser = subparsers.add_parser(
|
||||
"default", help="Define a default value for all inputs with a specified name"
|
||||
)
|
||||
default_parser.add_argument("input", type=str, help="The input field")
|
||||
default_parser.add_argument("value", help="The default value")
|
||||
|
||||
default_parser = subparsers.add_parser(
|
||||
"reset_default", help="Resets a default value"
|
||||
)
|
||||
default_parser.add_argument("input", type=str, help="The input field")
|
||||
|
||||
# Create subparsers for each invocation
|
||||
invocations = BaseInvocation.get_all_subclasses()
|
||||
for invocation in invocations:
|
||||
hints = get_type_hints(invocation)
|
||||
cmd_name = get_args(hints["type"])[0]
|
||||
command_parser = subparsers.add_parser(cmd_name, help=invocation.__doc__)
|
||||
invocation_parsers[cmd_name] = command_parser
|
||||
add_parsers(subparsers, invocations, add_arguments=add_invocation_args)
|
||||
|
||||
# Add linking capability
|
||||
command_parser.add_argument(
|
||||
"--link",
|
||||
"-l",
|
||||
action="append",
|
||||
nargs=3,
|
||||
help="A link in the format 'dest_field source_node source_field'. source_node can be relative to history (e.g. -1)",
|
||||
)
|
||||
|
||||
command_parser.add_argument(
|
||||
"--link_node",
|
||||
"-ln",
|
||||
action="append",
|
||||
help="A link from all fields in the specified node. Node can be relative to history (e.g. -1)",
|
||||
)
|
||||
|
||||
# Convert all fields to arguments
|
||||
fields = invocation.__fields__
|
||||
for name, field in fields.items():
|
||||
if name in ["id", "type"]:
|
||||
continue
|
||||
|
||||
if get_origin(field.type_) == Literal:
|
||||
allowed_values = get_args(field.type_)
|
||||
allowed_types = set()
|
||||
for val in allowed_values:
|
||||
allowed_types.add(type(val))
|
||||
allowed_types_list = list(allowed_types)
|
||||
field_type = allowed_types_list[0] if len(allowed_types) == 1 else Union[allowed_types_list] # type: ignore
|
||||
|
||||
command_parser.add_argument(
|
||||
f"--{name}",
|
||||
dest=name,
|
||||
type=field_type,
|
||||
default=field.default,
|
||||
choices=allowed_values,
|
||||
help=field.field_info.description,
|
||||
)
|
||||
else:
|
||||
command_parser.add_argument(
|
||||
f"--{name}",
|
||||
dest=name,
|
||||
type=field.type_,
|
||||
default=field.default,
|
||||
help=field.field_info.description,
|
||||
)
|
||||
# Create subparsers for each command
|
||||
commands = BaseCommand.get_all_subclasses()
|
||||
add_parsers(subparsers, commands, exclude_fields=["type"])
|
||||
|
||||
return parser
|
||||
|
||||
|
||||
def get_invocation_command(invocation) -> str:
|
||||
fields = invocation.__fields__.items()
|
||||
type_hints = get_type_hints(type(invocation))
|
||||
command = [invocation.type]
|
||||
for name, field in fields:
|
||||
if name in ["id", "type"]:
|
||||
continue
|
||||
|
||||
# TODO: add links
|
||||
|
||||
# Skip image fields when serializing command
|
||||
type_hint = type_hints.get(name) or None
|
||||
if type_hint is ImageField or ImageField in get_args(type_hint):
|
||||
continue
|
||||
|
||||
field_value = getattr(invocation, name)
|
||||
field_default = field.default
|
||||
if field_value != field_default:
|
||||
if type_hint is str or str in get_args(type_hint):
|
||||
command.append(f'--{name} "{field_value}"')
|
||||
else:
|
||||
command.append(f"--{name} {field_value}")
|
||||
|
||||
return " ".join(command)
|
||||
|
||||
|
||||
def get_graph_execution_history(
|
||||
graph_execution_state: GraphExecutionState,
|
||||
) -> Iterable[str]:
|
||||
"""Gets the history of fully-executed invocations for a graph execution"""
|
||||
return (
|
||||
n
|
||||
for n in reversed(graph_execution_state.executed_history)
|
||||
if n in graph_execution_state.graph.nodes
|
||||
)
|
||||
|
||||
|
||||
def generate_matching_edges(
|
||||
a: BaseInvocation, b: BaseInvocation
|
||||
) -> list[tuple[EdgeConnection, EdgeConnection]]:
|
||||
@ -233,13 +135,12 @@ def invoke_cli():
|
||||
invoker = Invoker(services)
|
||||
session: GraphExecutionState = invoker.create_execution_state()
|
||||
|
||||
parser = get_invocation_parser()
|
||||
parser = get_command_parser()
|
||||
|
||||
# Uncomment to print out previous sessions at startup
|
||||
# print(services.session_manager.list())
|
||||
|
||||
# Defaults storage
|
||||
defaults: Dict[str, Any] = dict()
|
||||
context = CliContext(invoker, session, parser)
|
||||
|
||||
while True:
|
||||
try:
|
||||
@ -248,13 +149,6 @@ def invoke_cli():
|
||||
# Ctrl-c exits
|
||||
break
|
||||
|
||||
if cmd_input in ["exit", "q"]:
|
||||
break
|
||||
|
||||
if cmd_input in ["--help", "help", "h", "?"]:
|
||||
parser.print_help()
|
||||
continue
|
||||
|
||||
try:
|
||||
# Refresh the state of the session
|
||||
session = invoker.services.graph_execution_manager.get(session.id)
|
||||
@ -272,35 +166,23 @@ def invoke_cli():
|
||||
# Parse args to create invocation
|
||||
args = vars(parser.parse_args(shlex.split(cmd.strip())))
|
||||
|
||||
# Check for special commands
|
||||
# TODO: These might be better as Pydantic models, similar to the invocations
|
||||
if args["type"] == "history":
|
||||
history_count = args["count"] or 5
|
||||
for i in range(min(history_count, len(history))):
|
||||
entry_id = history[-1 - i]
|
||||
entry = session.graph.get_node(entry_id)
|
||||
print(f"{entry_id}: {get_invocation_command(entry.invocation)}")
|
||||
continue
|
||||
|
||||
if args["type"] == "reset_default":
|
||||
if args["input"] in defaults:
|
||||
del defaults[args["input"]]
|
||||
continue
|
||||
|
||||
if args["type"] == "default":
|
||||
field = args["input"]
|
||||
field_value = args["value"]
|
||||
defaults[field] = field_value
|
||||
continue
|
||||
|
||||
# Override defaults
|
||||
for field_name, field_default in defaults.items():
|
||||
for field_name, field_default in context.defaults.items():
|
||||
if field_name in args:
|
||||
args[field_name] = field_default
|
||||
|
||||
# Parse invocation
|
||||
args["id"] = current_id
|
||||
command = InvocationCommand(invocation=args)
|
||||
command = CliCommand(command=args)
|
||||
|
||||
# Run any CLI commands immediately
|
||||
# TODO: this won't behave as expected if piping and using e.g. history,
|
||||
# since invocations are gathered and then run together at the end.
|
||||
# This is more efficient if the CLI is running against a distributed
|
||||
# backend, so it's preferable not to change that behavior.
|
||||
if isinstance(command.command, BaseCommand):
|
||||
command.command.run(context)
|
||||
continue
|
||||
|
||||
# Pipe previous command output (if there was a previous command)
|
||||
edges = []
|
||||
@ -314,7 +196,7 @@ def invoke_cli():
|
||||
else session.graph.get_node(from_id)
|
||||
)
|
||||
matching_edges = generate_matching_edges(
|
||||
from_node, command.invocation
|
||||
from_node, command.command
|
||||
)
|
||||
edges.extend(matching_edges)
|
||||
|
||||
@ -323,22 +205,25 @@ def invoke_cli():
|
||||
for link in args["link_node"]:
|
||||
link_node = session.graph.get_node(link)
|
||||
matching_edges = generate_matching_edges(
|
||||
link_node, command.invocation
|
||||
link_node, command.command
|
||||
)
|
||||
matching_destinations = [e[1] for e in matching_edges]
|
||||
edges = [e for e in edges if e[1] not in matching_destinations]
|
||||
edges.extend(matching_edges)
|
||||
|
||||
if "link" in args and args["link"]:
|
||||
for link in args["link"]:
|
||||
edges = [e for e in edges if e[1].node_id != command.command.id and e[1].field != link[2]]
|
||||
edges.append(
|
||||
(
|
||||
EdgeConnection(node_id=link[1], field=link[0]),
|
||||
EdgeConnection(
|
||||
node_id=command.invocation.id, field=link[2]
|
||||
node_id=command.command.id, field=link[2]
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
new_invocations.append((command.invocation, edges))
|
||||
new_invocations.append((command.command, edges))
|
||||
|
||||
current_id = current_id + 1
|
||||
|
||||
@ -347,13 +232,14 @@ def invoke_cli():
|
||||
for invocation in new_invocations:
|
||||
session.add_node(invocation[0])
|
||||
for edge in invocation[1]:
|
||||
print(edge)
|
||||
session.add_edge(edge)
|
||||
|
||||
# Execute all available invocations
|
||||
invoker.invoke(session, invoke_all=True)
|
||||
while not session.is_complete():
|
||||
# Wait some time
|
||||
session = invoker.services.graph_execution_manager.get(session.id)
|
||||
session = context.get_session()
|
||||
time.sleep(0.1)
|
||||
|
||||
# Print any errors
|
||||
@ -366,11 +252,15 @@ def invoke_cli():
|
||||
# Start a new session
|
||||
print("Creating a new session")
|
||||
session = invoker.create_execution_state()
|
||||
context.session = session
|
||||
|
||||
except InvalidArgs:
|
||||
print('Invalid command, use "help" to list commands')
|
||||
continue
|
||||
|
||||
except ExitCli:
|
||||
break
|
||||
|
||||
except SystemExit:
|
||||
continue
|
||||
|
||||
|
@ -295,7 +295,7 @@ def download_vaes():
|
||||
# first the diffusers version
|
||||
repo_id = "stabilityai/sd-vae-ft-mse"
|
||||
args = dict(
|
||||
cache_dir=global_cache_dir("diffusers"),
|
||||
cache_dir=global_cache_dir("hub"),
|
||||
)
|
||||
if not AutoencoderKL.from_pretrained(repo_id, **args):
|
||||
raise Exception(f"download of {repo_id} failed")
|
||||
|
@ -270,7 +270,6 @@ def _download_diffusion_weights(
|
||||
path = download_from_hf(
|
||||
model_class,
|
||||
repo_id,
|
||||
cache_subdir="diffusers",
|
||||
safety_checker=None,
|
||||
**extra_args,
|
||||
)
|
||||
|
@ -98,16 +98,13 @@ def global_cache_dir(subdir: Union[str, Path] = "") -> Path:
|
||||
"""
|
||||
Returns Path to the model cache directory. If a subdirectory
|
||||
is provided, it will be appended to the end of the path, allowing
|
||||
for huggingface-style conventions:
|
||||
global_cache_dir('diffusers')
|
||||
for Hugging Face-style conventions. Currently, Hugging Face has
|
||||
moved all models into the "hub" subfolder, so for any pretrained
|
||||
HF model, use:
|
||||
global_cache_dir('hub')
|
||||
Current HuggingFace documentation (mid-Jan 2023) indicates that
|
||||
transformers models will be cached into a "transformers" subdirectory,
|
||||
but in practice they seem to go into "hub". But if needed:
|
||||
global_cache_dir('transformers')
|
||||
One other caveat is that HuggingFace is moving some diffusers models
|
||||
into the "hub" subdirectory as well, so this will need to be revisited
|
||||
from time to time.
|
||||
|
||||
The legacy location for transformers used to be global_cache_dir('transformers')
|
||||
and global_cache_dir('diffusers') for diffusers.
|
||||
"""
|
||||
home: str = os.getenv("HF_HOME")
|
||||
|
||||
@ -115,7 +112,7 @@ def global_cache_dir(subdir: Union[str, Path] = "") -> Path:
|
||||
home = os.getenv("XDG_CACHE_HOME")
|
||||
|
||||
if home is not None:
|
||||
# Set `home` to $XDG_CACHE_HOME/huggingface, which is the default location mentioned in HuggingFace Hub Client Library.
|
||||
# Set `home` to $XDG_CACHE_HOME/huggingface, which is the default location mentioned in Hugging Face Hub Client Library.
|
||||
# See: https://huggingface.co/docs/huggingface_hub/main/en/package_reference/environment_variables#xdgcachehome
|
||||
home += os.sep + "huggingface"
|
||||
|
||||
|
@ -6,5 +6,4 @@ from .convert_ckpt_to_diffusers import (
|
||||
load_pipeline_from_original_stable_diffusion_ckpt,
|
||||
)
|
||||
from .model_manager import ModelManager
|
||||
from invokeai.frontend.merge import merge_diffusion_models
|
||||
|
||||
|
@ -1101,14 +1101,17 @@ def load_pipeline_from_original_stable_diffusion_ckpt(
|
||||
if original_config_file is None:
|
||||
model_type = ModelManager.probe_model_type(checkpoint)
|
||||
|
||||
if model_type == SDLegacyType.V2:
|
||||
if model_type == SDLegacyType.V2_v:
|
||||
original_config_file = (
|
||||
global_config_dir() / "stable-diffusion" / "v2-inference-v.yaml"
|
||||
)
|
||||
if global_step == 110000:
|
||||
# v2.1 needs to upcast attention
|
||||
upcast_attention = True
|
||||
|
||||
elif model_type == SDLegacyType.V2_e:
|
||||
original_config_file = (
|
||||
global_config_dir() / "stable-diffusion" / "v2-inference.yaml"
|
||||
)
|
||||
elif model_type == SDLegacyType.V1_INPAINT:
|
||||
original_config_file = (
|
||||
global_config_dir()
|
||||
|
@ -40,16 +40,16 @@ from ..util import CPU_DEVICE, ask_user, download_with_resume
|
||||
class SDLegacyType(Enum):
|
||||
V1 = 1
|
||||
V1_INPAINT = 2
|
||||
V2 = 3
|
||||
V2 = 3
|
||||
V2_e = 4
|
||||
V2_v = 5
|
||||
UNKNOWN = 99
|
||||
|
||||
|
||||
DEFAULT_MAX_MODELS = 2
|
||||
VAE_TO_REPO_ID = { # hack, see note in convert_and_import()
|
||||
"vae-ft-mse-840000-ema-pruned": "stabilityai/sd-vae-ft-mse",
|
||||
}
|
||||
|
||||
|
||||
class ModelManager(object):
|
||||
def __init__(
|
||||
self,
|
||||
@ -335,10 +335,23 @@ class ModelManager(object):
|
||||
|
||||
tic = time.time()
|
||||
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
model, width, height, model_hash = self._load_diffusers_model(mconfig)
|
||||
|
||||
# this does the work
|
||||
model_format = mconfig.get("format", "ckpt")
|
||||
if model_format == "ckpt":
|
||||
weights = mconfig.weights
|
||||
print(f">> Loading {model_name} from {weights}")
|
||||
model, width, height, model_hash = self._load_ckpt_model(
|
||||
model_name, mconfig
|
||||
)
|
||||
elif model_format == "diffusers":
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
model, width, height, model_hash = self._load_diffusers_model(mconfig)
|
||||
else:
|
||||
raise NotImplementedError(
|
||||
f"Unknown model format {model_name}: {model_format}"
|
||||
)
|
||||
|
||||
# usage statistics
|
||||
toc = time.time()
|
||||
print(">> Model loaded in", "%4.2fs" % (toc - tic))
|
||||
@ -369,7 +382,7 @@ class ModelManager(object):
|
||||
if vae := self._load_vae(mconfig["vae"]):
|
||||
pipeline_args.update(vae=vae)
|
||||
if not isinstance(name_or_path, Path):
|
||||
pipeline_args.update(cache_dir=global_cache_dir("diffusers"))
|
||||
pipeline_args.update(cache_dir=global_cache_dir("hub"))
|
||||
if using_fp16:
|
||||
pipeline_args.update(torch_dtype=torch.float16)
|
||||
fp_args_list = [{"revision": "fp16"}, {}]
|
||||
@ -527,7 +540,7 @@ class ModelManager(object):
|
||||
self,
|
||||
repo_or_path: Union[str, Path],
|
||||
model_name: str = None,
|
||||
model_description: str = None,
|
||||
description: str = None,
|
||||
vae: dict = None,
|
||||
commit_to_conf: Path = None,
|
||||
) -> bool:
|
||||
@ -569,15 +582,24 @@ class ModelManager(object):
|
||||
format. Valid return values include:
|
||||
SDLegacyType.V1
|
||||
SDLegacyType.V1_INPAINT
|
||||
SDLegacyType.V2
|
||||
SDLegacyType.V2 (V2 prediction type unknown)
|
||||
SDLegacyType.V2_e (V2 using 'epsilon' prediction type)
|
||||
SDLegacyType.V2_v (V2 using 'v_prediction' prediction type)
|
||||
SDLegacyType.UNKNOWN
|
||||
"""
|
||||
key_name = "model.diffusion_model.input_blocks.2.1.transformer_blocks.0.attn2.to_k.weight"
|
||||
if key_name in checkpoint and checkpoint[key_name].shape[-1] == 1024:
|
||||
return SDLegacyType.V2
|
||||
global_step = checkpoint.get('global_step')
|
||||
state_dict = checkpoint.get("state_dict") or checkpoint
|
||||
|
||||
try:
|
||||
state_dict = checkpoint.get("state_dict") or checkpoint
|
||||
key_name = "model.diffusion_model.input_blocks.2.1.transformer_blocks.0.attn2.to_k.weight"
|
||||
if key_name in state_dict and state_dict[key_name].shape[-1] == 1024:
|
||||
if global_step == 220000:
|
||||
return SDLegacyType.V2_e
|
||||
elif global_step == 110000:
|
||||
return SDLegacyType.V2_v
|
||||
else:
|
||||
return SDLegacyType.V2
|
||||
# otherwise we assume a V1 file
|
||||
in_channels = state_dict[
|
||||
"model.diffusion_model.input_blocks.0.0.weight"
|
||||
].shape[1]
|
||||
@ -591,12 +613,13 @@ class ModelManager(object):
|
||||
return SDLegacyType.UNKNOWN
|
||||
|
||||
def heuristic_import(
|
||||
self,
|
||||
path_url_or_repo: str,
|
||||
convert: bool = True,
|
||||
model_name: str = None,
|
||||
description: str = None,
|
||||
commit_to_conf: Path = None,
|
||||
self,
|
||||
path_url_or_repo: str,
|
||||
convert: bool = True,
|
||||
model_name: str = None,
|
||||
description: str = None,
|
||||
model_config_file: Path = None,
|
||||
commit_to_conf: Path = None,
|
||||
) -> str:
|
||||
"""
|
||||
Accept a string which could be:
|
||||
@ -693,7 +716,7 @@ class ModelManager(object):
|
||||
|
||||
if model_path.stem in self.config: # already imported
|
||||
print(" | Already imported. Skipping")
|
||||
return
|
||||
return model_path.stem
|
||||
|
||||
# another round of heuristics to guess the correct config file.
|
||||
checkpoint = (
|
||||
@ -701,32 +724,46 @@ class ModelManager(object):
|
||||
if model_path.suffix == ".safetensors"
|
||||
else torch.load(model_path)
|
||||
)
|
||||
model_type = self.probe_model_type(checkpoint)
|
||||
|
||||
model_config_file = None
|
||||
if model_type == SDLegacyType.V1:
|
||||
print(" | SD-v1 model detected")
|
||||
model_config_file = Path(
|
||||
Globals.root, "configs/stable-diffusion/v1-inference.yaml"
|
||||
)
|
||||
elif model_type == SDLegacyType.V1_INPAINT:
|
||||
print(" | SD-v1 inpainting model detected")
|
||||
model_config_file = Path(
|
||||
Globals.root, "configs/stable-diffusion/v1-inpainting-inference.yaml"
|
||||
)
|
||||
elif model_type == SDLegacyType.V2:
|
||||
print(
|
||||
" | SD-v2 model detected; model will be converted to diffusers format"
|
||||
)
|
||||
model_config_file = Path(
|
||||
Globals.root, "configs/stable-diffusion/v2-inference-v.yaml"
|
||||
)
|
||||
convert = True
|
||||
else:
|
||||
print(
|
||||
f"** {thing} is a legacy checkpoint file but not in a known Stable Diffusion model. Skipping import"
|
||||
)
|
||||
return
|
||||
# additional probing needed if no config file provided
|
||||
if model_config_file is None:
|
||||
model_type = self.probe_model_type(checkpoint)
|
||||
if model_type == SDLegacyType.V1:
|
||||
print(" | SD-v1 model detected")
|
||||
model_config_file = Path(
|
||||
Globals.root, "configs/stable-diffusion/v1-inference.yaml"
|
||||
)
|
||||
elif model_type == SDLegacyType.V1_INPAINT:
|
||||
print(" | SD-v1 inpainting model detected")
|
||||
model_config_file = Path(
|
||||
Globals.root, "configs/stable-diffusion/v1-inpainting-inference.yaml"
|
||||
)
|
||||
elif model_type == SDLegacyType.V2_v:
|
||||
print(
|
||||
" | SD-v2-v model detected; model will be converted to diffusers format"
|
||||
)
|
||||
model_config_file = Path(
|
||||
Globals.root, "configs/stable-diffusion/v2-inference-v.yaml"
|
||||
)
|
||||
convert = True
|
||||
elif model_type == SDLegacyType.V2_e:
|
||||
print(
|
||||
" | SD-v2-e model detected; model will be converted to diffusers format"
|
||||
)
|
||||
model_config_file = Path(
|
||||
Globals.root, "configs/stable-diffusion/v2-inference.yaml"
|
||||
)
|
||||
convert = True
|
||||
elif model_type == SDLegacyType.V2:
|
||||
print(
|
||||
f"** {thing} is a V2 checkpoint file, but its parameterization cannot be determined. Please provide configuration file path."
|
||||
)
|
||||
return
|
||||
else:
|
||||
print(
|
||||
f"** {thing} is a legacy checkpoint file but not a known Stable Diffusion model. Please provide configuration file path."
|
||||
)
|
||||
return
|
||||
|
||||
diffuser_path = Path(
|
||||
Globals.root, "models", Globals.converted_ckpts_dir, model_path.stem
|
||||
@ -916,27 +953,40 @@ class ModelManager(object):
|
||||
to the 2.3.0 "diffusers" version. This should be a one-time operation, called at
|
||||
script startup time.
|
||||
"""
|
||||
# Three transformer models to check: bert, clip and safety checker
|
||||
# Three transformer models to check: bert, clip and safety checker, and
|
||||
# the diffusers as well
|
||||
models_dir = Path(Globals.root, "models")
|
||||
legacy_locations = [
|
||||
Path(
|
||||
models_dir,
|
||||
"CompVis/stable-diffusion-safety-checker/models--CompVis--stable-diffusion-safety-checker"
|
||||
),
|
||||
Path("bert-base-uncased/models--bert-base-uncased"),
|
||||
Path(models_dir, "bert-base-uncased/models--bert-base-uncased"),
|
||||
Path(
|
||||
models_dir,
|
||||
"openai/clip-vit-large-patch14/models--openai--clip-vit-large-patch14"
|
||||
),
|
||||
]
|
||||
models_dir = Path(Globals.root, "models")
|
||||
legacy_locations.extend(list(global_cache_dir("diffusers").glob('*')))
|
||||
|
||||
legacy_layout = False
|
||||
for model in legacy_locations:
|
||||
legacy_layout = legacy_layout or Path(models_dir, model).exists()
|
||||
legacy_layout = legacy_layout or model.exists()
|
||||
if not legacy_layout:
|
||||
return
|
||||
|
||||
print(
|
||||
"** Legacy version <= 2.2.5 model directory layout detected. Reorganizing."
|
||||
"""
|
||||
>> ALERT:
|
||||
>> The location of your previously-installed diffusers models needs to move from
|
||||
>> invokeai/models/diffusers to invokeai/models/hub due to a change introduced by
|
||||
>> diffusers version 0.14. InvokeAI will now move all models from the "diffusers" directory
|
||||
>> into "hub" and then remove the diffusers directory. This is a quick, safe, one-time
|
||||
>> operation. However if you have customized either of these directories and need to
|
||||
>> make adjustments, please press ctrl-C now to abort and relaunch InvokeAI when you are ready.
|
||||
>> Otherwise press <enter> to continue."""
|
||||
)
|
||||
print("** This is a quick one-time operation.")
|
||||
input('continue> ')
|
||||
|
||||
# transformer files get moved into the hub directory
|
||||
if cls._is_huggingface_hub_directory_present():
|
||||
@ -948,33 +998,20 @@ class ModelManager(object):
|
||||
for model in legacy_locations:
|
||||
source = models_dir / model
|
||||
dest = hub / model.stem
|
||||
if dest.exists() and not source.exists():
|
||||
continue
|
||||
print(f"** {source} => {dest}")
|
||||
if source.exists():
|
||||
if dest.exists():
|
||||
rmtree(source)
|
||||
if dest.is_symlink():
|
||||
print(f"** Found symlink at {dest.name}. Not migrating.")
|
||||
elif dest.exists():
|
||||
if source.is_dir():
|
||||
rmtree(source)
|
||||
else:
|
||||
source.unlink()
|
||||
else:
|
||||
move(source, dest)
|
||||
|
||||
# anything else gets moved into the diffusers directory
|
||||
if cls._is_huggingface_hub_directory_present():
|
||||
diffusers = global_cache_dir("diffusers")
|
||||
else:
|
||||
diffusers = models_dir / "diffusers"
|
||||
|
||||
os.makedirs(diffusers, exist_ok=True)
|
||||
for root, dirs, _ in os.walk(models_dir, topdown=False):
|
||||
for dir in dirs:
|
||||
full_path = Path(root, dir)
|
||||
if full_path.is_relative_to(hub) or full_path.is_relative_to(diffusers):
|
||||
continue
|
||||
if Path(dir).match("models--*--*"):
|
||||
dest = diffusers / dir
|
||||
print(f"** {full_path} => {dest}")
|
||||
if dest.exists():
|
||||
rmtree(full_path)
|
||||
else:
|
||||
move(full_path, dest)
|
||||
|
||||
# now clean up by removing any empty directories
|
||||
empty = [
|
||||
root
|
||||
@ -1072,7 +1109,7 @@ class ModelManager(object):
|
||||
path = name_or_path
|
||||
else:
|
||||
owner, repo = name_or_path.split("/")
|
||||
path = Path(global_cache_dir("diffusers") / f"models--{owner}--{repo}")
|
||||
path = Path(global_cache_dir("hub") / f"models--{owner}--{repo}")
|
||||
if not path.exists():
|
||||
return None
|
||||
hashpath = path / "checksum.sha256"
|
||||
@ -1133,7 +1170,7 @@ class ModelManager(object):
|
||||
using_fp16 = self.precision == "float16"
|
||||
|
||||
vae_args.update(
|
||||
cache_dir=global_cache_dir("diffusers"),
|
||||
cache_dir=global_cache_dir("hub"),
|
||||
local_files_only=not Globals.internet_available,
|
||||
)
|
||||
|
||||
@ -1172,7 +1209,7 @@ class ModelManager(object):
|
||||
|
||||
@staticmethod
|
||||
def _delete_model_from_cache(repo_id):
|
||||
cache_info = scan_cache_dir(global_cache_dir("diffusers"))
|
||||
cache_info = scan_cache_dir(global_cache_dir("hub"))
|
||||
|
||||
# I'm sure there is a way to do this with comprehensions
|
||||
# but the code quickly became incomprehensible!
|
||||
|
@ -640,7 +640,7 @@ def do_textual_inversion_training(
|
||||
assert (
|
||||
pretrained_model_name_or_path
|
||||
), f"models.yaml error: neither 'repo_id' nor 'path' is defined for {model}"
|
||||
pipeline_args = dict(cache_dir=global_cache_dir("diffusers"))
|
||||
pipeline_args = dict(cache_dir=global_cache_dir("hub"))
|
||||
|
||||
# Load tokenizer
|
||||
if tokenizer_name:
|
||||
|
@ -26,7 +26,7 @@ from ..args import APP_ID, APP_VERSION, Args, calculate_init_img_hash
|
||||
from ..generator import infill_methods
|
||||
from ..globals import Globals, global_converted_ckpts_dir, global_models_dir
|
||||
from ..image_util import PngWriter, retrieve_metadata
|
||||
from ..model_management import merge_diffusion_models
|
||||
from ...frontend.merge.merge_diffusers import merge_diffusion_models
|
||||
from ..prompting import (
|
||||
get_prompt_structure,
|
||||
get_tokenizer,
|
||||
|
@ -20,7 +20,7 @@ stable-diffusion-2.1:
|
||||
recommended: True
|
||||
sd-inpainting-2.0:
|
||||
description: Stable Diffusion version 2.0 inpainting model (5.21 GB)
|
||||
repo_id: stabilityai/stable-diffusion-2-1
|
||||
repo_id: stabilityai/stable-diffusion-2-inpainting
|
||||
format: diffusers
|
||||
recommended: False
|
||||
analog-diffusion-1.0:
|
||||
|
@ -1,6 +1,6 @@
|
||||
model:
|
||||
base_learning_rate: 1.0e-4
|
||||
target: invokeai.backend.models.diffusion.ddpm.LatentDiffusion
|
||||
target: invokeai.backend.stable_diffusion.diffusion.ddpm.LatentDiffusion
|
||||
params:
|
||||
parameterization: "v"
|
||||
linear_start: 0.00085
|
||||
|
67
invokeai/configs/stable-diffusion/v2-inference.yaml
Normal file
67
invokeai/configs/stable-diffusion/v2-inference.yaml
Normal file
@ -0,0 +1,67 @@
|
||||
model:
|
||||
base_learning_rate: 1.0e-4
|
||||
target: invokeai.backend.stable_diffusion.diffusion.ddpm.LatentDiffusion
|
||||
params:
|
||||
linear_start: 0.00085
|
||||
linear_end: 0.0120
|
||||
num_timesteps_cond: 1
|
||||
log_every_t: 200
|
||||
timesteps: 1000
|
||||
first_stage_key: "jpg"
|
||||
cond_stage_key: "txt"
|
||||
image_size: 64
|
||||
channels: 4
|
||||
cond_stage_trainable: false
|
||||
conditioning_key: crossattn
|
||||
monitor: val/loss_simple_ema
|
||||
scale_factor: 0.18215
|
||||
use_ema: False # we set this to false because this is an inference only config
|
||||
|
||||
unet_config:
|
||||
target: invokeai.backend.stable_diffusion.diffusionmodules.openaimodel.UNetModel
|
||||
params:
|
||||
use_checkpoint: True
|
||||
use_fp16: True
|
||||
image_size: 32 # unused
|
||||
in_channels: 4
|
||||
out_channels: 4
|
||||
model_channels: 320
|
||||
attention_resolutions: [ 4, 2, 1 ]
|
||||
num_res_blocks: 2
|
||||
channel_mult: [ 1, 2, 4, 4 ]
|
||||
num_head_channels: 64 # need to fix for flash-attn
|
||||
use_spatial_transformer: True
|
||||
use_linear_in_transformer: True
|
||||
transformer_depth: 1
|
||||
context_dim: 1024
|
||||
legacy: False
|
||||
|
||||
first_stage_config:
|
||||
target: invokeai.backend.stable_diffusion.autoencoder.AutoencoderKL
|
||||
params:
|
||||
embed_dim: 4
|
||||
monitor: val/rec_loss
|
||||
ddconfig:
|
||||
#attn_type: "vanilla-xformers"
|
||||
double_z: true
|
||||
z_channels: 4
|
||||
resolution: 256
|
||||
in_channels: 3
|
||||
out_ch: 3
|
||||
ch: 128
|
||||
ch_mult:
|
||||
- 1
|
||||
- 2
|
||||
- 4
|
||||
- 4
|
||||
num_res_blocks: 2
|
||||
attn_resolutions: []
|
||||
dropout: 0.0
|
||||
lossconfig:
|
||||
target: torch.nn.Identity
|
||||
|
||||
cond_stage_config:
|
||||
target: invokeai.backend.stable_diffusion.encoders.modules.FrozenOpenCLIPEmbedder
|
||||
params:
|
||||
freeze: True
|
||||
layer: "penultimate"
|
@ -19,7 +19,7 @@ import invokeai.version as invokeai
|
||||
|
||||
from ...backend import Generate, ModelManager
|
||||
from ...backend.args import Args, dream_cmd_from_png, metadata_dumps, metadata_from_png
|
||||
from ...backend.globals import Globals
|
||||
from ...backend.globals import Globals, global_config_dir
|
||||
from ...backend.image_util import (
|
||||
PngWriter,
|
||||
make_grid,
|
||||
@ -66,6 +66,9 @@ def main():
|
||||
Globals.sequential_guidance = args.sequential_guidance
|
||||
Globals.ckpt_convert = True # always true now
|
||||
|
||||
# run any post-install patches needed
|
||||
run_patches()
|
||||
|
||||
print(f">> Internet connectivity is {Globals.internet_available}")
|
||||
|
||||
if not args.conf:
|
||||
@ -658,7 +661,16 @@ def import_model(model_path: str, gen, opt, completer, convert=False):
|
||||
)
|
||||
|
||||
if not imported_name:
|
||||
print("** Import failed or was skipped")
|
||||
if config_file := _pick_configuration_file(completer):
|
||||
imported_name = gen.model_manager.heuristic_import(
|
||||
model_path,
|
||||
model_name=model_name,
|
||||
description=model_desc,
|
||||
convert=convert,
|
||||
model_config_file=config_file,
|
||||
)
|
||||
if not imported_name:
|
||||
print("** Aborting import.")
|
||||
return
|
||||
|
||||
if not _verify_load(imported_name, gen):
|
||||
@ -672,6 +684,46 @@ def import_model(model_path: str, gen, opt, completer, convert=False):
|
||||
completer.update_models(gen.model_manager.list_models())
|
||||
print(f">> {imported_name} successfully installed")
|
||||
|
||||
def _pick_configuration_file(completer)->Path:
|
||||
print(
|
||||
"""
|
||||
Please select the type of this model:
|
||||
[1] A Stable Diffusion v1.x ckpt/safetensors model
|
||||
[2] A Stable Diffusion v1.x inpainting ckpt/safetensors model
|
||||
[3] A Stable Diffusion v2.x base model (512 pixels)
|
||||
[4] A Stable Diffusion v2.x v-predictive model (768 pixels)
|
||||
[5] Other (you will be prompted to enter the config file path)
|
||||
[Q] I have no idea! Skip the import.
|
||||
""")
|
||||
choices = [
|
||||
global_config_dir() / 'stable-diffusion' / x
|
||||
for x in [
|
||||
'v1-inference.yaml',
|
||||
'v1-inpainting-inference.yaml',
|
||||
'v2-inference.yaml',
|
||||
'v2-inference-v.yaml',
|
||||
]
|
||||
]
|
||||
|
||||
ok = False
|
||||
while not ok:
|
||||
try:
|
||||
choice = input('select 0-5, Q > ').strip()
|
||||
if choice.startswith(('q','Q')):
|
||||
return
|
||||
if choice == '5':
|
||||
completer.complete_extensions(('.yaml'))
|
||||
choice = Path(input('Select config file for this model> ').strip()).absolute()
|
||||
completer.complete_extensions(None)
|
||||
ok = choice.exists()
|
||||
else:
|
||||
choice = choices[int(choice)-1]
|
||||
ok = True
|
||||
except (ValueError, IndexError):
|
||||
print(f'{choice} is not a valid choice')
|
||||
except EOFError:
|
||||
return
|
||||
return choice
|
||||
|
||||
def _verify_load(model_name: str, gen) -> bool:
|
||||
print(">> Verifying that new model loads...")
|
||||
@ -1236,6 +1288,21 @@ def check_internet() -> bool:
|
||||
except:
|
||||
return False
|
||||
|
||||
# This routine performs any patch-ups needed after installation
|
||||
def run_patches():
|
||||
# install ckpt configuration files that may have been added to the
|
||||
# distro after original root directory configuration
|
||||
import invokeai.configs as conf
|
||||
from shutil import copyfile
|
||||
|
||||
root_configs = Path(global_config_dir(), 'stable-diffusion')
|
||||
repo_configs = Path(conf.__path__[0], 'stable-diffusion')
|
||||
if not root_configs.exists():
|
||||
os.makedirs(root_configs, exist_ok=True)
|
||||
for src in repo_configs.iterdir():
|
||||
dest = root_configs / src.name
|
||||
if not dest.exists():
|
||||
copyfile(src, dest)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@ -442,7 +442,7 @@ def main():
|
||||
args = _parse_args()
|
||||
global_set_root(args.root_dir)
|
||||
|
||||
cache_dir = str(global_cache_dir("diffusers"))
|
||||
cache_dir = str(global_cache_dir("hub"))
|
||||
os.environ[
|
||||
"HF_HOME"
|
||||
] = cache_dir # because not clear the merge pipeline is honoring cache_dir
|
||||
|
@ -1,20 +1,43 @@
|
||||
# InvokeAI UI dev setup
|
||||
# InvokeAI Web UI
|
||||
|
||||
The UI is in `invokeai/frontend`.
|
||||
The UI is a fairly straightforward Typescript React app. The only really fancy stuff is the Unified Canvas.
|
||||
|
||||
## Environment set up
|
||||
Code in `invokeai/frontend/web/` if you want to have a look.
|
||||
|
||||
Install [node](https://nodejs.org/en/download/) (includes npm) and
|
||||
[yarn](https://yarnpkg.com/getting-started/install).
|
||||
## Details
|
||||
|
||||
From `invokeai/frontend/` run `yarn install --immutable` to get everything set up.
|
||||
State management is Redux via [Redux Toolkit](https://github.com/reduxjs/redux-toolkit). Communication with server is a mix of HTTP and [socket.io](https://github.com/socketio/socket.io-client) (with a custom redux middleware to help).
|
||||
|
||||
## Dev
|
||||
[Chakra-UI](https://github.com/chakra-ui/chakra-ui) for components and styling.
|
||||
|
||||
[Konva](https://github.com/konvajs/react-konva) for the canvas, but we are pushing the limits of what is feasible with it (and HTML canvas in general). We plan to rebuild it with [PixiJS](https://github.com/pixijs/pixijs) to take advantage of WebGL's improved raster handling.
|
||||
|
||||
[Vite](https://vitejs.dev/) for bundling.
|
||||
|
||||
Localisation is via [i18next](https://github.com/i18next/react-i18next), but translation happens on our [Weblate](https://hosted.weblate.org/engage/invokeai/) project. Only the English source strings should be changed on this repo.
|
||||
|
||||
## Contributing
|
||||
|
||||
Thanks for your interest in contributing to the InvokeAI Web UI!
|
||||
|
||||
We encourage you to ping @psychedelicious and @blessedcoolant on [Discord](https://discord.gg/ZmtBAhwWhy) if you want to contribute, just to touch base and ensure your work doesn't conflict with anything else going on. The project is very active.
|
||||
|
||||
### Dev Environment
|
||||
|
||||
Install [node](https://nodejs.org/en/download/) and [yarn classic](https://classic.yarnpkg.com/lang/en/).
|
||||
|
||||
From `invokeai/frontend/web/` run `yarn install` to get everything set up.
|
||||
|
||||
Start everything in dev mode:
|
||||
|
||||
1. Start the dev server: `yarn dev`
|
||||
2. Start the InvokeAI UI per usual: `invokeai --web`
|
||||
3. Point your browser to the dev server address e.g. `http://localhost:5173/`
|
||||
|
||||
To build for dev: `yarn build-dev`
|
||||
### Production builds
|
||||
|
||||
To build for production: `yarn build`
|
||||
For a number of technical and logistical reasons, we need to commit UI build artefacts to the repo.
|
||||
|
||||
If you submit a PR, there is a good chance we will ask you to include a separate commit with a build of the app.
|
||||
|
||||
To build for production, run `yarn build`.
|
||||
|
3
invokeai/frontend/web/__init__.py
Normal file
3
invokeai/frontend/web/__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
'''
|
||||
Initialization file for invokeai.frontend.web
|
||||
'''
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
315
invokeai/frontend/web/dist/assets/ThemeLocaleProvider-e23d0dbb.js
vendored
Normal file
315
invokeai/frontend/web/dist/assets/ThemeLocaleProvider-e23d0dbb.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
invokeai/frontend/web/dist/index.html
vendored
2
invokeai/frontend/web/dist/index.html
vendored
@ -12,7 +12,7 @@
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
<script type="module" crossorigin src="./assets/index-bcc89564.js"></script>
|
||||
<script type="module" crossorigin src="./assets/index-b928084d.js"></script>
|
||||
<link rel="stylesheet" href="./assets/index-5483945c.css">
|
||||
</head>
|
||||
|
||||
|
3
invokeai/frontend/web/dist/locales/en.json
vendored
3
invokeai/frontend/web/dist/locales/en.json
vendored
@ -371,7 +371,8 @@
|
||||
"convertToDiffusersHelpText6": "Do you wish to convert this model?",
|
||||
"convertToDiffusersSaveLocation": "Save Location",
|
||||
"v1": "v1",
|
||||
"v2": "v2",
|
||||
"v2_base": "v2 (512px)",
|
||||
"v2_768": "v2 (768px)",
|
||||
"inpainting": "v1 Inpainting",
|
||||
"customConfig": "Custom Config",
|
||||
"pathToCustomConfig": "Path To Custom Config",
|
||||
|
@ -4,14 +4,14 @@
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"prepare": "cd ../../../ && husky install invokeai/frontend/web/.husky",
|
||||
"dev": "vite dev",
|
||||
"build": "npm run lint && vite build",
|
||||
"dev": "concurrently \"vite dev\" \"yarn run theme:watch\"",
|
||||
"build": "yarn run lint && vite build",
|
||||
"preview": "vite preview",
|
||||
"lint:madge": "madge --circular src/main.tsx",
|
||||
"lint:eslint": "eslint --max-warnings=0",
|
||||
"lint:prettier": "prettier --check .",
|
||||
"lint:tsc": "tsc --noEmit",
|
||||
"lint": "npm run lint:eslint && npm run lint:prettier && npm run lint:tsc && npm run lint:madge",
|
||||
"lint": "yarn run lint:eslint && yarn run lint:prettier && yarn run lint:tsc && yarn run lint:madge",
|
||||
"fix": "eslint --fix . && prettier --loglevel warn --write . && tsc --noEmit",
|
||||
"lint-staged": "lint-staged",
|
||||
"postinstall": "patch-package && yarn run theme",
|
||||
@ -38,6 +38,7 @@
|
||||
"@chakra-ui/anatomy": "^2.1.1",
|
||||
"@chakra-ui/icons": "^2.0.17",
|
||||
"@chakra-ui/react": "^2.5.1",
|
||||
"@chakra-ui/styled-system": "^2.6.1",
|
||||
"@chakra-ui/theme-tools": "^2.0.16",
|
||||
"@emotion/react": "^11.10.6",
|
||||
"@emotion/styled": "^11.10.6",
|
||||
@ -82,6 +83,7 @@
|
||||
"@typescript-eslint/parser": "^5.52.0",
|
||||
"@vitejs/plugin-react-swc": "^3.2.0",
|
||||
"babel-plugin-transform-imports": "^2.0.0",
|
||||
"concurrently": "^7.6.0",
|
||||
"eslint": "^8.34.0",
|
||||
"eslint-config-prettier": "^8.6.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
|
@ -371,7 +371,8 @@
|
||||
"convertToDiffusersHelpText6": "Do you wish to convert this model?",
|
||||
"convertToDiffusersSaveLocation": "Save Location",
|
||||
"v1": "v1",
|
||||
"v2": "v2",
|
||||
"v2_base": "v2 (512px)",
|
||||
"v2_768": "v2 (768px)",
|
||||
"inpainting": "v1 Inpainting",
|
||||
"customConfig": "Custom Config",
|
||||
"pathToCustomConfig": "Path To Custom Config",
|
||||
|
@ -363,7 +363,6 @@
|
||||
"convertToDiffusersHelpText6": "¿Desea transformar este modelo?",
|
||||
"convertToDiffusersSaveLocation": "Guardar ubicación",
|
||||
"v1": "v1",
|
||||
"v2": "v2",
|
||||
"statusConverting": "Adaptar",
|
||||
"modelConverted": "Modelo adaptado",
|
||||
"sameFolder": "La misma carpeta",
|
||||
|
@ -45,7 +45,9 @@
|
||||
"statusUpscaling": "Mise à échelle",
|
||||
"statusUpscalingESRGAN": "Mise à échelle (ESRGAN)",
|
||||
"statusLoadingModel": "Chargement du modèle",
|
||||
"statusModelChanged": "Modèle changé"
|
||||
"statusModelChanged": "Modèle changé",
|
||||
"discordLabel": "Discord",
|
||||
"githubLabel": "Github"
|
||||
},
|
||||
"gallery": {
|
||||
"generations": "Générations",
|
||||
|
@ -92,7 +92,6 @@
|
||||
"modelThree": "מודל 3",
|
||||
"mergedModelName": "שם מודל ממוזג",
|
||||
"v1": "v1",
|
||||
"v2": "v2",
|
||||
"invokeRoot": "תיקיית InvokeAI",
|
||||
"customConfig": "תצורה מותאמת אישית",
|
||||
"pathToCustomConfig": "נתיב לתצורה מותאמת אישית",
|
||||
|
@ -361,7 +361,6 @@
|
||||
"convertToDiffusersHelpText5": "Assicurati di avere spazio su disco sufficiente. I modelli generalmente variano tra 4 GB e 7 GB di dimensioni.",
|
||||
"convertToDiffusersHelpText6": "Vuoi convertire questo modello?",
|
||||
"convertToDiffusersSaveLocation": "Ubicazione salvataggio",
|
||||
"v2": "v2",
|
||||
"inpainting": "v1 Inpainting",
|
||||
"customConfig": "Configurazione personalizzata",
|
||||
"statusConverting": "Conversione in corso",
|
||||
|
@ -302,7 +302,7 @@
|
||||
"name": "Naam",
|
||||
"nameValidationMsg": "Geef een naam voor je model",
|
||||
"description": "Beschrijving",
|
||||
"descriptionValidationMsg": "Voeg een beschrijving toe voor je model",
|
||||
"descriptionValidationMsg": "Voeg een beschrijving toe voor je model.",
|
||||
"config": "Configuratie",
|
||||
"configValidationMsg": "Pad naar het configuratiebestand van je model.",
|
||||
"modelLocation": "Locatie model",
|
||||
@ -364,7 +364,6 @@
|
||||
"convertToDiffusersHelpText5": "Zorg ervoor dat je genoeg schijfruimte hebt. Modellen nemen gewoonlijk ongeveer 4 - 7 GB ruimte in beslag.",
|
||||
"convertToDiffusersSaveLocation": "Bewaarlocatie",
|
||||
"v1": "v1",
|
||||
"v2": "v2",
|
||||
"inpainting": "v1-inpainting",
|
||||
"customConfig": "Eigen configuratie",
|
||||
"pathToCustomConfig": "Pad naar eigen configuratie",
|
||||
|
@ -358,7 +358,6 @@
|
||||
"convertToDiffusersHelpText6": "Você deseja converter este modelo?",
|
||||
"convertToDiffusersSaveLocation": "Local para Salvar",
|
||||
"v1": "v1",
|
||||
"v2": "v2",
|
||||
"inpainting": "v1 Inpainting",
|
||||
"customConfig": "Configuração personalizada",
|
||||
"pathToCustomConfig": "Caminho para configuração personalizada",
|
||||
@ -381,7 +380,19 @@
|
||||
"allModels": "Todos os Modelos",
|
||||
"repoIDValidationMsg": "Repositório Online do seu Modelo",
|
||||
"convert": "Converter",
|
||||
"convertToDiffusersHelpText2": "Este processo irá substituir sua entrada de Gerenciador de Modelos por uma versão Diffusers do mesmo modelo."
|
||||
"convertToDiffusersHelpText2": "Este processo irá substituir sua entrada de Gerenciador de Modelos por uma versão Diffusers do mesmo modelo.",
|
||||
"mergedModelCustomSaveLocation": "Caminho Personalizado",
|
||||
"mergedModelSaveLocation": "Local de Salvamento",
|
||||
"interpolationType": "Tipo de Interpolação",
|
||||
"ignoreMismatch": "Ignorar Divergências entre Modelos Selecionados",
|
||||
"invokeAIFolder": "Pasta Invoke AI",
|
||||
"weightedSum": "Soma Ponderada",
|
||||
"sigmoid": "Sigmóide",
|
||||
"inverseSigmoid": "Sigmóide Inversa",
|
||||
"modelMergeHeaderHelp1": "Você pode mesclar até três modelos diferentes para criar uma mistura que atenda às suas necessidades.",
|
||||
"modelMergeInterpAddDifferenceHelp": "Neste modo, o Modelo 3 é primeiro subtraído do Modelo 2. A versão resultante é mesclada com o Modelo 1 com a taxa alpha definida acima.",
|
||||
"modelMergeAlphaHelp": "Alpha controla a força da mistura dos modelos. Valores de alpha mais baixos resultam em uma influência menor do segundo modelo.",
|
||||
"modelMergeHeaderHelp2": "Apenas Diffusers estão disponíveis para mesclagem. Se você deseja mesclar um modelo de checkpoint, por favor, converta-o para Diffusers primeiro."
|
||||
},
|
||||
"parameters": {
|
||||
"images": "Imagems",
|
||||
@ -441,7 +452,22 @@
|
||||
"info": "Informações",
|
||||
"deleteImage": "Apagar Imagem",
|
||||
"initialImage": "Imagem inicial",
|
||||
"showOptionsPanel": "Mostrar Painel de Opções"
|
||||
"showOptionsPanel": "Mostrar Painel de Opções",
|
||||
"vSymmetryStep": "V Passo de Simetria",
|
||||
"hSymmetryStep": "H Passo de Simetria",
|
||||
"symmetry": "Simetria",
|
||||
"copyImage": "Copiar imagem",
|
||||
"negativePrompts": "Indicações negativas",
|
||||
"hiresStrength": "Força da Alta Resolução",
|
||||
"denoisingStrength": "A força de remoção de ruído",
|
||||
"imageToImage": "Imagem para Imagem",
|
||||
"cancel": {
|
||||
"setType": "Definir tipo de cancelamento",
|
||||
"isScheduled": "Cancelando",
|
||||
"schedule": "Cancelar após a iteração atual",
|
||||
"immediate": "Cancelar imediatamente"
|
||||
},
|
||||
"general": "Geral"
|
||||
},
|
||||
"settings": {
|
||||
"models": "Modelos",
|
||||
@ -454,7 +480,8 @@
|
||||
"resetWebUI": "Reiniciar Interface",
|
||||
"resetWebUIDesc1": "Reiniciar a interface apenas reinicia o cache local do broswer para imagens e configurações lembradas. Não apaga nenhuma imagem do disco.",
|
||||
"resetWebUIDesc2": "Se as imagens não estão aparecendo na galeria ou algo mais não está funcionando, favor tentar reiniciar antes de postar um problema no GitHub.",
|
||||
"resetComplete": "A interface foi reiniciada. Atualize a página para carregar."
|
||||
"resetComplete": "A interface foi reiniciada. Atualize a página para carregar.",
|
||||
"useSlidersForAll": "Usar deslizadores para todas as opções"
|
||||
},
|
||||
"toast": {
|
||||
"tempFoldersEmptied": "Pasta de Arquivos Temporários Esvaziada",
|
||||
@ -546,5 +573,20 @@
|
||||
"betaDarkenOutside": "Escurecer Externamente",
|
||||
"betaLimitToBox": "Limitar Para a Caixa",
|
||||
"betaPreserveMasked": "Preservar Máscarado"
|
||||
},
|
||||
"tooltip": {
|
||||
"feature": {
|
||||
"seed": "O valor da semente afeta o ruído inicial a partir do qual a imagem é formada. Você pode usar as sementes já existentes de imagens anteriores. 'Limiar de ruído' é usado para mitigar artefatos em valores CFG altos (experimente a faixa de 0-10), e o Perlin para adicionar ruído Perlin durante a geração: ambos servem para adicionar variação às suas saídas.",
|
||||
"gallery": "A galeria exibe as gerações da pasta de saída conforme elas são criadas. As configurações são armazenadas em arquivos e acessadas pelo menu de contexto.",
|
||||
"other": "Essas opções ativam modos alternativos de processamento para o Invoke. 'Seamless tiling' criará padrões repetidos na saída. 'High resolution' é uma geração em duas etapas com img2img: use essa configuração quando desejar uma imagem maior e mais coerente sem artefatos. Levará mais tempo do que o txt2img usual.",
|
||||
"boundingBox": "A caixa delimitadora é a mesma que as configurações de largura e altura para Texto para Imagem ou Imagem para Imagem. Apenas a área na caixa será processada.",
|
||||
"upscale": "Use o ESRGAN para ampliar a imagem imediatamente após a geração.",
|
||||
"seamCorrection": "Controla o tratamento das emendas visíveis que ocorrem entre as imagens geradas no canvas.",
|
||||
"faceCorrection": "Correção de rosto com GFPGAN ou Codeformer: o algoritmo detecta rostos na imagem e corrige quaisquer defeitos. Um valor alto mudará mais a imagem, resultando em rostos mais atraentes. Codeformer com uma fidelidade maior preserva a imagem original às custas de uma correção de rosto mais forte.",
|
||||
"prompt": "Este é o campo de prompt. O prompt inclui objetos de geração e termos estilísticos. Você também pode adicionar peso (importância do token) no prompt, mas comandos e parâmetros de CLI não funcionarão.",
|
||||
"infillAndScaling": "Gerencie os métodos de preenchimento (usados em áreas mascaradas ou apagadas do canvas) e a escala (útil para tamanhos de caixa delimitadora pequenos).",
|
||||
"imageToImage": "Image to Image carrega qualquer imagem como inicial, que é então usada para gerar uma nova junto com o prompt. Quanto maior o valor, mais a imagem resultante mudará. Valores de 0.0 a 1.0 são possíveis, a faixa recomendada é de 0.25 a 0.75",
|
||||
"variations": "Experimente uma variação com um valor entre 0,1 e 1,0 para mudar o resultado para uma determinada semente. Variações interessantes da semente estão entre 0,1 e 0,3."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1 +1,24 @@
|
||||
{}
|
||||
{
|
||||
"common": {
|
||||
"nodes": "節點",
|
||||
"img2img": "圖片轉圖片",
|
||||
"langSimplifiedChinese": "簡體中文",
|
||||
"statusError": "錯誤",
|
||||
"statusDisconnected": "已中斷連線",
|
||||
"statusConnected": "已連線",
|
||||
"back": "返回",
|
||||
"load": "載入",
|
||||
"close": "關閉",
|
||||
"langEnglish": "英語",
|
||||
"settingsLabel": "設定",
|
||||
"upload": "上傳",
|
||||
"langArabic": "阿拉伯語",
|
||||
"greenTheme": "綠色",
|
||||
"lightTheme": "淺色",
|
||||
"darkTheme": "深色",
|
||||
"discordLabel": "Discord",
|
||||
"nodesDesc": "使用Node生成圖像的系統正在開發中。敬請期待有關於這項功能的更新。",
|
||||
"reportBugLabel": "回報錯誤",
|
||||
"githubLabel": "GitHub"
|
||||
}
|
||||
}
|
||||
|
@ -163,7 +163,8 @@ export default function SearchModels() {
|
||||
|
||||
const configFiles = {
|
||||
v1: 'configs/stable-diffusion/v1-inference.yaml',
|
||||
v2: 'configs/stable-diffusion/v2-inference-v.yaml',
|
||||
v2_base: 'configs/stable-diffusion/v2-inference-v.yaml',
|
||||
v2_768: 'configs/stable-diffusion/v2-inference-v.yaml',
|
||||
inpainting: 'configs/stable-diffusion/v1-inpainting-inference.yaml',
|
||||
custom: pathToConfig,
|
||||
};
|
||||
@ -372,8 +373,11 @@ export default function SearchModels() {
|
||||
<Radio value="v1">
|
||||
<Text fontSize="sm">{t('modelManager.v1')}</Text>
|
||||
</Radio>
|
||||
<Radio value="v2">
|
||||
<Text fontSize="sm">{t('modelManager.v2')}</Text>
|
||||
<Radio value="v2_base">
|
||||
<Text fontSize="sm">{t('modelManager.v2_base')}</Text>
|
||||
</Radio>
|
||||
<Radio value="v2_768">
|
||||
<Text fontSize="sm">{t('modelManager.v2_768')}</Text>
|
||||
</Radio>
|
||||
<Radio value="inpainting">
|
||||
<Text fontSize="sm">{t('modelManager.inpainting')}</Text>
|
||||
|
@ -1,40 +0,0 @@
|
||||
@mixin Button(
|
||||
$btn-color: rgb(45, 49, 53),
|
||||
$btn-color-hover: rgb(65, 69, 73),
|
||||
$btn-width: 100%,
|
||||
$btn-height: 100%,
|
||||
$icon-size: 20px
|
||||
) {
|
||||
// min-width: $btn-width;
|
||||
// min-height: $btn-height;
|
||||
// background-color: $btn-color;
|
||||
|
||||
// &:hover {
|
||||
// background-color: $btn-color-hover;
|
||||
// }
|
||||
|
||||
// &:disabled {
|
||||
// background-color: var(--btn-base-color);
|
||||
// &:hover {
|
||||
// background-color: var(--btn-base-color);
|
||||
// }
|
||||
// }
|
||||
|
||||
// svg {
|
||||
// width: $icon-size;
|
||||
// height: $icon-size;
|
||||
// color: var(--btn-svg-color);
|
||||
// }
|
||||
}
|
||||
|
||||
@mixin BaseButton {
|
||||
// background-color: var(--btn-base-color);
|
||||
// &:hover {
|
||||
// background-color: var(--btn-base-color-hover);
|
||||
// }
|
||||
// &:disabled {
|
||||
// &:hover {
|
||||
// background-color: var(--btn-base-color);
|
||||
// }
|
||||
// }
|
||||
}
|
@ -1,159 +0,0 @@
|
||||
// @media (max-width: 600px) {
|
||||
// #root {
|
||||
// .app-content {
|
||||
// padding: 5px;
|
||||
// .site-header {
|
||||
// position: fixed;
|
||||
// display: flex;
|
||||
// height: 100px;
|
||||
// z-index: 1;
|
||||
// .site-header-left-side {
|
||||
// position: absolute;
|
||||
// display: flex;
|
||||
// min-width: 145px;
|
||||
// float: left;
|
||||
// padding-left: 0;
|
||||
// }
|
||||
// .site-header-right-side {
|
||||
// display: grid;
|
||||
// grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
|
||||
// grid-template-rows: 25px 25px 25px;
|
||||
// grid-template-areas:
|
||||
// 'logoSpace logoSpace logoSpace sampler sampler sampler'
|
||||
// 'status status status status status status'
|
||||
// 'btn1 btn2 btn3 btn4 btn5 btn6';
|
||||
// row-gap: 15px;
|
||||
// .chakra-popover__popper {
|
||||
// grid-area: logoSpace;
|
||||
// }
|
||||
// > :nth-child(1).chakra-text {
|
||||
// grid-area: status;
|
||||
// width: 100%;
|
||||
// display: flex;
|
||||
// justify-content: center;
|
||||
// }
|
||||
// > :nth-child(2) {
|
||||
// grid-area: sampler;
|
||||
// display: flex;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
// select {
|
||||
// width: 185px;
|
||||
// margin-top: 10px;
|
||||
// }
|
||||
// .chakra-select__icon-wrapper {
|
||||
// right: 10px;
|
||||
// svg {
|
||||
// margin-top: 10px;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// > :nth-child(3) {
|
||||
// grid-area: btn1;
|
||||
// }
|
||||
// > :nth-child(4) {
|
||||
// grid-area: btn2;
|
||||
// }
|
||||
// > :nth-child(6) {
|
||||
// grid-area: btn3;
|
||||
// }
|
||||
// > :nth-child(7) {
|
||||
// grid-area: btn4;
|
||||
// }
|
||||
// > :nth-child(8) {
|
||||
// grid-area: btn5;
|
||||
// }
|
||||
// > :nth-child(9) {
|
||||
// grid-area: btn6;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// .app-tabs {
|
||||
// position: fixed;
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// row-gap: 15px;
|
||||
// max-width: 100%;
|
||||
// overflow: hidden;
|
||||
// margin-top: 120px;
|
||||
// .app-tabs-list {
|
||||
// display: flex;
|
||||
// justify-content: space-between;
|
||||
// }
|
||||
// .app-tabs-panels {
|
||||
// overflow: hidden;
|
||||
// overflow-y: scroll;
|
||||
// .workarea-main {
|
||||
// display: grid;
|
||||
// grid-template-areas:
|
||||
// 'workarea'
|
||||
// 'options'
|
||||
// 'gallery';
|
||||
// row-gap: 15px;
|
||||
// .parameters-panel-wrapper {
|
||||
// grid-area: options;
|
||||
// width: 100%;
|
||||
// max-width: 100%;
|
||||
// height: inherit;
|
||||
// overflow: inherit;
|
||||
// padding: 0 10px;
|
||||
// .main-settings-row {
|
||||
// max-width: 100%;
|
||||
// }
|
||||
// .advanced-parameters-item {
|
||||
// max-width: 100%;
|
||||
// }
|
||||
// }
|
||||
// .workarea-children-wrapper {
|
||||
// grid-area: workarea;
|
||||
// .workarea-split-view {
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// }
|
||||
// .current-image-options {
|
||||
// column-gap: 3px;
|
||||
// }
|
||||
// .text-to-image-area {
|
||||
// padding: 0;
|
||||
// }
|
||||
// .current-image-preview {
|
||||
// height: 430px;
|
||||
// }
|
||||
|
||||
// //image 2 image
|
||||
// .image-upload-button {
|
||||
// row-gap: 10px;
|
||||
// padding: 5px;
|
||||
// svg {
|
||||
// width: 2rem;
|
||||
// height: 2rem;
|
||||
// margin-top: 10px;
|
||||
// }
|
||||
// }
|
||||
|
||||
// //Cavas Painting
|
||||
// .inpainting-settings {
|
||||
// display: flex;
|
||||
// flex-wrap: wrap;
|
||||
// row-gap: 10px;
|
||||
// }
|
||||
// .inpainting-canvas-area {
|
||||
// .konvajs-content {
|
||||
// height: 400px !important;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// .image-gallery-wrapper {
|
||||
// grid-area: gallery;
|
||||
// min-height: 400px;
|
||||
// .image-gallery-popup {
|
||||
// width: 100% !important;
|
||||
// max-width: 100% !important;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
@ -1,7 +0,0 @@
|
||||
@mixin HideScrollbar {
|
||||
-ms-overflow-style: none;
|
||||
scrollbar-width: none;
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
// Calc Values
|
||||
$app-cutoff: 0px;
|
||||
$app-content-height-cutoff: calc(70px + 1rem); // default: 7rem
|
||||
|
||||
// Usage Variables
|
||||
// app
|
||||
$app-padding: 1rem;
|
||||
$progress-bar-thickness: 0.3rem;
|
||||
$app-width: calc(100vw - $app-cutoff);
|
||||
$app-height: calc(100vh - $progress-bar-thickness);
|
||||
$app-content-height: calc(100vh - $app-content-height-cutoff);
|
||||
$app-gallery-height: calc(100vh - ($app-content-height-cutoff + 5.5rem));
|
||||
$app-gallery-popover-height: calc(100vh - ($app-content-height-cutoff + 6rem));
|
||||
$app-metadata-height: calc(100vh - ($app-content-height-cutoff + 4.4rem));
|
||||
$app-text-to-image-height: calc(
|
||||
100vh - 9.4375rem - 1.925rem - 1.15rem
|
||||
); // do not touch ffs
|
||||
|
||||
// option bar
|
||||
$options-bar-max-width: 22.5rem;
|
@ -1,4 +0,0 @@
|
||||
@forward './Shared';
|
||||
@forward './Buttons';
|
||||
@forward './Variables';
|
||||
@forward './Responsive';
|
@ -1,143 +0,0 @@
|
||||
[data-theme='asdf'] {
|
||||
// General Colors
|
||||
--white: rgb(255, 255, 255);
|
||||
|
||||
// Accent Colors
|
||||
--accent-color-dim: rgb(57, 25, 153);
|
||||
--accent-color: rgb(80, 40, 200);
|
||||
--accent-color-bright: rgb(104, 60, 230);
|
||||
--accent-color-hover: var(--accent-color-bright);
|
||||
|
||||
// App Colors
|
||||
--root-bg-color: rgb(10, 10, 10);
|
||||
--background-color: rgb(26, 26, 32);
|
||||
--background-color-light: rgb(40, 44, 48);
|
||||
--background-color-secondary: rgb(16, 16, 22);
|
||||
|
||||
--text-color: rgb(255, 255, 255);
|
||||
--text-color-secondary: rgb(160, 162, 188);
|
||||
--subtext-color: rgb(24, 24, 34);
|
||||
--subtext-color-bright: rgb(48, 48, 64);
|
||||
|
||||
--border-color: rgb(30, 30, 46);
|
||||
--border-color-light: rgb(60, 60, 76);
|
||||
|
||||
--svg-color: rgb(255, 255, 255);
|
||||
|
||||
--invalid: rgb(255, 75, 75);
|
||||
--invalid-secondary: rgb(120, 5, 5);
|
||||
|
||||
--destructive-color: rgb(185, 55, 55);
|
||||
--destructive-color-hover: rgb(255, 75, 75);
|
||||
|
||||
--warning-color: rgb(200, 88, 40);
|
||||
--warning-color-hover: rgb(230, 117, 60);
|
||||
|
||||
// Error status colors
|
||||
--border-color-invalid: rgb(255, 80, 50);
|
||||
--box-shadow-color-invalid: rgb(210, 30, 10);
|
||||
|
||||
// Tabs
|
||||
--tab-color: rgb(30, 32, 42);
|
||||
--tab-hover-color: rgb(46, 48, 58);
|
||||
--tab-panel-bg: rgb(36, 38, 48);
|
||||
--tab-list-bg: var(--accent-color);
|
||||
--tab-list-text: rgb(202, 204, 216);
|
||||
--tab-list-text-inactive: rgb(92, 94, 114);
|
||||
|
||||
// Button Colors
|
||||
--btn-base-color: rgb(30, 32, 42);
|
||||
--btn-base-color-hover: rgb(46, 48, 68);
|
||||
|
||||
--btn-load-more: rgb(30, 32, 42);
|
||||
--btn-load-more-hover: rgb(54, 56, 66);
|
||||
|
||||
--btn-svg-color: rgb(255, 255, 255);
|
||||
--btn-delete-image: rgb(182, 46, 46);
|
||||
|
||||
// IAI Button Colors
|
||||
--btn-checkbox-border-hover: rgb(46, 48, 68);
|
||||
|
||||
// Progress Bar Color
|
||||
--progress-bar-color: var(--accent-color);
|
||||
|
||||
// Prompt Box Colors
|
||||
--prompt-bg-color: rgb(10, 10, 10);
|
||||
|
||||
// Switch
|
||||
--switch-bg-color: rgb(100, 102, 110);
|
||||
--switch-bg-active-color: var(--accent-color);
|
||||
|
||||
// Slider
|
||||
--slider-color: var(--accent-color-bright);
|
||||
|
||||
// Slider
|
||||
--slider-color: rgb(151, 113, 255);
|
||||
--slider-mark-color: rgb(151, 113, 255);
|
||||
|
||||
// Resizable
|
||||
--resizeable-handle-border-color: var(--accent-color);
|
||||
|
||||
// Metadata Viewer
|
||||
--metadata-bg-color: rgba(0, 0, 0, 0.7);
|
||||
--metadata-json-bg-color: rgba(255, 255, 255, 0.1);
|
||||
|
||||
// Status Message
|
||||
--status-good-color: rgb(125, 255, 100);
|
||||
--status-good-glow: rgb(40, 215, 40);
|
||||
--status-working-color: rgb(255, 175, 55);
|
||||
--status-working-glow: rgb(255, 160, 55);
|
||||
--status-bad-color: rgb(255, 90, 90);
|
||||
--status-bad-glow: rgb(255, 40, 40);
|
||||
--notice-color: rgb(130, 71, 19);
|
||||
|
||||
// Settings Modal
|
||||
--settings-modal-bg: rgb(30, 32, 42);
|
||||
|
||||
// Input
|
||||
--input-checkbox-bg: rgb(60, 64, 68);
|
||||
--input-checkbox-checked-bg: var(--accent-color);
|
||||
--input-checkbox-checked-tick: rgb(0, 0, 0);
|
||||
|
||||
--input-border-color: var(--accent-color-bright);
|
||||
--input-box-shadow-color: var(--accent-color);
|
||||
|
||||
// Console
|
||||
--error-level-info: rgb(200, 202, 224);
|
||||
--error-level-warning: rgb(255, 225, 105);
|
||||
--error-level-error: rgb(255, 81, 46);
|
||||
--console-bg-color: rgb(30, 30, 36);
|
||||
--console-icon-button-bg-color: rgb(50, 53, 64);
|
||||
--console-icon-button-bg-color-hover: rgb(70, 73, 84);
|
||||
|
||||
// Img2Img
|
||||
--img2img-img-bg-color: rgb(30, 32, 42);
|
||||
|
||||
// Gallery
|
||||
|
||||
// Context Menus
|
||||
--context-menu-bg-color: rgb(46, 48, 58);
|
||||
--context-menu-box-shadow: none;
|
||||
--context-menu-bg-color-hover: rgb(30, 32, 42);
|
||||
|
||||
// Shadows
|
||||
--floating-button-drop-shadow-color: var(--accent-color);
|
||||
|
||||
// Canvas
|
||||
--inpainting-alerts-bg: rgba(20, 20, 26, 0.75);
|
||||
--inpainting-alerts-icon-color: rgb(255, 255, 255);
|
||||
--inpainting-alerts-bg-active: var(--accent-color);
|
||||
--inpainting-alerts-icon-active: rgb(255, 255, 255);
|
||||
--inpainting-alerts-bg-alert: var(--invalid);
|
||||
--inpainting-alerts-icon-alert: rgb(255, 255, 255);
|
||||
|
||||
// Checkerboard
|
||||
--checkboard-dots-color: rgb(35, 35, 39);
|
||||
|
||||
// Scrollbar
|
||||
--scrollbar-color: var(--accent-color);
|
||||
--scrollbar-color-hover: var(--accent-color-bright);
|
||||
|
||||
// SubHook
|
||||
--subhook-color: var(--accent-color);
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
[data-theme='green'] {
|
||||
// General Colors
|
||||
--white: rgb(255, 255, 255);
|
||||
|
||||
// Accent Colors
|
||||
--accent-color-dim: rgb(10, 60, 40);
|
||||
--accent-color: rgb(20, 110, 70);
|
||||
--accent-color-bright: rgb(30, 180, 100);
|
||||
--accent-color-hover: var(--accent-color-bright);
|
||||
|
||||
// App Colors
|
||||
--root-bg-color: rgb(10, 10, 14);
|
||||
--background-color: rgb(30, 32, 37);
|
||||
--background-color-light: rgb(40, 44, 48);
|
||||
--background-color-secondary: rgb(22, 24, 28);
|
||||
|
||||
--text-color: rgb(255, 255, 255);
|
||||
--text-color-secondary: rgb(160, 164, 168);
|
||||
--subtext-color: rgb(24, 24, 28);
|
||||
--subtext-color-bright: rgb(68, 72, 76);
|
||||
|
||||
--border-color: rgb(40, 44, 48);
|
||||
--border-color-light: rgb(60, 60, 64);
|
||||
|
||||
--svg-color: rgb(220, 224, 228);
|
||||
|
||||
--invalid: rgb(255, 75, 75);
|
||||
--invalid-secondary: rgb(120, 5, 5);
|
||||
|
||||
--destructive-color: rgb(185, 55, 55);
|
||||
--destructive-color-hover: rgb(255, 75, 75);
|
||||
|
||||
--warning-color: rgb(200, 88, 40);
|
||||
--warning-color-hover: rgb(230, 117, 60);
|
||||
|
||||
// Error status colors
|
||||
--border-color-invalid: rgb(255, 80, 50);
|
||||
--box-shadow-color-invalid: rgb(210, 30, 10);
|
||||
|
||||
// Tabs
|
||||
--tab-color: rgb(40, 44, 48);
|
||||
--tab-hover-color: rgb(48, 52, 56); //done
|
||||
--tab-panel-bg: rgb(36, 40, 44);
|
||||
--tab-list-bg: var(--accent-color);
|
||||
--tab-list-text: rgb(202, 204, 206);
|
||||
--tab-list-text-inactive: rgb(92, 94, 96); //done
|
||||
|
||||
// Button Colors
|
||||
--btn-base-color: rgb(40, 44, 48);
|
||||
--btn-base-color-hover: rgb(56, 60, 64);
|
||||
|
||||
--btn-load-more: rgb(30, 32, 42);
|
||||
--btn-load-more-hover: rgb(54, 56, 66);
|
||||
|
||||
--btn-svg-color: rgb(255, 255, 255);
|
||||
|
||||
--btn-delete-image: rgb(182, 46, 46);
|
||||
|
||||
// IAI Button Colors
|
||||
--btn-checkbox-border-hover: rgb(46, 48, 68);
|
||||
|
||||
// Progress Bar Color
|
||||
--progress-bar-color: var(--accent-color);
|
||||
|
||||
// Prompt Box Colors
|
||||
--prompt-bg-color: rgb(10, 10, 14);
|
||||
|
||||
// Switch
|
||||
--switch-bg-color: rgb(100, 102, 110);
|
||||
--switch-bg-active-color: var(--accent-color);
|
||||
|
||||
// Slider
|
||||
--slider-color: var(--accent-color-bright);
|
||||
--slider-mark-color: var(--accent-color-bright);
|
||||
|
||||
// Resizable
|
||||
--resizeable-handle-border-color: var(--accent-color);
|
||||
|
||||
// Metadata Viewer
|
||||
--metadata-bg-color: rgba(0, 0, 0, 0.7);
|
||||
--metadata-json-bg-color: rgba(255, 255, 255, 0.1);
|
||||
|
||||
// Status Message
|
||||
--status-good-color: rgb(125, 255, 100);
|
||||
--status-good-glow: rgb(40, 215, 40);
|
||||
--status-working-color: rgb(255, 175, 55);
|
||||
--status-working-glow: rgb(255, 160, 55);
|
||||
--status-bad-color: rgb(255, 90, 90);
|
||||
--status-bad-glow: rgb(255, 40, 40);
|
||||
--notice-color: rgb(130, 71, 19);
|
||||
|
||||
// Settings Modal
|
||||
--settings-modal-bg: rgb(30, 32, 42);
|
||||
|
||||
// Input
|
||||
--input-checkbox-bg: rgb(60, 64, 68);
|
||||
--input-checkbox-checked-bg: var(--accent-color);
|
||||
--input-checkbox-checked-tick: rgb(0, 0, 0);
|
||||
|
||||
--input-border-color: var(--accent-color-bright);
|
||||
--input-box-shadow-color: var(--accent-color);
|
||||
|
||||
// Console
|
||||
--error-level-info: rgb(200, 202, 224);
|
||||
--error-level-warning: rgb(255, 225, 105);
|
||||
--error-level-error: rgb(255, 81, 46);
|
||||
--console-bg-color: rgb(30, 30, 36);
|
||||
--console-icon-button-bg-color: rgb(50, 53, 64);
|
||||
--console-icon-button-bg-color-hover: rgb(70, 73, 84);
|
||||
|
||||
// Img2Img
|
||||
--img2img-img-bg-color: rgb(30, 32, 42);
|
||||
|
||||
// Gallery
|
||||
|
||||
// Context Menus
|
||||
--context-menu-bg-color: rgb(46, 48, 58);
|
||||
--context-menu-box-shadow: none;
|
||||
--context-menu-bg-color-hover: rgb(30, 32, 42);
|
||||
|
||||
// Shadows
|
||||
--floating-button-drop-shadow-color: var(--accent-color);
|
||||
|
||||
// Canvas
|
||||
--inpainting-alerts-bg: rgba(20, 20, 26, 0.75);
|
||||
--inpainting-alerts-icon-color: rgb(255, 255, 255);
|
||||
--inpainting-alerts-bg-active: var(--accent-color);
|
||||
--inpainting-alerts-icon-active: rgb(255, 255, 255);
|
||||
--inpainting-alerts-bg-alert: var(--invalid);
|
||||
--inpainting-alerts-icon-alert: rgb(255, 255, 255);
|
||||
|
||||
//Checkerboard
|
||||
--checkboard-dots-color: rgb(35, 35, 39);
|
||||
|
||||
// Scrollbar
|
||||
--scrollbar-color: var(--accent-color);
|
||||
--scrollbar-color-hover: var(--accent-color-bright);
|
||||
|
||||
// SubHook
|
||||
--subhook-color: var(--accent-color);
|
||||
}
|
@ -1,138 +0,0 @@
|
||||
// [data-theme='light'] {
|
||||
// // General Colors
|
||||
// --white: rgb(255, 255, 255);
|
||||
|
||||
// // Accent Colors
|
||||
// --accent-color-dim: rgb(186, 146, 0);
|
||||
// --accent-color: rgb(235, 185, 5);
|
||||
// --accent-color-bright: rgb(255, 200, 0);
|
||||
// --accent-color-hover: var(--accent-color-bright);
|
||||
|
||||
// // App Colors
|
||||
// --root-bg-color: rgb(255, 255, 255);
|
||||
// --background-color: rgb(220, 222, 224);
|
||||
// --background-color-light: rgb(250, 252, 254);
|
||||
// --background-color-secondary: rgb(208, 210, 212);
|
||||
|
||||
// --text-color: rgb(0, 0, 0);
|
||||
// --text-color-secondary: rgb(40, 40, 40);
|
||||
// --subtext-color: rgb(24, 24, 34);
|
||||
// --subtext-color-bright: rgb(142, 144, 146);
|
||||
|
||||
// --border-color: rgb(200, 200, 200);
|
||||
// --border-color-light: rgb(147, 147, 147);
|
||||
|
||||
// --svg-color: rgb(50, 50, 50);
|
||||
|
||||
// --invalid: rgb(255, 75, 75);
|
||||
// --invalid-secondary: rgb(120, 5, 5);
|
||||
|
||||
// --destructive-color: rgb(237, 51, 51);
|
||||
// --destructive-color-hover: rgb(255, 55, 55);
|
||||
|
||||
// --warning-color: rgb(224, 142, 42);
|
||||
// --warning-color-hover: rgb(255, 167, 60);
|
||||
|
||||
// // Error status colors
|
||||
// --border-color-invalid: rgb(255, 80, 50);
|
||||
// --box-shadow-color-invalid: none;
|
||||
|
||||
// // Tabs
|
||||
// --tab-color: rgb(202, 204, 206);
|
||||
// --tab-hover-color: rgb(196, 198, 200);
|
||||
// --tab-panel-bg: rgb(206, 208, 210);
|
||||
// --tab-list-bg: rgb(235, 185, 5);
|
||||
// --tab-list-text: rgb(0, 0, 0);
|
||||
// --tab-list-text-inactive: rgb(106, 108, 110);
|
||||
|
||||
// // Button Colors
|
||||
// --btn-base-color: rgb(184, 186, 188);
|
||||
// --btn-base-color-hover: rgb(230, 232, 234);
|
||||
|
||||
// --btn-load-more: rgb(202, 204, 206);
|
||||
// --btn-load-more-hover: rgb(178, 180, 182);
|
||||
// --btn-svg-color: rgb(0, 0, 0);
|
||||
|
||||
// --btn-delete-image: rgb(213, 49, 49);
|
||||
|
||||
// // IAI Button Colors
|
||||
// --btn-checkbox-border-hover: rgb(176, 178, 182);
|
||||
// // Progress Bar Color
|
||||
// --progress-bar-color: rgb(235, 185, 5);
|
||||
|
||||
// // Prompt Box Colors
|
||||
// --prompt-bg-color: rgb(225, 227, 229);
|
||||
// // Switch
|
||||
// --switch-bg-color: rgb(178, 180, 182);
|
||||
// --switch-bg-active-color: rgb(235, 185, 5);
|
||||
|
||||
// // Slider
|
||||
// --slider-color: var(--accent-color);
|
||||
// --slider-mark-color: rgb(0, 0, 0);
|
||||
|
||||
// // Resizable
|
||||
// --resizeable-handle-border-color: rgb(160, 162, 164);
|
||||
|
||||
// // Metadata Viewer
|
||||
// --metadata-bg-color: rgba(230, 230, 230, 0.9);
|
||||
// --metadata-json-bg-color: rgba(0, 0, 0, 0.1);
|
||||
|
||||
// // Status Message
|
||||
// --status-good-color: rgb(21, 126, 0);
|
||||
// --status-good-glow: var(--background-color);
|
||||
// --status-working-color: rgb(235, 141, 0);
|
||||
// --status-working-glow: var(--background-color);
|
||||
// --status-bad-color: rgb(202, 0, 0);
|
||||
// --status-bad-glow: var(--background-color);
|
||||
// --notice-color: rgb(255, 71, 90);
|
||||
|
||||
// // Settings Modal
|
||||
// --settings-modal-bg: rgb(202, 204, 206);
|
||||
|
||||
// // Input
|
||||
// --input-checkbox-bg: rgb(167, 167, 171);
|
||||
// --input-checkbox-checked-bg: rgb(235, 185, 5);
|
||||
// --input-checkbox-checked-tick: rgb(0, 0, 0);
|
||||
// --input-border-color: rgb(0, 0, 0);
|
||||
// --input-box-shadow-color: none;
|
||||
|
||||
// // Console
|
||||
// --error-level-info: rgb(42, 42, 42);
|
||||
// --error-level-warning: rgb(173, 121, 0);
|
||||
// --error-level-error: rgb(145, 14, 0);
|
||||
// --console-bg-color: rgb(220, 224, 230);
|
||||
// --console-icon-button-bg-color: var(--switch-bg-color);
|
||||
// --console-icon-button-bg-color-hover: var(--resizeable-handle-border-color);
|
||||
|
||||
// // Img2Img
|
||||
// --img2img-img-bg-color: rgb(180, 182, 184);
|
||||
|
||||
// // Gallery
|
||||
|
||||
// // Context Menus
|
||||
// --context-menu-bg-color: var(--background-color);
|
||||
// --context-menu-box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, 0.35),
|
||||
// 0px 10px 20px -15px rgba(22, 23, 24, 0.2);
|
||||
// --context-menu-bg-color-hover: var(--background-color-secondary);
|
||||
|
||||
// // Shadows
|
||||
// --floating-button-drop-shadow-color: rgba(0, 0, 0, 0.7);
|
||||
|
||||
// // Canvas
|
||||
// --inpainting-alerts-bg: rgba(220, 222, 224, 0.75);
|
||||
// --inpainting-alerts-icon-color: rgb(0, 0, 0);
|
||||
// --inpainting-alerts-bg-active: rgb(255, 200, 0);
|
||||
// --inpainting-alerts-icon-active: rgb(0, 0, 0);
|
||||
// --inpainting-alerts-bg-alert: var(--invalid);
|
||||
// --inpainting-alerts-icon-alert: rgb(0, 0, 0);
|
||||
|
||||
// // Checkerboard
|
||||
// --checkboard-dots-color: rgb(160, 160, 172);
|
||||
|
||||
// // Scrollbar
|
||||
// --scrollbar-color: rgb(180, 180, 184);
|
||||
// --scrollbar-color-hover: rgb(150, 150, 154);
|
||||
|
||||
// // SubHook
|
||||
// --subhook-color: rgb(0, 0, 0);
|
||||
// }
|
@ -3,7 +3,6 @@ import {
|
||||
createMultiStyleConfigHelpers,
|
||||
defineStyle,
|
||||
} from '@chakra-ui/styled-system';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { definePartsStyle, defineMultiStyleConfig } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
@ -20,16 +19,16 @@ const invokeAIButton = defineStyle((props) => {
|
||||
fontSize: 'sm',
|
||||
border: 'none',
|
||||
borderRadius: 'base',
|
||||
bg: mode(`${c}.250`, `${c}.800`)(props),
|
||||
color: mode('base.900', 'base.100')(props),
|
||||
bg: `${c}.800`,
|
||||
color: 'base.100',
|
||||
_hover: {
|
||||
bg: mode(`${c}.300`, `${c}.700`)(props),
|
||||
bg: `${c}.700`,
|
||||
},
|
||||
_expanded: {
|
||||
bg: mode(`${c}.250`, `${c}.750`)(props),
|
||||
bg: `${c}.750`,
|
||||
borderBottomRadius: 'none',
|
||||
_hover: {
|
||||
bg: mode(`${c}.300`, `${c}.700`)(props),
|
||||
bg: `${c}.700`,
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -38,7 +37,7 @@ const invokeAIButton = defineStyle((props) => {
|
||||
const invokeAIPanel = defineStyle((props) => {
|
||||
const { colorScheme: c } = props;
|
||||
return {
|
||||
bg: mode(`${c}.200`, `${c}.800`)(props),
|
||||
bg: `${c}.800`,
|
||||
borderRadius: 'base',
|
||||
borderTopRadius: 'none',
|
||||
p: 4,
|
||||
|
@ -1,45 +1,44 @@
|
||||
import { defineStyle, defineStyleConfig } from '@chakra-ui/react';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const invokeAI = defineStyle((props) => {
|
||||
const { colorScheme: c } = props;
|
||||
// must specify `_disabled` colors if we override `_hover`, else hover on disabled has no styles
|
||||
const _disabled = {
|
||||
bg: mode(`${c}.200`, `${c}.600`)(props),
|
||||
color: mode(`${c}.700`, `${c}.100`)(props),
|
||||
bg: `${c}.600`,
|
||||
color: `${c}.100`,
|
||||
svg: {
|
||||
fill: mode(`${c}.700`, `${c}.100`)(props),
|
||||
fill: `${c}.100`,
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
bg: mode(`${c}.300`, `${c}.700`)(props),
|
||||
color: mode(`${c}.800`, `${c}.100`)(props),
|
||||
bg: `${c}.700`,
|
||||
color: `${c}.100`,
|
||||
borderRadius: 'base',
|
||||
svg: {
|
||||
fill: mode(`${c}.800`, `${c}.100`)(props),
|
||||
fill: `${c}.100`,
|
||||
},
|
||||
_disabled,
|
||||
_hover: {
|
||||
bg: mode(`${c}.400`, `${c}.650`)(props),
|
||||
color: mode(`black`, `${c}.50`)(props),
|
||||
bg: `${c}.650`,
|
||||
color: `${c}.50`,
|
||||
svg: {
|
||||
fill: mode(`black`, `${c}.50`)(props),
|
||||
fill: `${c}.50`,
|
||||
},
|
||||
_disabled,
|
||||
},
|
||||
_checked: {
|
||||
bg: mode('accent.200', 'accent.700')(props),
|
||||
color: mode('accent.800', 'accent.100')(props),
|
||||
bg: 'accent.700',
|
||||
color: 'accent.100',
|
||||
svg: {
|
||||
fill: mode('accent.800', 'accent.100')(props),
|
||||
fill: 'accent.100',
|
||||
},
|
||||
_disabled,
|
||||
_hover: {
|
||||
bg: mode('accent.300', 'accent.600')(props),
|
||||
color: mode('accent.900', 'accent.50')(props),
|
||||
bg: 'accent.600',
|
||||
color: 'accent.50',
|
||||
svg: {
|
||||
fill: mode('accent.900', 'accent.50')(props),
|
||||
fill: 'accent.50',
|
||||
},
|
||||
_disabled,
|
||||
},
|
||||
|
@ -3,7 +3,6 @@ import {
|
||||
createMultiStyleConfigHelpers,
|
||||
defineStyle,
|
||||
} from '@chakra-ui/styled-system';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { definePartsStyle, defineMultiStyleConfig } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
@ -13,31 +12,31 @@ const invokeAIControl = defineStyle((props) => {
|
||||
|
||||
return {
|
||||
_checked: {
|
||||
bg: mode(`${c}.500`, `${c}.200`)(props),
|
||||
borderColor: mode(`${c}.500`, `${c}.200`)(props),
|
||||
color: mode('white', 'base.900')(props),
|
||||
bg: `${c}.200`,
|
||||
borderColor: `${c}.200`,
|
||||
color: 'base.900',
|
||||
|
||||
_hover: {
|
||||
bg: mode(`${c}.600`, `${c}.300`)(props),
|
||||
borderColor: mode(`${c}.600`, `${c}.300`)(props),
|
||||
bg: `${c}.300`,
|
||||
borderColor: `${c}.300`,
|
||||
},
|
||||
|
||||
_disabled: {
|
||||
borderColor: mode('base.200', 'transparent')(props),
|
||||
bg: mode('base.200', 'whiteAlpha.300')(props),
|
||||
color: mode('base.500', 'whiteAlpha.500')(props),
|
||||
borderColor: 'transparent',
|
||||
bg: 'whiteAlpha.300',
|
||||
color: 'whiteAlpha.500',
|
||||
},
|
||||
},
|
||||
|
||||
_indeterminate: {
|
||||
bg: mode(`${c}.500`, `${c}.200`)(props),
|
||||
borderColor: mode(`${c}.500`, `${c}.200`)(props),
|
||||
color: mode('white', 'base.900')(props),
|
||||
bg: `${c}.200`,
|
||||
borderColor: `${c}.200`,
|
||||
color: 'base.900',
|
||||
},
|
||||
|
||||
_disabled: {
|
||||
bg: mode('base.100', 'whiteAlpha.100')(props),
|
||||
borderColor: mode('base.100', 'transparent')(props),
|
||||
bg: 'whiteAlpha.100',
|
||||
borderColor: 'transparent',
|
||||
},
|
||||
|
||||
_focusVisible: {
|
||||
@ -45,7 +44,7 @@ const invokeAIControl = defineStyle((props) => {
|
||||
},
|
||||
|
||||
_invalid: {
|
||||
borderColor: mode('red.500', 'red.300')(props),
|
||||
borderColor: 'red.300',
|
||||
},
|
||||
};
|
||||
});
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { defineStyle, defineStyleConfig } from '@chakra-ui/styled-system';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const invokeAI = defineStyle((props) => {
|
||||
const invokeAI = defineStyle((_props) => {
|
||||
return {
|
||||
fontSize: 'sm',
|
||||
marginEnd: 0,
|
||||
@ -13,7 +12,7 @@ const invokeAI = defineStyle((props) => {
|
||||
_disabled: {
|
||||
opacity: 0.4,
|
||||
},
|
||||
color: mode('base.600', 'base.300')(props),
|
||||
color: 'base.300',
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -3,7 +3,6 @@ import {
|
||||
createMultiStyleConfigHelpers,
|
||||
defineStyle,
|
||||
} from '@chakra-ui/styled-system';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { defineMultiStyleConfig, definePartsStyle } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
@ -14,18 +13,18 @@ const invokeAIOverlay = defineStyle({
|
||||
|
||||
const invokeAIDialogContainer = defineStyle({});
|
||||
|
||||
const invokeAIDialog = defineStyle((props) => {
|
||||
const invokeAIDialog = defineStyle((_props) => {
|
||||
return {
|
||||
bg: mode('base.300', 'base.850')(props),
|
||||
bg: 'base.850',
|
||||
maxH: '80vh',
|
||||
};
|
||||
});
|
||||
|
||||
const invokeAIHeader = defineStyle((props) => {
|
||||
const invokeAIHeader = defineStyle((_props) => {
|
||||
return {
|
||||
fontWeight: '600',
|
||||
fontSize: 'lg',
|
||||
color: mode('base.700', 'base.200')(props),
|
||||
color: 'base.200',
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -3,7 +3,7 @@ import {
|
||||
createMultiStyleConfigHelpers,
|
||||
defineStyle,
|
||||
} from '@chakra-ui/styled-system';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
import { getInputOutlineStyles } from '../util/getInputOutlineStyles';
|
||||
|
||||
const { defineMultiStyleConfig, definePartsStyle } =
|
||||
@ -33,7 +33,7 @@ const invokeAIStepperGroup = defineStyle((_props) => {
|
||||
};
|
||||
});
|
||||
|
||||
const invokeAIStepper = defineStyle((props) => {
|
||||
const invokeAIStepper = defineStyle((_props) => {
|
||||
return {
|
||||
border: 'none',
|
||||
// expand arrow hitbox
|
||||
@ -43,11 +43,11 @@ const invokeAIStepper = defineStyle((props) => {
|
||||
my: 0,
|
||||
|
||||
svg: {
|
||||
color: mode('base.600', 'base.300')(props),
|
||||
color: 'base.300',
|
||||
width: 2.5,
|
||||
height: 2.5,
|
||||
_hover: {
|
||||
color: mode('base.900', 'base.50')(props),
|
||||
color: 'base.50',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -4,7 +4,6 @@ import {
|
||||
defineStyle,
|
||||
} from '@chakra-ui/styled-system';
|
||||
import { cssVar } from '@chakra-ui/theme-tools';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { defineMultiStyleConfig, definePartsStyle } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
@ -13,7 +12,7 @@ const $popperBg = cssVar('popper-bg');
|
||||
const $arrowBg = cssVar('popper-arrow-bg');
|
||||
const $arrowShadowColor = cssVar('popper-arrow-shadow-color');
|
||||
|
||||
const invokeAIContent = defineStyle((props) => {
|
||||
const invokeAIContent = defineStyle((_props) => {
|
||||
return {
|
||||
[$arrowBg.variable]: `colors.base.800`,
|
||||
[$popperBg.variable]: `colors.base.800`,
|
||||
@ -23,8 +22,8 @@ const invokeAIContent = defineStyle((props) => {
|
||||
p: 4,
|
||||
borderWidth: '2px',
|
||||
borderStyle: 'solid',
|
||||
borderColor: mode('base.500', 'base.600')(props),
|
||||
bg: mode('base.200', 'base.800')(props),
|
||||
borderColor: 'base.600',
|
||||
bg: 'base.800',
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -3,25 +3,22 @@ import {
|
||||
createMultiStyleConfigHelpers,
|
||||
defineStyle,
|
||||
} from '@chakra-ui/styled-system';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { defineMultiStyleConfig, definePartsStyle } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
|
||||
const invokeAIFilledTrack = defineStyle((props) => ({
|
||||
bg: mode('accent.400', 'accent.600')(props),
|
||||
const invokeAIFilledTrack = defineStyle((_props) => ({
|
||||
bg: 'accent.600',
|
||||
transition: 'width 0.2s ease-in-out',
|
||||
_indeterminate: {
|
||||
bgGradient: `linear(to-r, transparent 0%, ${mode(
|
||||
'accent.400',
|
||||
'accent.600'
|
||||
)(props)} 50%, transparent 100%);`,
|
||||
bgGradient:
|
||||
'linear(to-r, transparent 0%, accent.600 50%, transparent 100%);',
|
||||
},
|
||||
}));
|
||||
|
||||
const invokeAITrack = defineStyle((props) => {
|
||||
const invokeAITrack = defineStyle((_props) => {
|
||||
return {
|
||||
bg: mode('base.300', 'base.800')(props),
|
||||
bg: 'base.800',
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -1,14 +1,13 @@
|
||||
import { selectAnatomy as parts } from '@chakra-ui/anatomy';
|
||||
import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react';
|
||||
import { getInputOutlineStyles } from '../util/getInputOutlineStyles';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { definePartsStyle, defineMultiStyleConfig } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
|
||||
const invokeAIIcon = defineStyle((props) => {
|
||||
const invokeAIIcon = defineStyle((_props) => {
|
||||
return {
|
||||
color: mode('base.600', 'base.300')(props),
|
||||
color: 'base.300',
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -1,13 +1,12 @@
|
||||
import { sliderAnatomy as parts } from '@chakra-ui/anatomy';
|
||||
import { createMultiStyleConfigHelpers, defineStyle } from '@chakra-ui/react';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { definePartsStyle, defineMultiStyleConfig } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
|
||||
const invokeAITrack = defineStyle((props) => {
|
||||
const invokeAITrack = defineStyle((_props) => {
|
||||
return {
|
||||
bg: mode('base.300', 'base.400')(props),
|
||||
bg: 'base.400',
|
||||
h: 1.5,
|
||||
};
|
||||
});
|
||||
@ -15,7 +14,7 @@ const invokeAITrack = defineStyle((props) => {
|
||||
const invokeAIFilledTrack = defineStyle((props) => {
|
||||
const { colorScheme: c } = props;
|
||||
return {
|
||||
bg: mode(`${c}.400`, `${c}.600`)(props),
|
||||
bg: `${c}.600`,
|
||||
h: 1.5,
|
||||
};
|
||||
});
|
||||
@ -27,11 +26,11 @@ const invokeAIThumb = defineStyle((_props) => {
|
||||
};
|
||||
});
|
||||
|
||||
const invokeAIMark = defineStyle((props) => {
|
||||
const invokeAIMark = defineStyle((_props) => {
|
||||
return {
|
||||
fontSize: 'xs',
|
||||
fontWeight: '500',
|
||||
color: mode('base.800', 'base.200')(props),
|
||||
color: 'base.200',
|
||||
mt: 2,
|
||||
insetInlineStart: 'unset',
|
||||
};
|
||||
|
@ -3,7 +3,6 @@ import {
|
||||
createMultiStyleConfigHelpers,
|
||||
defineStyle,
|
||||
} from '@chakra-ui/styled-system';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { defineMultiStyleConfig, definePartsStyle } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
@ -12,13 +11,13 @@ const invokeAITrack = defineStyle((props) => {
|
||||
const { colorScheme: c } = props;
|
||||
|
||||
return {
|
||||
bg: mode(`base.400`, `base.600`)(props),
|
||||
bg: 'base.600',
|
||||
|
||||
_focusVisible: {
|
||||
boxShadow: 'none',
|
||||
},
|
||||
_checked: {
|
||||
bg: mode(`${c}.400`, `${c}.600`)(props),
|
||||
bg: `${c}.600`,
|
||||
},
|
||||
};
|
||||
});
|
||||
@ -27,7 +26,7 @@ const invokeAIThumb = defineStyle((props) => {
|
||||
const { colorScheme: c } = props;
|
||||
|
||||
return {
|
||||
bg: mode(`${c}.50`, `${c}.50`)(props),
|
||||
bg: `${c}.50`,
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -3,7 +3,6 @@ import {
|
||||
createMultiStyleConfigHelpers,
|
||||
defineStyle,
|
||||
} from '@chakra-ui/styled-system';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const { defineMultiStyleConfig, definePartsStyle } =
|
||||
createMultiStyleConfigHelpers(parts.keys);
|
||||
@ -17,26 +16,26 @@ const invokeAIRoot = defineStyle((_props) => {
|
||||
|
||||
const invokeAITab = defineStyle((_props) => ({}));
|
||||
|
||||
const invokeAITablist = defineStyle((props) => ({
|
||||
const invokeAITablist = defineStyle((_props) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: 1,
|
||||
color: mode('base.500', 'base.700')(props),
|
||||
color: 'base.700',
|
||||
button: {
|
||||
fontSize: 'sm',
|
||||
padding: 2,
|
||||
borderRadius: 'base',
|
||||
_selected: {
|
||||
bg: mode('accent.200', 'accent.700')(props),
|
||||
color: mode('accent.800', 'accent.100')(props),
|
||||
bg: 'accent.700',
|
||||
color: 'accent.100',
|
||||
_hover: {
|
||||
bg: mode('accent.300', 'accent.600')(props),
|
||||
color: mode('accent.900', 'accent.50')(props),
|
||||
bg: 'accent.600',
|
||||
color: 'accent.50',
|
||||
},
|
||||
},
|
||||
_hover: {
|
||||
bg: mode('base.300', 'base.600')(props),
|
||||
color: mode('base.900', 'base.50')(props),
|
||||
bg: 'base.600',
|
||||
color: 'base.50',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { defineStyle, defineStyleConfig } from '@chakra-ui/react';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
const subtext = defineStyle((props) => ({
|
||||
color: mode('base.700', 'base.400')(props),
|
||||
const subtext = defineStyle((_props) => ({
|
||||
color: 'base.400',
|
||||
}));
|
||||
|
||||
export const textTheme = defineStyleConfig({
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { ThemeOverride } from '@chakra-ui/react';
|
||||
import type { StyleFunctionProps } from '@chakra-ui/styled-system';
|
||||
import { mode } from '@chakra-ui/theme-tools';
|
||||
|
||||
import { invokeAIThemeColors } from './colors/invokeAI';
|
||||
import { accordionTheme } from './components/accordion';
|
||||
import { buttonTheme } from './components/button';
|
||||
@ -22,15 +22,13 @@ import { textareaTheme } from './components/textarea';
|
||||
|
||||
export const theme: ThemeOverride = {
|
||||
config: {
|
||||
initialColorMode: 'dark',
|
||||
useSystemColorMode: false,
|
||||
cssVarPrefix: 'invokeai',
|
||||
},
|
||||
styles: {
|
||||
global: (props: StyleFunctionProps) => ({
|
||||
global: (_props: StyleFunctionProps) => ({
|
||||
body: {
|
||||
bg: mode('base.100', 'base.900')(props),
|
||||
color: mode('base.800', 'base.50')(props),
|
||||
bg: 'base.900',
|
||||
color: 'base.50',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
...scrollbar,
|
||||
|
@ -1,40 +1,40 @@
|
||||
import { mode, StyleFunctionProps } from '@chakra-ui/theme-tools';
|
||||
import { StyleFunctionProps } from '@chakra-ui/theme-tools';
|
||||
|
||||
export const getInputOutlineStyles = (props: StyleFunctionProps) => ({
|
||||
export const getInputOutlineStyles = (_props: StyleFunctionProps) => ({
|
||||
outline: 'none',
|
||||
borderWidth: 2,
|
||||
borderStyle: 'solid',
|
||||
borderColor: mode('base.300', 'base.800')(props),
|
||||
bg: mode('base.200', 'base.900')(props),
|
||||
borderColor: 'base.800',
|
||||
bg: 'base.900',
|
||||
borderRadius: 'base',
|
||||
color: mode('base.900', 'base.100')(props),
|
||||
color: 'base.100',
|
||||
boxShadow: 'none',
|
||||
_hover: {
|
||||
borderColor: mode('base.500', 'base.600')(props),
|
||||
borderColor: 'base.600',
|
||||
},
|
||||
_focus: {
|
||||
borderColor: mode('accent.600', 'accent.700')(props),
|
||||
borderColor: 'accent.700',
|
||||
boxShadow: 'none',
|
||||
_hover: {
|
||||
borderColor: mode('accent.700', 'accent.600')(props),
|
||||
borderColor: 'accent.600',
|
||||
},
|
||||
},
|
||||
_invalid: {
|
||||
borderColor: mode('error.300', 'error.700')(props),
|
||||
borderColor: 'error.700',
|
||||
boxShadow: 'none',
|
||||
_hover: {
|
||||
borderColor: mode('error.500', 'error.600')(props),
|
||||
borderColor: 'error.600',
|
||||
},
|
||||
},
|
||||
_disabled: {
|
||||
borderColor: mode('base.300', 'base.700')(props),
|
||||
bg: mode('base.400', 'base.700')(props),
|
||||
color: mode('base.600', 'base.400')(props),
|
||||
borderColor: 'base.700',
|
||||
bg: 'base.700',
|
||||
color: 'base.400',
|
||||
_hover: {
|
||||
borderColor: mode('base.300', 'base.700')(props),
|
||||
borderColor: 'base.700',
|
||||
},
|
||||
},
|
||||
_placeholder: {
|
||||
color: mode('base.600', 'base.400')(props),
|
||||
color: 'base.400',
|
||||
},
|
||||
});
|
||||
|
File diff suppressed because one or more lines are too long
@ -734,7 +734,7 @@
|
||||
"@chakra-ui/react-context" "2.0.7"
|
||||
"@chakra-ui/shared-utils" "2.0.5"
|
||||
|
||||
"@chakra-ui/styled-system@2.6.1":
|
||||
"@chakra-ui/styled-system@2.6.1", "@chakra-ui/styled-system@^2.6.1":
|
||||
version "2.6.1"
|
||||
resolved "https://registry.yarnpkg.com/@chakra-ui/styled-system/-/styled-system-2.6.1.tgz#302d496d34c0b7b30c646a7e3c9b113a2f4588da"
|
||||
integrity sha512-jy/1dVi1LxjoRCm+Eo5mqBgvPy5SCWMlIcz6GbIZBDpkGeKZwtqrZLjekxxLBCy8ORY+kJlUB0FT6AzVR/1tjw==
|
||||
@ -2107,6 +2107,21 @@ concat-map@0.0.1:
|
||||
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
|
||||
|
||||
concurrently@^7.6.0:
|
||||
version "7.6.0"
|
||||
resolved "https://registry.yarnpkg.com/concurrently/-/concurrently-7.6.0.tgz#531a6f5f30cf616f355a4afb8f8fcb2bba65a49a"
|
||||
integrity sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw==
|
||||
dependencies:
|
||||
chalk "^4.1.0"
|
||||
date-fns "^2.29.1"
|
||||
lodash "^4.17.21"
|
||||
rxjs "^7.0.0"
|
||||
shell-quote "^1.7.3"
|
||||
spawn-command "^0.0.2-1"
|
||||
supports-color "^8.1.0"
|
||||
tree-kill "^1.2.2"
|
||||
yargs "^17.3.1"
|
||||
|
||||
configstore@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96"
|
||||
@ -2191,6 +2206,11 @@ csstype@^3.0.11, csstype@^3.0.2:
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9"
|
||||
integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==
|
||||
|
||||
date-fns@^2.29.1:
|
||||
version "2.29.3"
|
||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8"
|
||||
integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==
|
||||
|
||||
dateformat@^5.0.3:
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-5.0.3.tgz#fe2223eff3cc70ce716931cb3038b59a9280696e"
|
||||
@ -4833,7 +4853,7 @@ run-parallel@^1.1.9:
|
||||
dependencies:
|
||||
queue-microtask "^1.2.2"
|
||||
|
||||
rxjs@^7.8.0:
|
||||
rxjs@^7.0.0, rxjs@^7.8.0:
|
||||
version "7.8.0"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.0.tgz#90a938862a82888ff4c7359811a595e14e1e09a4"
|
||||
integrity sha512-F2+gxDshqmIub1KdvZkaEfGDwLNpPvk9Fs6LD/MyQxNgMds/WH9OdDDXOmxUZpME+iSK3rQCctkL0DYyytUqMg==
|
||||
@ -4916,6 +4936,11 @@ shebang-regex@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
|
||||
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
|
||||
|
||||
shell-quote@^1.7.3:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.0.tgz#20d078d0eaf71d54f43bd2ba14a1b5b9bfa5c8ba"
|
||||
integrity sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ==
|
||||
|
||||
side-channel@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
|
||||
@ -5012,6 +5037,11 @@ source-map@^0.7.4:
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656"
|
||||
integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==
|
||||
|
||||
spawn-command@^0.0.2-1:
|
||||
version "0.0.2-1"
|
||||
resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0"
|
||||
integrity sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==
|
||||
|
||||
stream-to-array@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/stream-to-array/-/stream-to-array-2.3.0.tgz#bbf6b39f5f43ec30bc71babcb37557acecf34353"
|
||||
@ -5151,6 +5181,13 @@ supports-color@^7.1.0:
|
||||
dependencies:
|
||||
has-flag "^4.0.0"
|
||||
|
||||
supports-color@^8.1.0:
|
||||
version "8.1.1"
|
||||
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
|
||||
integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
|
||||
dependencies:
|
||||
has-flag "^4.0.0"
|
||||
|
||||
supports-preserve-symlinks-flag@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
|
||||
@ -5225,6 +5262,11 @@ tr46@~0.0.3:
|
||||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
||||
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
|
||||
|
||||
tree-kill@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc"
|
||||
integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==
|
||||
|
||||
ts-graphviz@^1.5.0:
|
||||
version "1.5.5"
|
||||
resolved "https://registry.yarnpkg.com/ts-graphviz/-/ts-graphviz-1.5.5.tgz#b5e9079c18289fb36b6b53f3d81da96445c37514"
|
||||
@ -5628,7 +5670,7 @@ yargs-parser@^21.1.1:
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
|
||||
integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
|
||||
|
||||
yargs@^17.5.1:
|
||||
yargs@^17.3.1, yargs@^17.5.1:
|
||||
version "17.7.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.1.tgz#34a77645201d1a8fc5213ace787c220eabbd0967"
|
||||
integrity sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==
|
||||
|
Loading…
Reference in New Issue
Block a user