diff --git a/invokeai/app/invocations/baseinvocation.py b/invokeai/app/invocations/baseinvocation.py index 4ce3e839b6..1bf9353368 100644 --- a/invokeai/app/invocations/baseinvocation.py +++ b/invokeai/app/invocations/baseinvocation.py @@ -97,6 +97,7 @@ class UIConfig(TypedDict, total=False): "latents", "model", "control", + "image_collection", ], ] tags: List[str] diff --git a/invokeai/app/invocations/collections.py b/invokeai/app/invocations/collections.py index 891f217317..33bde42d69 100644 --- a/invokeai/app/invocations/collections.py +++ b/invokeai/app/invocations/collections.py @@ -4,13 +4,16 @@ from typing import Literal import numpy as np from pydantic import Field, validator +from invokeai.app.models.image import ImageField from invokeai.app.util.misc import SEED_MAX, get_random_seed from .baseinvocation import ( BaseInvocation, + InvocationConfig, InvocationContext, BaseInvocationOutput, + UIConfig, ) @@ -22,6 +25,7 @@ class IntCollectionOutput(BaseInvocationOutput): # Outputs collection: list[int] = Field(default=[], description="The int collection") + class FloatCollectionOutput(BaseInvocationOutput): """A collection of floats""" @@ -31,6 +35,18 @@ class FloatCollectionOutput(BaseInvocationOutput): collection: list[float] = Field(default=[], description="The float collection") +class ImageCollectionOutput(BaseInvocationOutput): + """A collection of images""" + + type: Literal["image_collection"] = "image_collection" + + # Outputs + collection: list[ImageField] = Field(default=[], description="The output images") + + class Config: + schema_extra = {"required": ["type", "collection"]} + + class RangeInvocation(BaseInvocation): """Creates a range of numbers from start to stop with step""" @@ -92,3 +108,27 @@ class RandomRangeInvocation(BaseInvocation): return IntCollectionOutput( collection=list(rng.integers(low=self.low, high=self.high, size=self.size)) ) + + +class ImageCollectionInvocation(BaseInvocation): + """Load a collection of images and provide it as output.""" + + # fmt: off + type: Literal["image_collection"] = "image_collection" + + # Inputs + images: list[ImageField] = Field( + default=[], description="The image collection to load" + ) + # fmt: on + def invoke(self, context: InvocationContext) -> ImageCollectionOutput: + return ImageCollectionOutput(collection=self.images) + + class Config(InvocationConfig): + schema_extra = { + "ui": { + "type_hints": { + "images": "image_collection", + } + }, + } diff --git a/invokeai/backend/model_management/models/vae.py b/invokeai/backend/model_management/models/vae.py index b582f16b30..3f0d226687 100644 --- a/invokeai/backend/model_management/models/vae.py +++ b/invokeai/backend/model_management/models/vae.py @@ -137,7 +137,6 @@ def _convert_vae_ckpt_and_cache( from .stable_diffusion import _select_ckpt_config # all sd models use same vae settings config_file = _select_ckpt_config(base_model, ModelVariantType.Normal) - else: raise Exception(f"Vae conversion not supported for model type: {base_model}") @@ -152,7 +151,7 @@ def _convert_vae_ckpt_and_cache( if "state_dict" in checkpoint: checkpoint = checkpoint["state_dict"] - config = OmegaConf.load(config_file) + config = OmegaConf.load(app_config.root_path/config_file) vae_model = convert_ldm_vae_to_diffusers( checkpoint = checkpoint, diff --git a/invokeai/frontend/web/.eslintrc.js b/invokeai/frontend/web/.eslintrc.js index b1a2b6a7e4..34db9d466b 100644 --- a/invokeai/frontend/web/.eslintrc.js +++ b/invokeai/frontend/web/.eslintrc.js @@ -36,6 +36,12 @@ module.exports = { ], 'prettier/prettier': ['error', { endOfLine: 'auto' }], '@typescript-eslint/ban-ts-comment': 'warn', + '@typescript-eslint/no-empty-interface': [ + 'error', + { + allowSingleExtends: true, + }, + ], }, settings: { react: { diff --git a/invokeai/frontend/web/config/common.ts b/invokeai/frontend/web/config/common.ts index 2dce54e70a..4470224225 100644 --- a/invokeai/frontend/web/config/common.ts +++ b/invokeai/frontend/web/config/common.ts @@ -3,12 +3,10 @@ import { visualizer } from 'rollup-plugin-visualizer'; import { PluginOption, UserConfig } from 'vite'; import eslint from 'vite-plugin-eslint'; import tsconfigPaths from 'vite-tsconfig-paths'; -import { nodePolyfills } from 'vite-plugin-node-polyfills'; export const commonPlugins: UserConfig['plugins'] = [ react(), eslint(), tsconfigPaths(), visualizer() as unknown as PluginOption, - nodePolyfills(), ]; diff --git a/invokeai/frontend/web/package.json b/invokeai/frontend/web/package.json index 8c66222584..19cd5e935b 100644 --- a/invokeai/frontend/web/package.json +++ b/invokeai/frontend/web/package.json @@ -53,7 +53,6 @@ ] }, "dependencies": { - "@apidevtools/swagger-parser": "^10.1.0", "@chakra-ui/anatomy": "^2.1.1", "@chakra-ui/icons": "^2.0.19", "@chakra-ui/react": "^2.7.1", @@ -83,7 +82,7 @@ "konva": "^9.2.0", "lodash-es": "^4.17.21", "nanostores": "^0.9.2", - "openapi-fetch": "^0.4.0", + "openapi-fetch": "0.4.0", "overlayscrollbars": "^2.2.0", "overlayscrollbars-react": "^0.5.0", "patch-package": "^7.0.0", @@ -155,7 +154,6 @@ "vite-plugin-css-injected-by-js": "^3.1.1", "vite-plugin-dts": "^2.3.0", "vite-plugin-eslint": "^1.8.1", - "vite-plugin-node-polyfills": "^0.9.0", "vite-tsconfig-paths": "^4.2.0", "yarn": "^1.22.19" } diff --git a/invokeai/frontend/web/public/locales/en.json b/invokeai/frontend/web/public/locales/en.json index b69e3b82af..ab5d536f0c 100644 --- a/invokeai/frontend/web/public/locales/en.json +++ b/invokeai/frontend/web/public/locales/en.json @@ -24,16 +24,13 @@ }, "common": { "hotkeysLabel": "Hotkeys", - "themeLabel": "Theme", + "darkMode": "Dark Mode", + "lightMode": "Light Mode", "languagePickerLabel": "Language", "reportBugLabel": "Report Bug", "githubLabel": "Github", "discordLabel": "Discord", "settingsLabel": "Settings", - "darkTheme": "Dark", - "lightTheme": "Light", - "greenTheme": "Green", - "oceanTheme": "Ocean", "langArabic": "العربية", "langEnglish": "English", "langDutch": "Nederlands", @@ -55,6 +52,7 @@ "unifiedCanvas": "Unified Canvas", "linear": "Linear", "nodes": "Node Editor", + "batch": "Batch Manager", "postprocessing": "Post Processing", "nodesDesc": "A node based system for the generation of images is under development currently. Stay tuned for updates about this amazing feature.", "postProcessing": "Post Processing", diff --git a/invokeai/frontend/web/src/app/components/App.tsx b/invokeai/frontend/web/src/app/components/App.tsx index 5b3cf5925f..2b0e247d48 100644 --- a/invokeai/frontend/web/src/app/components/App.tsx +++ b/invokeai/frontend/web/src/app/components/App.tsx @@ -1,67 +1,40 @@ -import { Box, Flex, Grid, Portal } from '@chakra-ui/react'; +import { Flex, Grid, Portal } from '@chakra-ui/react'; import { useLogger } from 'app/logging/useLogger'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { PartialAppConfig } from 'app/types/invokeai'; import ImageUploader from 'common/components/ImageUploader'; -import Loading from 'common/components/Loading/Loading'; import GalleryDrawer from 'features/gallery/components/GalleryPanel'; import Lightbox from 'features/lightbox/components/Lightbox'; import SiteHeader from 'features/system/components/SiteHeader'; import { useFeatureStatus } from 'features/system/hooks/useFeatureStatus'; -import { useIsApplicationReady } from 'features/system/hooks/useIsApplicationReady'; import { configChanged } from 'features/system/store/configSlice'; import { languageSelector } from 'features/system/store/systemSelectors'; import FloatingGalleryButton from 'features/ui/components/FloatingGalleryButton'; import FloatingParametersPanelButtons from 'features/ui/components/FloatingParametersPanelButtons'; import InvokeTabs from 'features/ui/components/InvokeTabs'; import ParametersDrawer from 'features/ui/components/ParametersDrawer'; -import { AnimatePresence, motion } from 'framer-motion'; import i18n from 'i18n'; -import { ReactNode, memo, useCallback, useEffect, useState } from 'react'; -import { APP_HEIGHT, APP_WIDTH } from 'theme/util/constants'; +import { ReactNode, memo, useEffect } from 'react'; import GlobalHotkeys from './GlobalHotkeys'; import Toaster from './Toaster'; -import DeleteImageModal from 'features/gallery/components/DeleteImageModal'; -import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; import UpdateImageBoardModal from '../../features/gallery/components/Boards/UpdateImageBoardModal'; -import { useListModelsQuery } from 'services/api/endpoints/models'; import DeleteBoardImagesModal from '../../features/gallery/components/Boards/DeleteBoardImagesModal'; +import DeleteImageModal from 'features/imageDeletion/components/DeleteImageModal'; const DEFAULT_CONFIG = {}; interface Props { config?: PartialAppConfig; headerComponent?: ReactNode; - setIsReady?: (isReady: boolean) => void; } -const App = ({ - config = DEFAULT_CONFIG, - headerComponent, - setIsReady, -}: Props) => { +const App = ({ config = DEFAULT_CONFIG, headerComponent }: Props) => { const language = useAppSelector(languageSelector); const log = useLogger(); const isLightboxEnabled = useFeatureStatus('lightbox').isFeatureEnabled; - const isApplicationReady = useIsApplicationReady(); - - const { data: pipelineModels } = useListModelsQuery({ - model_type: 'main', - }); - const { data: controlnetModels } = useListModelsQuery({ - model_type: 'controlnet', - }); - const { data: vaeModels } = useListModelsQuery({ model_type: 'vae' }); - const { data: loraModels } = useListModelsQuery({ model_type: 'lora' }); - const { data: embeddingModels } = useListModelsQuery({ - model_type: 'embedding', - }); - - const [loadingOverridden, setLoadingOverridden] = useState(false); - const dispatch = useAppDispatch(); useEffect(() => { @@ -73,27 +46,6 @@ const App = ({ dispatch(configChanged(config)); }, [dispatch, config, log]); - const handleOverrideClicked = useCallback(() => { - setLoadingOverridden(true); - }, []); - - useEffect(() => { - if (isApplicationReady && setIsReady) { - setIsReady(true); - } - - if (isApplicationReady) { - // TODO: This is a jank fix for canvas not filling the screen on first load - setTimeout(() => { - dispatch(requestCanvasRescale()); - }, 200); - } - - return () => { - setIsReady && setIsReady(false); - }; - }, [dispatch, isApplicationReady, setIsReady]); - return ( <> @@ -123,33 +75,6 @@ const App = ({ - - - {!isApplicationReady && !loadingOverridden && ( - - - - - - - )} - - diff --git a/invokeai/frontend/web/src/app/components/ImageDnd/DragPreview.tsx b/invokeai/frontend/web/src/app/components/ImageDnd/DragPreview.tsx new file mode 100644 index 0000000000..5b6142d748 --- /dev/null +++ b/invokeai/frontend/web/src/app/components/ImageDnd/DragPreview.tsx @@ -0,0 +1,82 @@ +import { Box, ChakraProps, Flex, Heading, Image } from '@chakra-ui/react'; +import { memo } from 'react'; +import { TypesafeDraggableData } from './typesafeDnd'; + +type OverlayDragImageProps = { + dragData: TypesafeDraggableData | null; +}; + +const BOX_SIZE = 28; + +const STYLES: ChakraProps['sx'] = { + w: BOX_SIZE, + h: BOX_SIZE, + maxW: BOX_SIZE, + maxH: BOX_SIZE, + shadow: 'dark-lg', + borderRadius: 'lg', + borderWidth: 2, + borderStyle: 'dashed', + borderColor: 'base.100', + opacity: 0.5, + bg: 'base.800', + color: 'base.50', + _dark: { + borderColor: 'base.200', + bg: 'base.900', + color: 'base.100', + }, +}; + +const DragPreview = (props: OverlayDragImageProps) => { + if (!props.dragData) { + return; + } + + if (props.dragData.payloadType === 'IMAGE_DTO') { + return ( + + + + ); + } + + if (props.dragData.payloadType === 'IMAGE_NAMES') { + return ( + + {props.dragData.payload.imageNames.length} + Images + + ); + } + + return null; +}; + +export default memo(DragPreview); diff --git a/invokeai/frontend/web/src/app/components/ImageDnd/ImageDndContext.tsx b/invokeai/frontend/web/src/app/components/ImageDnd/ImageDndContext.tsx index 6150259f66..1b8687bf8e 100644 --- a/invokeai/frontend/web/src/app/components/ImageDnd/ImageDndContext.tsx +++ b/invokeai/frontend/web/src/app/components/ImageDnd/ImageDndContext.tsx @@ -1,8 +1,5 @@ import { - DndContext, - DragEndEvent, DragOverlay, - DragStartEvent, MouseSensor, TouchSensor, pointerWithin, @@ -10,33 +7,45 @@ import { useSensors, } from '@dnd-kit/core'; import { PropsWithChildren, memo, useCallback, useState } from 'react'; -import OverlayDragImage from './OverlayDragImage'; -import { ImageDTO } from 'services/api/types'; -import { isImageDTO } from 'services/api/guards'; +import DragPreview from './DragPreview'; import { snapCenterToCursor } from '@dnd-kit/modifiers'; import { AnimatePresence, motion } from 'framer-motion'; +import { + DndContext, + DragEndEvent, + DragStartEvent, + TypesafeDraggableData, +} from './typesafeDnd'; +import { useAppDispatch } from 'app/store/storeHooks'; +import { imageDropped } from 'app/store/middleware/listenerMiddleware/listeners/imageDropped'; type ImageDndContextProps = PropsWithChildren; const ImageDndContext = (props: ImageDndContextProps) => { - const [draggedImage, setDraggedImage] = useState(null); + const [activeDragData, setActiveDragData] = + useState(null); + + const dispatch = useAppDispatch(); const handleDragStart = useCallback((event: DragStartEvent) => { - const dragData = event.active.data.current; - if (dragData && 'image' in dragData && isImageDTO(dragData.image)) { - setDraggedImage(dragData.image); + const activeData = event.active.data.current; + if (!activeData) { + return; } + setActiveDragData(activeData); }, []); const handleDragEnd = useCallback( (event: DragEndEvent) => { - const handleDrop = event.over?.data.current?.handleDrop; - if (handleDrop && typeof handleDrop === 'function' && draggedImage) { - handleDrop(draggedImage); + const activeData = event.active.data.current; + const overData = event.over?.data.current; + if (!activeData || !overData) { + return; } - setDraggedImage(null); + dispatch(imageDropped({ overData, activeData })); + setActiveDragData(null); }, - [draggedImage] + [dispatch] ); const mouseSensor = useSensor(MouseSensor, { @@ -46,6 +55,7 @@ const ImageDndContext = (props: ImageDndContextProps) => { const touchSensor = useSensor(TouchSensor, { activationConstraint: { delay: 150, tolerance: 5 }, }); + // TODO: Use KeyboardSensor - needs composition of multiple collisionDetection algos // Alternatively, fix `rectIntersection` collection detection to work with the drag overlay // (currently the drag element collision rect is not correctly calculated) @@ -63,7 +73,7 @@ const ImageDndContext = (props: ImageDndContextProps) => { {props.children} - {draggedImage && ( + {activeDragData && ( { transition: { duration: 0.1 }, }} > - + )} diff --git a/invokeai/frontend/web/src/app/components/ImageDnd/OverlayDragImage.tsx b/invokeai/frontend/web/src/app/components/ImageDnd/OverlayDragImage.tsx deleted file mode 100644 index 611d1ceee9..0000000000 --- a/invokeai/frontend/web/src/app/components/ImageDnd/OverlayDragImage.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { Box, Image } from '@chakra-ui/react'; -import { memo } from 'react'; -import { ImageDTO } from 'services/api/types'; - -type OverlayDragImageProps = { - image: ImageDTO; -}; - -const OverlayDragImage = (props: OverlayDragImageProps) => { - return ( - - - - ); -}; - -export default memo(OverlayDragImage); diff --git a/invokeai/frontend/web/src/app/components/ImageDnd/typesafeDnd.tsx b/invokeai/frontend/web/src/app/components/ImageDnd/typesafeDnd.tsx new file mode 100644 index 0000000000..e744a70750 --- /dev/null +++ b/invokeai/frontend/web/src/app/components/ImageDnd/typesafeDnd.tsx @@ -0,0 +1,195 @@ +// type-safe dnd from https://github.com/clauderic/dnd-kit/issues/935 +import { + Active, + Collision, + DndContextProps, + DndContext as OriginalDndContext, + Over, + Translate, + UseDraggableArguments, + UseDroppableArguments, + useDraggable as useOriginalDraggable, + useDroppable as useOriginalDroppable, +} from '@dnd-kit/core'; +import { ImageDTO } from 'services/api/types'; + +type BaseDropData = { + id: string; +}; + +export type CurrentImageDropData = BaseDropData & { + actionType: 'SET_CURRENT_IMAGE'; +}; + +export type InitialImageDropData = BaseDropData & { + actionType: 'SET_INITIAL_IMAGE'; +}; + +export type ControlNetDropData = BaseDropData & { + actionType: 'SET_CONTROLNET_IMAGE'; + context: { + controlNetId: string; + }; +}; + +export type CanvasInitialImageDropData = BaseDropData & { + actionType: 'SET_CANVAS_INITIAL_IMAGE'; +}; + +export type NodesImageDropData = BaseDropData & { + actionType: 'SET_NODES_IMAGE'; + context: { + nodeId: string; + fieldName: string; + }; +}; + +export type NodesMultiImageDropData = BaseDropData & { + actionType: 'SET_MULTI_NODES_IMAGE'; + context: { nodeId: string; fieldName: string }; +}; + +export type AddToBatchDropData = BaseDropData & { + actionType: 'ADD_TO_BATCH'; +}; + +export type MoveBoardDropData = BaseDropData & { + actionType: 'MOVE_BOARD'; + context: { boardId: string | null }; +}; + +export type TypesafeDroppableData = + | CurrentImageDropData + | InitialImageDropData + | ControlNetDropData + | CanvasInitialImageDropData + | NodesImageDropData + | AddToBatchDropData + | NodesMultiImageDropData + | MoveBoardDropData; + +type BaseDragData = { + id: string; +}; + +export type ImageDraggableData = BaseDragData & { + payloadType: 'IMAGE_DTO'; + payload: { imageDTO: ImageDTO }; +}; + +export type ImageNamesDraggableData = BaseDragData & { + payloadType: 'IMAGE_NAMES'; + payload: { imageNames: string[] }; +}; + +export type TypesafeDraggableData = + | ImageDraggableData + | ImageNamesDraggableData; + +interface UseDroppableTypesafeArguments + extends Omit { + data?: TypesafeDroppableData; +} + +type UseDroppableTypesafeReturnValue = Omit< + ReturnType, + 'active' | 'over' +> & { + active: TypesafeActive | null; + over: TypesafeOver | null; +}; + +export function useDroppable(props: UseDroppableTypesafeArguments) { + return useOriginalDroppable(props) as UseDroppableTypesafeReturnValue; +} + +interface UseDraggableTypesafeArguments + extends Omit { + data?: TypesafeDraggableData; +} + +type UseDraggableTypesafeReturnValue = Omit< + ReturnType, + 'active' | 'over' +> & { + active: TypesafeActive | null; + over: TypesafeOver | null; +}; + +export function useDraggable(props: UseDraggableTypesafeArguments) { + return useOriginalDraggable(props) as UseDraggableTypesafeReturnValue; +} + +interface TypesafeActive extends Omit { + data: React.MutableRefObject; +} + +interface TypesafeOver extends Omit { + data: React.MutableRefObject; +} + +export const isValidDrop = ( + overData: TypesafeDroppableData | undefined, + active: TypesafeActive | null +) => { + if (!overData || !active?.data.current) { + return false; + } + + const { actionType } = overData; + const { payloadType } = active.data.current; + + if (overData.id === active.data.current.id) { + return false; + } + + switch (actionType) { + case 'SET_CURRENT_IMAGE': + return payloadType === 'IMAGE_DTO'; + case 'SET_INITIAL_IMAGE': + return payloadType === 'IMAGE_DTO'; + case 'SET_CONTROLNET_IMAGE': + return payloadType === 'IMAGE_DTO'; + case 'SET_CANVAS_INITIAL_IMAGE': + return payloadType === 'IMAGE_DTO'; + case 'SET_NODES_IMAGE': + return payloadType === 'IMAGE_DTO'; + case 'SET_MULTI_NODES_IMAGE': + return payloadType === 'IMAGE_DTO' || 'IMAGE_NAMES'; + case 'ADD_TO_BATCH': + return payloadType === 'IMAGE_DTO' || 'IMAGE_NAMES'; + case 'MOVE_BOARD': + return payloadType === 'IMAGE_DTO' || 'IMAGE_NAMES'; + default: + return false; + } +}; + +interface DragEvent { + activatorEvent: Event; + active: TypesafeActive; + collisions: Collision[] | null; + delta: Translate; + over: TypesafeOver | null; +} + +export interface DragStartEvent extends Pick {} +export interface DragMoveEvent extends DragEvent {} +export interface DragOverEvent extends DragMoveEvent {} +export interface DragEndEvent extends DragEvent {} +export interface DragCancelEvent extends DragEndEvent {} + +export interface DndContextTypesafeProps + extends Omit< + DndContextProps, + 'onDragStart' | 'onDragMove' | 'onDragOver' | 'onDragEnd' | 'onDragCancel' + > { + onDragStart?(event: DragStartEvent): void; + onDragMove?(event: DragMoveEvent): void; + onDragOver?(event: DragOverEvent): void; + onDragEnd?(event: DragEndEvent): void; + onDragCancel?(event: DragCancelEvent): void; +} +export function DndContext(props: DndContextTypesafeProps) { + return ; +} diff --git a/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx b/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx index 7259f6105d..105f8f18d7 100644 --- a/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx +++ b/invokeai/frontend/web/src/app/components/InvokeAIUI.tsx @@ -7,7 +7,6 @@ import React, { } from 'react'; import { Provider } from 'react-redux'; import { store } from 'app/store/store'; -// import { OpenAPI } from 'services/api/types'; import Loading from '../../common/components/Loading/Loading'; import { addMiddleware, resetMiddlewares } from 'redux-dynamic-middlewares'; @@ -17,11 +16,6 @@ import '../../i18n'; import { socketMiddleware } from 'services/events/middleware'; import { Middleware } from '@reduxjs/toolkit'; import ImageDndContext from './ImageDnd/ImageDndContext'; -import { - DeleteImageContext, - DeleteImageContextProvider, -} from 'app/contexts/DeleteImageContext'; -import UpdateImageBoardModal from '../../features/gallery/components/Boards/UpdateImageBoardModal'; import { AddImageToBoardContextProvider } from '../contexts/AddImageToBoardContext'; import { $authToken, $baseUrl } from 'services/api/client'; import { DeleteBoardImagesContextProvider } from '../contexts/DeleteBoardImagesContext'; @@ -34,7 +28,6 @@ interface Props extends PropsWithChildren { token?: string; config?: PartialAppConfig; headerComponent?: ReactNode; - setIsReady?: (isReady: boolean) => void; middleware?: Middleware[]; } @@ -43,7 +36,6 @@ const InvokeAIUI = ({ token, config, headerComponent, - setIsReady, middleware, }: Props) => { useEffect(() => { @@ -85,17 +77,11 @@ const InvokeAIUI = ({ }> - - - - - - - + + + + + diff --git a/invokeai/frontend/web/src/app/components/ThemeLocaleProvider.tsx b/invokeai/frontend/web/src/app/components/ThemeLocaleProvider.tsx index 5eea4bb940..1e86e0ce1b 100644 --- a/invokeai/frontend/web/src/app/components/ThemeLocaleProvider.tsx +++ b/invokeai/frontend/web/src/app/components/ThemeLocaleProvider.tsx @@ -3,17 +3,10 @@ import { createLocalStorageManager, extendTheme, } from '@chakra-ui/react'; -import { RootState } from 'app/store/store'; -import { useAppSelector } from 'app/store/storeHooks'; -import { ReactNode, useEffect } from 'react'; +import { ReactNode, useEffect, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import { theme as invokeAITheme } from 'theme/theme'; -import { greenTeaThemeColors } from 'theme/colors/greenTea'; -import { invokeAIThemeColors } from 'theme/colors/invokeAI'; -import { lightThemeColors } from 'theme/colors/lightTheme'; -import { oceanBlueColors } from 'theme/colors/oceanBlue'; - import '@fontsource-variable/inter'; import { MantineProvider } from '@mantine/core'; import { mantineTheme } from 'mantine-theme/theme'; @@ -24,29 +17,19 @@ type ThemeLocaleProviderProps = { children: ReactNode; }; -const THEMES = { - dark: invokeAIThemeColors, - light: lightThemeColors, - green: greenTeaThemeColors, - ocean: oceanBlueColors, -}; - const manager = createLocalStorageManager('@@invokeai-color-mode'); function ThemeLocaleProvider({ children }: ThemeLocaleProviderProps) { const { i18n } = useTranslation(); - const currentTheme = useAppSelector( - (state: RootState) => state.ui.currentTheme - ); - const direction = i18n.dir(); - const theme = extendTheme({ - ...invokeAITheme, - colors: THEMES[currentTheme as keyof typeof THEMES], - direction, - }); + const theme = useMemo(() => { + return extendTheme({ + ...invokeAITheme, + direction, + }); + }, [direction]); useEffect(() => { document.body.dir = direction; diff --git a/invokeai/frontend/web/src/app/contexts/DeleteBoardImagesContext.tsx b/invokeai/frontend/web/src/app/contexts/DeleteBoardImagesContext.tsx index 38c89bfcf9..15f9fab282 100644 --- a/invokeai/frontend/web/src/app/contexts/DeleteBoardImagesContext.tsx +++ b/invokeai/frontend/web/src/app/contexts/DeleteBoardImagesContext.tsx @@ -5,15 +5,15 @@ import { useDeleteBoardMutation } from '../../services/api/endpoints/boards'; import { defaultSelectorOptions } from '../store/util/defaultMemoizeOptions'; import { createSelector } from '@reduxjs/toolkit'; import { some } from 'lodash-es'; -import { canvasSelector } from '../../features/canvas/store/canvasSelectors'; -import { controlNetSelector } from '../../features/controlNet/store/controlNetSlice'; -import { selectImagesById } from '../../features/gallery/store/imagesSlice'; -import { nodesSelector } from '../../features/nodes/store/nodesSlice'; -import { generationSelector } from '../../features/parameters/store/generationSelectors'; +import { canvasSelector } from 'features/canvas/store/canvasSelectors'; +import { controlNetSelector } from 'features/controlNet/store/controlNetSlice'; +import { selectImagesById } from 'features/gallery/store/gallerySlice'; +import { nodesSelector } from 'features/nodes/store/nodesSlice'; +import { generationSelector } from 'features/parameters/store/generationSelectors'; import { RootState } from '../store/store'; import { useAppDispatch, useAppSelector } from '../store/storeHooks'; import { ImageUsage } from './DeleteImageContext'; -import { requestedBoardImagesDeletion } from '../../features/gallery/store/actions'; +import { requestedBoardImagesDeletion } from 'features/gallery/store/actions'; export const selectBoardImagesUsage = createSelector( [ diff --git a/invokeai/frontend/web/src/app/contexts/DeleteImageContext.tsx b/invokeai/frontend/web/src/app/contexts/DeleteImageContext.tsx deleted file mode 100644 index 6f4af7608f..0000000000 --- a/invokeai/frontend/web/src/app/contexts/DeleteImageContext.tsx +++ /dev/null @@ -1,201 +0,0 @@ -import { useDisclosure } from '@chakra-ui/react'; -import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; -import { requestedImageDeletion } from 'features/gallery/store/actions'; -import { systemSelector } from 'features/system/store/systemSelectors'; -import { - PropsWithChildren, - createContext, - useCallback, - useEffect, - useState, -} from 'react'; -import { ImageDTO } from 'services/api/types'; -import { RootState } from 'app/store/store'; -import { canvasSelector } from 'features/canvas/store/canvasSelectors'; -import { controlNetSelector } from 'features/controlNet/store/controlNetSlice'; -import { nodesSelector } from 'features/nodes/store/nodesSlice'; -import { generationSelector } from 'features/parameters/store/generationSelectors'; -import { some } from 'lodash-es'; - -export type ImageUsage = { - isInitialImage: boolean; - isCanvasImage: boolean; - isNodesImage: boolean; - isControlNetImage: boolean; -}; - -export const selectImageUsage = createSelector( - [ - generationSelector, - canvasSelector, - nodesSelector, - controlNetSelector, - (state: RootState, image_name?: string) => image_name, - ], - (generation, canvas, nodes, controlNet, image_name) => { - const isInitialImage = generation.initialImage?.imageName === image_name; - - const isCanvasImage = canvas.layerState.objects.some( - (obj) => obj.kind === 'image' && obj.imageName === image_name - ); - - const isNodesImage = nodes.nodes.some((node) => { - return some( - node.data.inputs, - (input) => input.type === 'image' && input.value === image_name - ); - }); - - const isControlNetImage = some( - controlNet.controlNets, - (c) => - c.controlImage === image_name || c.processedControlImage === image_name - ); - - const imageUsage: ImageUsage = { - isInitialImage, - isCanvasImage, - isNodesImage, - isControlNetImage, - }; - - return imageUsage; - }, - defaultSelectorOptions -); - -type DeleteImageContextValue = { - /** - * Whether the delete image dialog is open. - */ - isOpen: boolean; - /** - * Closes the delete image dialog. - */ - onClose: () => void; - /** - * Opens the delete image dialog and handles all deletion-related checks. - */ - onDelete: (image?: ImageDTO) => void; - /** - * The image pending deletion - */ - image?: ImageDTO; - /** - * The features in which this image is used - */ - imageUsage?: ImageUsage; - /** - * Immediately deletes an image. - * - * You probably don't want to use this - use `onDelete` instead. - */ - onImmediatelyDelete: () => void; -}; - -export const DeleteImageContext = createContext({ - isOpen: false, - onClose: () => undefined, - onImmediatelyDelete: () => undefined, - onDelete: () => undefined, -}); - -const selector = createSelector( - [systemSelector], - (system) => { - const { isProcessing, isConnected, shouldConfirmOnDelete } = system; - - return { - canDeleteImage: isConnected && !isProcessing, - shouldConfirmOnDelete, - }; - }, - defaultSelectorOptions -); - -type Props = PropsWithChildren; - -export const DeleteImageContextProvider = (props: Props) => { - const { canDeleteImage, shouldConfirmOnDelete } = useAppSelector(selector); - const [imageToDelete, setImageToDelete] = useState(); - const dispatch = useAppDispatch(); - const { isOpen, onOpen, onClose } = useDisclosure(); - - // Check where the image to be deleted is used (eg init image, controlnet, etc.) - const imageUsage = useAppSelector((state) => - selectImageUsage(state, imageToDelete?.image_name) - ); - - // Clean up after deleting or dismissing the modal - const closeAndClearImageToDelete = useCallback(() => { - setImageToDelete(undefined); - onClose(); - }, [onClose]); - - // Dispatch the actual deletion action, to be handled by listener middleware - const handleActualDeletion = useCallback( - (image: ImageDTO) => { - dispatch(requestedImageDeletion({ image, imageUsage })); - closeAndClearImageToDelete(); - }, - [closeAndClearImageToDelete, dispatch, imageUsage] - ); - - // This is intended to be called by the delete button in the dialog - const onImmediatelyDelete = useCallback(() => { - if (canDeleteImage && imageToDelete) { - handleActualDeletion(imageToDelete); - } - closeAndClearImageToDelete(); - }, [ - canDeleteImage, - imageToDelete, - closeAndClearImageToDelete, - handleActualDeletion, - ]); - - const handleGatedDeletion = useCallback( - (image: ImageDTO) => { - if (shouldConfirmOnDelete || some(imageUsage)) { - // If we should confirm on delete, or if the image is in use, open the dialog - onOpen(); - } else { - handleActualDeletion(image); - } - }, - [imageUsage, shouldConfirmOnDelete, onOpen, handleActualDeletion] - ); - - // Consumers of the context call this to delete an image - const onDelete = useCallback((image?: ImageDTO) => { - if (!image) { - return; - } - // Set the image to delete, then let the effect call the actual deletion - setImageToDelete(image); - }, []); - - useEffect(() => { - // We need to use an effect here to trigger the image usage selector, else we get a stale value - if (imageToDelete) { - handleGatedDeletion(imageToDelete); - } - }, [handleGatedDeletion, imageToDelete]); - - return ( - - {props.children} - - ); -}; diff --git a/invokeai/frontend/web/src/app/store/enhancers/reduxRemember/unserialize.ts b/invokeai/frontend/web/src/app/store/enhancers/reduxRemember/unserialize.ts index 8f40b0bb59..23e6448987 100644 --- a/invokeai/frontend/web/src/app/store/enhancers/reduxRemember/unserialize.ts +++ b/invokeai/frontend/web/src/app/store/enhancers/reduxRemember/unserialize.ts @@ -1,7 +1,6 @@ import { initialCanvasState } from 'features/canvas/store/canvasSlice'; import { initialControlNetState } from 'features/controlNet/store/controlNetSlice'; import { initialGalleryState } from 'features/gallery/store/gallerySlice'; -import { initialImagesState } from 'features/gallery/store/imagesSlice'; import { initialLightboxState } from 'features/lightbox/store/lightboxSlice'; import { initialNodesState } from 'features/nodes/store/nodesSlice'; import { initialGenerationState } from 'features/parameters/store/generationSlice'; @@ -26,7 +25,6 @@ const initialStates: { config: initialConfigState, ui: initialUIState, hotkeys: initialHotkeysState, - images: initialImagesState, controlNet: initialControlNetState, }; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/index.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/index.ts index a36141fafc..900fabfee9 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/index.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/index.ts @@ -72,7 +72,6 @@ import { addCommitStagingAreaImageListener } from './listeners/addCommitStagingA import { addImageCategoriesChangedListener } from './listeners/imageCategoriesChanged'; import { addControlNetImageProcessedListener } from './listeners/controlNetImageProcessed'; import { addControlNetAutoProcessListener } from './listeners/controlNetAutoProcess'; -import { addUpdateImageUrlsOnConnectListener } from './listeners/updateImageUrlsOnConnect'; import { addImageAddedToBoardFulfilledListener, addImageAddedToBoardRejectedListener, @@ -84,6 +83,9 @@ import { } from './listeners/imageRemovedFromBoard'; import { addReceivedOpenAPISchemaListener } from './listeners/receivedOpenAPISchema'; import { addRequestedBoardImageDeletionListener } from './listeners/boardImagesDeleted'; +import { addSelectionAddedToBatchListener } from './listeners/selectionAddedToBatch'; +import { addImageDroppedListener } from './listeners/imageDropped'; +import { addImageToDeleteSelectedListener } from './listeners/imageToDeleteSelected'; export const listenerMiddleware = createListenerMiddleware(); @@ -126,6 +128,7 @@ addImageDeletedPendingListener(); addImageDeletedFulfilledListener(); addImageDeletedRejectedListener(); addRequestedBoardImageDeletionListener(); +addImageToDeleteSelectedListener(); // Image metadata addImageMetadataReceivedFulfilledListener(); @@ -211,3 +214,9 @@ addBoardIdSelectedListener(); // Node schemas addReceivedOpenAPISchemaListener(); + +// Batches +addSelectionAddedToBatchListener(); + +// DND +addImageDroppedListener(); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardIdSelected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardIdSelected.ts index 1c96c5700d..6ce6665cc5 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardIdSelected.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardIdSelected.ts @@ -1,12 +1,14 @@ import { log } from 'app/logging/useLogger'; import { startAppListening } from '..'; -import { boardIdSelected } from 'features/gallery/store/boardSlice'; -import { selectImagesAll } from 'features/gallery/store/imagesSlice'; +import { + imageSelected, + selectImagesAll, + boardIdSelected, +} from 'features/gallery/store/gallerySlice'; import { IMAGES_PER_PAGE, receivedPageOfImages, } from 'services/api/thunks/image'; -import { imageSelected } from 'features/gallery/store/gallerySlice'; import { boardsApi } from 'services/api/endpoints/boards'; const moduleLog = log.child({ namespace: 'boards' }); @@ -28,7 +30,7 @@ export const addBoardIdSelectedListener = () => { return; } - const { categories } = state.images; + const { categories } = state.gallery; const filteredImages = allImages.filter((i) => { const isInCategory = categories.includes(i.image_category); @@ -47,7 +49,7 @@ export const addBoardIdSelectedListener = () => { return; } - dispatch(imageSelected(board.cover_image_name)); + dispatch(imageSelected(board.cover_image_name ?? null)); // if we haven't loaded one full page of images from this board, load more if ( @@ -77,7 +79,7 @@ export const addBoardIdSelected_changeSelectedImage_listener = () => { return; } - const { categories } = state.images; + const { categories } = state.gallery; const filteredImages = selectImagesAll(state).filter((i) => { const isInCategory = categories.includes(i.image_category); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardImagesDeleted.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardImagesDeleted.ts index c4d3c5f0ba..4b48aa4626 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardImagesDeleted.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/boardImagesDeleted.ts @@ -1,11 +1,11 @@ import { requestedBoardImagesDeletion } from 'features/gallery/store/actions'; import { startAppListening } from '..'; -import { imageSelected } from 'features/gallery/store/gallerySlice'; import { + imageSelected, imagesRemoved, selectImagesAll, selectImagesById, -} from 'features/gallery/store/imagesSlice'; +} from 'features/gallery/store/gallerySlice'; import { resetCanvas } from 'features/canvas/store/canvasSlice'; import { controlNetReset } from 'features/controlNet/store/controlNetSlice'; import { clearInitialImage } from 'features/parameters/store/generationSlice'; @@ -22,12 +22,15 @@ export const addRequestedBoardImageDeletionListener = () => { const { board_id } = board; const state = getState(); - const selectedImage = state.gallery.selectedImage - ? selectImagesById(state, state.gallery.selectedImage) + const selectedImageName = + state.gallery.selection[state.gallery.selection.length - 1]; + + const selectedImage = selectedImageName + ? selectImagesById(state, selectedImageName) : undefined; if (selectedImage && selectedImage.board_id === board_id) { - dispatch(imageSelected()); + dispatch(imageSelected(null)); } // We need to reset the features where the board images are in use - none of these work if their image(s) don't exist diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasSavedToGallery.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasSavedToGallery.ts index af55a1382e..610d89873f 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasSavedToGallery.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/canvasSavedToGallery.ts @@ -4,7 +4,7 @@ import { log } from 'app/logging/useLogger'; import { imageUploaded } from 'services/api/thunks/image'; import { getBaseLayerBlob } from 'features/canvas/util/getBaseLayerBlob'; import { addToast } from 'features/system/store/systemSlice'; -import { imageUpserted } from 'features/gallery/store/imagesSlice'; +import { imageUpserted } from 'features/gallery/store/gallerySlice'; const moduleLog = log.child({ namespace: 'canvasSavedToGalleryListener' }); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageCategoriesChanged.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageCategoriesChanged.ts index 25b7b7c11f..178cb3c835 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageCategoriesChanged.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageCategoriesChanged.ts @@ -3,8 +3,8 @@ import { startAppListening } from '..'; import { receivedPageOfImages } from 'services/api/thunks/image'; import { imageCategoriesChanged, - selectFilteredImagesAsArray, -} from 'features/gallery/store/imagesSlice'; + selectFilteredImages, +} from 'features/gallery/store/gallerySlice'; const moduleLog = log.child({ namespace: 'gallery' }); @@ -13,7 +13,7 @@ export const addImageCategoriesChangedListener = () => { actionCreator: imageCategoriesChanged, effect: (action, { getState, dispatch }) => { const state = getState(); - const filteredImagesCount = selectFilteredImagesAsArray(state).length; + const filteredImagesCount = selectFilteredImages(state).length; if (!filteredImagesCount) { dispatch( diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDeleted.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDeleted.ts index 91cd509ca6..ca20170c5d 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDeleted.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDeleted.ts @@ -1,18 +1,21 @@ -import { requestedImageDeletion } from 'features/gallery/store/actions'; import { startAppListening } from '..'; import { imageDeleted } from 'services/api/thunks/image'; import { log } from 'app/logging/useLogger'; import { clamp } from 'lodash-es'; -import { imageSelected } from 'features/gallery/store/gallerySlice'; import { + imageSelected, imageRemoved, selectImagesIds, -} from 'features/gallery/store/imagesSlice'; +} from 'features/gallery/store/gallerySlice'; import { resetCanvas } from 'features/canvas/store/canvasSlice'; import { controlNetReset } from 'features/controlNet/store/controlNetSlice'; import { clearInitialImage } from 'features/parameters/store/generationSlice'; import { nodeEditorReset } from 'features/nodes/store/nodesSlice'; import { api } from 'services/api'; +import { + imageDeletionConfirmed, + isModalOpenChanged, +} from 'features/imageDeletion/store/imageDeletionSlice'; const moduleLog = log.child({ namespace: 'image' }); @@ -21,16 +24,19 @@ const moduleLog = log.child({ namespace: 'image' }); */ export const addRequestedImageDeletionListener = () => { startAppListening({ - actionCreator: requestedImageDeletion, + actionCreator: imageDeletionConfirmed, effect: async (action, { dispatch, getState, condition }) => { - const { image, imageUsage } = action.payload; + const { imageDTO, imageUsage } = action.payload; - const { image_name } = image; + dispatch(isModalOpenChanged(false)); + + const { image_name } = imageDTO; const state = getState(); - const selectedImage = state.gallery.selectedImage; + const lastSelectedImage = + state.gallery.selection[state.gallery.selection.length - 1]; - if (selectedImage === image_name) { + if (lastSelectedImage === image_name) { const ids = selectImagesIds(state); const deletedImageIndex = ids.findIndex( @@ -50,7 +56,7 @@ export const addRequestedImageDeletionListener = () => { if (newSelectedImageId) { dispatch(imageSelected(newSelectedImageId as string)); } else { - dispatch(imageSelected()); + dispatch(imageSelected(null)); } } @@ -88,7 +94,7 @@ export const addRequestedImageDeletionListener = () => { if (wasImageDeleted) { dispatch( - api.util.invalidateTags([{ type: 'Board', id: image.board_id }]) + api.util.invalidateTags([{ type: 'Board', id: imageDTO.board_id }]) ); } }, diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDropped.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDropped.ts new file mode 100644 index 0000000000..56f660a653 --- /dev/null +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageDropped.ts @@ -0,0 +1,188 @@ +import { createAction } from '@reduxjs/toolkit'; +import { startAppListening } from '../'; +import { log } from 'app/logging/useLogger'; +import { + TypesafeDraggableData, + TypesafeDroppableData, +} from 'app/components/ImageDnd/typesafeDnd'; +import { imageSelected } from 'features/gallery/store/gallerySlice'; +import { initialImageChanged } from 'features/parameters/store/generationSlice'; +import { + imageAddedToBatch, + imagesAddedToBatch, +} from 'features/batch/store/batchSlice'; +import { controlNetImageChanged } from 'features/controlNet/store/controlNetSlice'; +import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice'; +import { + fieldValueChanged, + imageCollectionFieldValueChanged, +} from 'features/nodes/store/nodesSlice'; +import { boardsApi } from 'services/api/endpoints/boards'; +import { boardImagesApi } from 'services/api/endpoints/boardImages'; + +const moduleLog = log.child({ namespace: 'dnd' }); + +export const imageDropped = createAction<{ + overData: TypesafeDroppableData; + activeData: TypesafeDraggableData; +}>('dnd/imageDropped'); + +export const addImageDroppedListener = () => { + startAppListening({ + actionCreator: imageDropped, + effect: (action, { dispatch, getState }) => { + const { activeData, overData } = action.payload; + const { actionType } = overData; + + // set current image + if ( + actionType === 'SET_CURRENT_IMAGE' && + activeData.payloadType === 'IMAGE_DTO' && + activeData.payload.imageDTO + ) { + dispatch(imageSelected(activeData.payload.imageDTO.image_name)); + } + + // set initial image + if ( + actionType === 'SET_INITIAL_IMAGE' && + activeData.payloadType === 'IMAGE_DTO' && + activeData.payload.imageDTO + ) { + dispatch(initialImageChanged(activeData.payload.imageDTO)); + } + + // add image to batch + if ( + actionType === 'ADD_TO_BATCH' && + activeData.payloadType === 'IMAGE_DTO' && + activeData.payload.imageDTO + ) { + dispatch(imageAddedToBatch(activeData.payload.imageDTO.image_name)); + } + + // add multiple images to batch + if ( + actionType === 'ADD_TO_BATCH' && + activeData.payloadType === 'IMAGE_NAMES' + ) { + dispatch(imagesAddedToBatch(activeData.payload.imageNames)); + } + + // set control image + if ( + actionType === 'SET_CONTROLNET_IMAGE' && + activeData.payloadType === 'IMAGE_DTO' && + activeData.payload.imageDTO + ) { + const { controlNetId } = overData.context; + dispatch( + controlNetImageChanged({ + controlImage: activeData.payload.imageDTO.image_name, + controlNetId, + }) + ); + } + + // set canvas image + if ( + actionType === 'SET_CANVAS_INITIAL_IMAGE' && + activeData.payloadType === 'IMAGE_DTO' && + activeData.payload.imageDTO + ) { + dispatch(setInitialCanvasImage(activeData.payload.imageDTO)); + } + + // set nodes image + if ( + actionType === 'SET_NODES_IMAGE' && + activeData.payloadType === 'IMAGE_DTO' && + activeData.payload.imageDTO + ) { + const { fieldName, nodeId } = overData.context; + dispatch( + fieldValueChanged({ + nodeId, + fieldName, + value: activeData.payload.imageDTO, + }) + ); + } + + // set multiple nodes images (single image handler) + if ( + actionType === 'SET_MULTI_NODES_IMAGE' && + activeData.payloadType === 'IMAGE_DTO' && + activeData.payload.imageDTO + ) { + const { fieldName, nodeId } = overData.context; + dispatch( + fieldValueChanged({ + nodeId, + fieldName, + value: [activeData.payload.imageDTO], + }) + ); + } + + // set multiple nodes images (multiple images handler) + if ( + actionType === 'SET_MULTI_NODES_IMAGE' && + activeData.payloadType === 'IMAGE_NAMES' + ) { + const { fieldName, nodeId } = overData.context; + dispatch( + imageCollectionFieldValueChanged({ + nodeId, + fieldName, + value: activeData.payload.imageNames.map((image_name) => ({ + image_name, + })), + }) + ); + } + + // remove image from board + // TODO: remove board_id from `removeImageFromBoard()` endpoint + // TODO: handle multiple images + // if ( + // actionType === 'MOVE_BOARD' && + // activeData.payloadType === 'IMAGE_DTO' && + // activeData.payload.imageDTO && + // overData.boardId !== null + // ) { + // const { image_name } = activeData.payload.imageDTO; + // dispatch( + // boardImagesApi.endpoints.removeImageFromBoard.initiate({ image_name }) + // ); + // } + + // add image to board + if ( + actionType === 'MOVE_BOARD' && + activeData.payloadType === 'IMAGE_DTO' && + activeData.payload.imageDTO && + overData.context.boardId + ) { + const { image_name } = activeData.payload.imageDTO; + const { boardId } = overData.context; + dispatch( + boardImagesApi.endpoints.addImageToBoard.initiate({ + image_name, + board_id: boardId, + }) + ); + } + + // add multiple images to board + // TODO: add endpoint + // if ( + // actionType === 'ADD_TO_BATCH' && + // activeData.payloadType === 'IMAGE_NAMES' && + // activeData.payload.imageDTONames + // ) { + // dispatch(boardImagesApi.endpoints.addImagesToBoard.intiate({})); + // } + }, + }); +}; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageMetadataReceived.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageMetadataReceived.ts index 24265faaa9..19af5b24c3 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageMetadataReceived.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageMetadataReceived.ts @@ -1,7 +1,7 @@ import { log } from 'app/logging/useLogger'; import { startAppListening } from '..'; import { imageMetadataReceived, imageUpdated } from 'services/api/thunks/image'; -import { imageUpserted } from 'features/gallery/store/imagesSlice'; +import { imageUpserted } from 'features/gallery/store/gallerySlice'; const moduleLog = log.child({ namespace: 'image' }); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageToDeleteSelected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageToDeleteSelected.ts new file mode 100644 index 0000000000..531981126a --- /dev/null +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageToDeleteSelected.ts @@ -0,0 +1,40 @@ +import { startAppListening } from '..'; +import { log } from 'app/logging/useLogger'; +import { + imageDeletionConfirmed, + imageToDeleteSelected, + isModalOpenChanged, + selectImageUsage, +} from 'features/imageDeletion/store/imageDeletionSlice'; + +const moduleLog = log.child({ namespace: 'image' }); + +export const addImageToDeleteSelectedListener = () => { + startAppListening({ + actionCreator: imageToDeleteSelected, + effect: async (action, { dispatch, getState, condition }) => { + const imageDTO = action.payload; + const state = getState(); + const { shouldConfirmOnDelete } = state.system; + const imageUsage = selectImageUsage(getState()); + + if (!imageUsage) { + // should never happen + return; + } + + const isImageInUse = + imageUsage.isCanvasImage || + imageUsage.isInitialImage || + imageUsage.isControlNetImage || + imageUsage.isNodesImage; + + if (shouldConfirmOnDelete || isImageInUse) { + dispatch(isModalOpenChanged(true)); + return; + } + + dispatch(imageDeletionConfirmed({ imageDTO, imageUsage })); + }, + }); +}; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUploaded.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUploaded.ts index f55ed11c8f..0cd852c3de 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUploaded.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUploaded.ts @@ -2,11 +2,12 @@ import { startAppListening } from '..'; import { imageUploaded } from 'services/api/thunks/image'; import { addToast } from 'features/system/store/systemSlice'; import { log } from 'app/logging/useLogger'; -import { imageUpserted } from 'features/gallery/store/imagesSlice'; +import { imageUpserted } from 'features/gallery/store/gallerySlice'; import { setInitialCanvasImage } from 'features/canvas/store/canvasSlice'; import { controlNetImageChanged } from 'features/controlNet/store/controlNetSlice'; import { initialImageChanged } from 'features/parameters/store/generationSlice'; import { fieldValueChanged } from 'features/nodes/store/nodesSlice'; +import { imageAddedToBatch } from 'features/batch/store/batchSlice'; const moduleLog = log.child({ namespace: 'image' }); @@ -70,6 +71,11 @@ export const addImageUploadedFulfilledListener = () => { dispatch(addToast({ title: 'Image Uploaded', status: 'success' })); return; } + + if (postUploadAction?.type === 'ADD_TO_BATCH') { + dispatch(imageAddedToBatch(image.image_name)); + return; + } }, }); }; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUrlsReceived.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUrlsReceived.ts index c663c64361..0d8aa3d7c9 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUrlsReceived.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/imageUrlsReceived.ts @@ -1,7 +1,7 @@ import { log } from 'app/logging/useLogger'; import { startAppListening } from '..'; import { imageUrlsReceived } from 'services/api/thunks/image'; -import { imageUpdatedOne } from 'features/gallery/store/imagesSlice'; +import { imageUpdatedOne } from 'features/gallery/store/gallerySlice'; const moduleLog = log.child({ namespace: 'image' }); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/initialImageSelected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/initialImageSelected.ts index 9aca82a32b..fe1a9bd806 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/initialImageSelected.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/initialImageSelected.ts @@ -4,7 +4,7 @@ import { addToast } from 'features/system/store/systemSlice'; import { startAppListening } from '..'; import { initialImageSelected } from 'features/parameters/store/actions'; import { makeToast } from 'app/components/Toaster'; -import { selectImagesById } from 'features/gallery/store/imagesSlice'; +import { selectImagesById } from 'features/gallery/store/gallerySlice'; import { isImageDTO } from 'services/api/guards'; export const addInitialImageSelectedListener = () => { diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/receivedPageOfImages.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/receivedPageOfImages.ts index e357d38dc3..3c11916be0 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/receivedPageOfImages.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/receivedPageOfImages.ts @@ -2,6 +2,7 @@ import { log } from 'app/logging/useLogger'; import { startAppListening } from '..'; import { serializeError } from 'serialize-error'; import { receivedPageOfImages } from 'services/api/thunks/image'; +import { imagesApi } from 'services/api/endpoints/images'; const moduleLog = log.child({ namespace: 'gallery' }); @@ -9,11 +10,17 @@ export const addReceivedPageOfImagesFulfilledListener = () => { startAppListening({ actionCreator: receivedPageOfImages.fulfilled, effect: (action, { getState, dispatch }) => { - const page = action.payload; + const { items } = action.payload; moduleLog.debug( { data: { payload: action.payload } }, - `Received ${page.items.length} images` + `Received ${items.length} images` ); + + items.forEach((image) => { + dispatch( + imagesApi.util.upsertQueryData('getImageDTO', image.image_name, image) + ); + }); }, }); }; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/selectionAddedToBatch.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/selectionAddedToBatch.ts new file mode 100644 index 0000000000..dae72d92e7 --- /dev/null +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/selectionAddedToBatch.ts @@ -0,0 +1,19 @@ +import { startAppListening } from '..'; +import { log } from 'app/logging/useLogger'; +import { + imagesAddedToBatch, + selectionAddedToBatch, +} from 'features/batch/store/batchSlice'; + +const moduleLog = log.child({ namespace: 'batch' }); + +export const addSelectionAddedToBatchListener = () => { + startAppListening({ + actionCreator: selectionAddedToBatch, + effect: (action, { dispatch, getState }) => { + const { selection } = getState().gallery; + + dispatch(imagesAddedToBatch(selection)); + }, + }); +}; diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketConnected.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketConnected.ts index 976c1558d0..cab4738373 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketConnected.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/socketio/socketConnected.ts @@ -14,11 +14,11 @@ export const addSocketConnectedEventListener = () => { moduleLog.debug({ timestamp }, 'Connected'); - const { nodes, config, images } = getState(); + const { nodes, config, gallery } = getState(); const { disabledTabs } = config; - if (!images.ids.length) { + if (!gallery.ids.length) { dispatch( receivedPageOfImages({ categories: ['general'], diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/stagingAreaImageSaved.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/stagingAreaImageSaved.ts index bc2c1d1c27..36840e5de1 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/stagingAreaImageSaved.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/stagingAreaImageSaved.ts @@ -2,7 +2,7 @@ import { stagingAreaImageSaved } from 'features/canvas/store/actions'; import { startAppListening } from '..'; import { log } from 'app/logging/useLogger'; import { imageUpdated } from 'services/api/thunks/image'; -import { imageUpserted } from 'features/gallery/store/imagesSlice'; +import { imageUpserted } from 'features/gallery/store/gallerySlice'; import { addToast } from 'features/system/store/systemSlice'; const moduleLog = log.child({ namespace: 'canvas' }); diff --git a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/updateImageUrlsOnConnect.ts b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/updateImageUrlsOnConnect.ts index 670d762d24..490d99290d 100644 --- a/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/updateImageUrlsOnConnect.ts +++ b/invokeai/frontend/web/src/app/store/middleware/listenerMiddleware/listeners/updateImageUrlsOnConnect.ts @@ -8,7 +8,7 @@ import { controlNetSelector } from 'features/controlNet/store/controlNetSlice'; import { forEach, uniqBy } from 'lodash-es'; import { imageUrlsReceived } from 'services/api/thunks/image'; import { log } from 'app/logging/useLogger'; -import { selectImagesEntities } from 'features/gallery/store/imagesSlice'; +import { selectImagesEntities } from 'features/gallery/store/gallerySlice'; const moduleLog = log.child({ namespace: 'images' }); @@ -36,7 +36,7 @@ const selectAllUsedImages = createSelector( nodes.nodes.forEach((node) => { forEach(node.data.inputs, (input) => { if (input.type === 'image' && input.value) { - allUsedImages.push(input.value); + allUsedImages.push(input.value.image_name); } }); }); diff --git a/invokeai/frontend/web/src/app/store/store.ts b/invokeai/frontend/web/src/app/store/store.ts index e92a422d68..2fd071bd23 100644 --- a/invokeai/frontend/web/src/app/store/store.ts +++ b/invokeai/frontend/web/src/app/store/store.ts @@ -11,18 +11,18 @@ import { rememberEnhancer, rememberReducer } from 'redux-remember'; import canvasReducer from 'features/canvas/store/canvasSlice'; import controlNetReducer from 'features/controlNet/store/controlNetSlice'; import galleryReducer from 'features/gallery/store/gallerySlice'; -import imagesReducer from 'features/gallery/store/imagesSlice'; import lightboxReducer from 'features/lightbox/store/lightboxSlice'; import generationReducer from 'features/parameters/store/generationSlice'; import postprocessingReducer from 'features/parameters/store/postprocessingSlice'; import systemReducer from 'features/system/store/systemSlice'; -// import sessionReducer from 'features/system/store/sessionSlice'; import nodesReducer from 'features/nodes/store/nodesSlice'; import boardsReducer from 'features/gallery/store/boardSlice'; import configReducer from 'features/system/store/configSlice'; import hotkeysReducer from 'features/ui/store/hotkeysSlice'; import uiReducer from 'features/ui/store/uiSlice'; import dynamicPromptsReducer from 'features/dynamicPrompts/store/slice'; +import batchReducer from 'features/batch/store/batchSlice'; +import imageDeletionReducer from 'features/imageDeletion/store/imageDeletionSlice'; import { listenerMiddleware } from './middleware/listenerMiddleware'; @@ -45,11 +45,11 @@ const allReducers = { config: configReducer, ui: uiReducer, hotkeys: hotkeysReducer, - images: imagesReducer, controlNet: controlNetReducer, boards: boardsReducer, - // session: sessionReducer, dynamicPrompts: dynamicPromptsReducer, + batch: batchReducer, + imageDeletion: imageDeletionReducer, [api.reducerPath]: api.reducer, }; @@ -68,6 +68,7 @@ const rememberedKeys: (keyof typeof allReducers)[] = [ 'ui', 'controlNet', 'dynamicPrompts', + 'batch', // 'boards', // 'hotkeys', // 'config', diff --git a/invokeai/frontend/web/src/common/components/IAIButton.tsx b/invokeai/frontend/web/src/common/components/IAIButton.tsx index 3efae76d1e..d1e77537cc 100644 --- a/invokeai/frontend/web/src/common/components/IAIButton.tsx +++ b/invokeai/frontend/web/src/common/components/IAIButton.tsx @@ -15,10 +15,25 @@ export interface IAIButtonProps extends ButtonProps { } const IAIButton = forwardRef((props: IAIButtonProps, forwardedRef) => { - const { children, tooltip = '', tooltipProps, isChecked, ...rest } = props; + const { + children, + tooltip = '', + tooltipProps: { placement = 'top', hasArrow = true, ...tooltipProps } = {}, + isChecked, + ...rest + } = props; return ( - - diff --git a/invokeai/frontend/web/src/common/components/IAICollapse.tsx b/invokeai/frontend/web/src/common/components/IAICollapse.tsx index ec23793741..5db26f3841 100644 --- a/invokeai/frontend/web/src/common/components/IAICollapse.tsx +++ b/invokeai/frontend/web/src/common/components/IAICollapse.tsx @@ -1,6 +1,14 @@ import { ChevronUpIcon } from '@chakra-ui/icons'; -import { Box, Collapse, Flex, Spacer, Switch } from '@chakra-ui/react'; +import { + Box, + Collapse, + Flex, + Spacer, + Switch, + useColorMode, +} from '@chakra-ui/react'; import { PropsWithChildren, memo } from 'react'; +import { mode } from 'theme/util/mode'; export type IAIToggleCollapseProps = PropsWithChildren & { label: string; @@ -11,6 +19,7 @@ export type IAIToggleCollapseProps = PropsWithChildren & { const IAICollapse = (props: IAIToggleCollapseProps) => { const { label, isOpen, onToggle, children, withSwitch = false } = props; + const { colorMode } = useColorMode(); return ( { px: 4, borderTopRadius: 'base', borderBottomRadius: isOpen ? 0 : 'base', - bg: isOpen ? 'base.750' : 'base.800', - color: 'base.100', + bg: isOpen + ? mode('base.200', 'base.750')(colorMode) + : mode('base.150', 'base.800')(colorMode), + color: mode('base.900', 'base.100')(colorMode), _hover: { - bg: isOpen ? 'base.700' : 'base.750', + bg: isOpen + ? mode('base.250', 'base.700')(colorMode) + : mode('base.200', 'base.750')(colorMode), }, fontSize: 'sm', fontWeight: 600, @@ -50,7 +63,13 @@ const IAICollapse = (props: IAIToggleCollapseProps) => { )} - + {children} diff --git a/invokeai/frontend/web/src/common/components/IAIDndImage.tsx b/invokeai/frontend/web/src/common/components/IAIDndImage.tsx index bdf22c2df1..959a70bc29 100644 --- a/invokeai/frontend/web/src/common/components/IAIDndImage.tsx +++ b/invokeai/frontend/web/src/common/components/IAIDndImage.tsx @@ -1,18 +1,20 @@ import { - Box, ChakraProps, Flex, Icon, - IconButtonProps, Image, + useColorMode, + useColorModeValue, } from '@chakra-ui/react'; -import { useDraggable, useDroppable } from '@dnd-kit/core'; import { useCombinedRefs } from '@dnd-kit/utilities'; import IAIIconButton from 'common/components/IAIIconButton'; -import { IAIImageLoadingFallback } from 'common/components/IAIImageFallback'; +import { + IAILoadingImageFallback, + IAINoContentFallback, +} from 'common/components/IAIImageFallback'; import ImageMetadataOverlay from 'common/components/ImageMetadataOverlay'; import { AnimatePresence } from 'framer-motion'; -import { ReactElement, SyntheticEvent } from 'react'; +import { MouseEvent, ReactElement, SyntheticEvent } from 'react'; import { memo, useRef } from 'react'; import { FaImage, FaUndo, FaUpload } from 'react-icons/fa'; import { ImageDTO } from 'services/api/types'; @@ -20,89 +22,107 @@ import { v4 as uuidv4 } from 'uuid'; import IAIDropOverlay from './IAIDropOverlay'; import { PostUploadAction } from 'services/api/thunks/image'; import { useImageUploadButton } from 'common/hooks/useImageUploadButton'; +import { mode } from 'theme/util/mode'; +import { + TypesafeDraggableData, + TypesafeDroppableData, + isValidDrop, + useDraggable, + useDroppable, +} from 'app/components/ImageDnd/typesafeDnd'; type IAIDndImageProps = { - image: ImageDTO | null | undefined; - onDrop: (droppedImage: ImageDTO) => void; - onReset?: () => void; + imageDTO: ImageDTO | undefined; onError?: (event: SyntheticEvent) => void; onLoad?: (event: SyntheticEvent) => void; - resetIconSize?: IconButtonProps['size']; + onClick?: (event: MouseEvent) => void; + onClickReset?: (event: MouseEvent) => void; withResetIcon?: boolean; + resetIcon?: ReactElement; + resetTooltip?: string; withMetadataOverlay?: boolean; isDragDisabled?: boolean; isDropDisabled?: boolean; isUploadDisabled?: boolean; - fallback?: ReactElement; - payloadImage?: ImageDTO | null | undefined; minSize?: number; postUploadAction?: PostUploadAction; imageSx?: ChakraProps['sx']; fitContainer?: boolean; + droppableData?: TypesafeDroppableData; + draggableData?: TypesafeDraggableData; + dropLabel?: string; + isSelected?: boolean; + thumbnail?: boolean; + noContentFallback?: ReactElement; }; const IAIDndImage = (props: IAIDndImageProps) => { const { - image, - onDrop, - onReset, + imageDTO, + onClickReset, onError, - resetIconSize = 'md', + onClick, withResetIcon = false, withMetadataOverlay = false, isDropDisabled = false, isDragDisabled = false, isUploadDisabled = false, - fallback = , - payloadImage, minSize = 24, postUploadAction, imageSx, fitContainer = false, + droppableData, + draggableData, + dropLabel, + isSelected = false, + thumbnail = false, + resetTooltip = 'Reset', + resetIcon = , + noContentFallback = , } = props; - const dndId = useRef(uuidv4()); + const { colorMode } = useColorMode(); - const { - isOver, - setNodeRef: setDroppableRef, - active: isDropActive, - } = useDroppable({ - id: dndId.current, - disabled: isDropDisabled, - data: { - handleDrop: onDrop, - }, - }); + const dndId = useRef(uuidv4()); const { attributes, listeners, setNodeRef: setDraggableRef, isDragging, + active, } = useDraggable({ id: dndId.current, - data: { - image: payloadImage ? payloadImage : image, - }, - disabled: isDragDisabled || !image, + disabled: isDragDisabled || !imageDTO, + data: draggableData, }); + const { isOver, setNodeRef: setDroppableRef } = useDroppable({ + id: dndId.current, + disabled: isDropDisabled, + data: droppableData, + }); + + const setDndRef = useCombinedRefs(setDroppableRef, setDraggableRef); + const { getUploadButtonProps, getUploadInputProps } = useImageUploadButton({ postUploadAction, isDisabled: isUploadDisabled, }); - const setNodeRef = useCombinedRefs(setDroppableRef, setDraggableRef); + const resetIconShadow = useColorModeValue( + `drop-shadow(0px 0px 0.1rem var(--invokeai-colors-base-600))`, + `drop-shadow(0px 0px 0.1rem var(--invokeai-colors-base-800))` + ); const uploadButtonStyles = isUploadDisabled ? {} : { cursor: 'pointer', - bg: 'base.800', + bg: mode('base.200', 'base.800')(colorMode), _hover: { - bg: 'base.750', - color: 'base.300', + bg: mode('base.300', 'base.650')(colorMode), + color: mode('base.500', 'base.300')(colorMode), }, }; @@ -114,16 +134,16 @@ const IAIDndImage = (props: IAIDndImageProps) => { alignItems: 'center', justifyContent: 'center', position: 'relative', - minW: minSize, - minH: minSize, + minW: minSize ? minSize : undefined, + minH: minSize ? minSize : undefined, userSelect: 'none', - cursor: isDragDisabled || !image ? 'auto' : 'grab', + cursor: isDragDisabled || !imageDTO ? 'default' : 'pointer', }} {...attributes} {...listeners} - ref={setNodeRef} + ref={setDndRef} > - {image && ( + {imageDTO && ( { }} > } onError={onError} - objectFit="contain" draggable={false} sx={{ + objectFit: 'contain', maxW: 'full', maxH: 'full', borderRadius: 'base', + shadow: isSelected ? 'selected.light' : undefined, + _dark: { shadow: isSelected ? 'selected.dark' : undefined }, ...imageSx, }} /> - {withMetadataOverlay && } - {onReset && withResetIcon && ( - } + {onClickReset && withResetIcon && ( + - } - onClick={onReset} - /> - + /> )} - - {isDropActive && } - )} - {!image && ( + {!imageDTO && !isUploadDisabled && ( <> { borderRadius: 'base', transitionProperty: 'common', transitionDuration: '0.1s', - color: 'base.500', + color: mode('base.500', 'base.500')(colorMode), ...uploadButtonStyles, }} {...getUploadButtonProps()} > - - {isDropActive && } - )} + {!imageDTO && isUploadDisabled && noContentFallback} + + {isValidDrop(droppableData, active) && !isDragging && ( + + )} + ); }; diff --git a/invokeai/frontend/web/src/common/components/IAIDropOverlay.tsx b/invokeai/frontend/web/src/common/components/IAIDropOverlay.tsx index 79105c00d6..573a900fef 100644 --- a/invokeai/frontend/web/src/common/components/IAIDropOverlay.tsx +++ b/invokeai/frontend/web/src/common/components/IAIDropOverlay.tsx @@ -1,6 +1,7 @@ -import { Flex, Text } from '@chakra-ui/react'; +import { Flex, Text, useColorMode } from '@chakra-ui/react'; import { motion } from 'framer-motion'; import { memo, useRef } from 'react'; +import { mode } from 'theme/util/mode'; import { v4 as uuidv4 } from 'uuid'; type Props = { @@ -11,6 +12,7 @@ type Props = { export const IAIDropOverlay = (props: Props) => { const { isOver, label = 'Drop' } = props; const motionId = useRef(uuidv4()); + const { colorMode } = useColorMode(); return ( { insetInlineStart: 0, w: 'full', h: 'full', - bg: 'base.900', + bg: mode('base.700', 'base.900')(colorMode), opacity: 0.7, borderRadius: 'base', alignItems: 'center', @@ -60,8 +62,10 @@ export const IAIDropOverlay = (props: Props) => { w: 'full', h: 'full', opacity: 1, - borderWidth: 2, - borderColor: isOver ? 'base.200' : 'base.500', + borderWidth: 3, + borderColor: isOver + ? mode('base.50', 'base.200')(colorMode) + : mode('base.100', 'base.500')(colorMode), borderRadius: 'base', borderStyle: 'dashed', transitionProperty: 'common', @@ -74,8 +78,10 @@ export const IAIDropOverlay = (props: Props) => { sx={{ fontSize: '2xl', fontWeight: 600, - transform: isOver ? 'scale(1.1)' : 'scale(1)', - color: isOver ? 'base.100' : 'base.500', + transform: isOver ? 'scale(1.02)' : 'scale(1)', + color: isOver + ? mode('base.50', 'base.50')(colorMode) + : mode('base.100', 'base.200')(colorMode), transitionProperty: 'common', transitionDuration: '0.1s', }} diff --git a/invokeai/frontend/web/src/common/components/IAIIconButton.tsx b/invokeai/frontend/web/src/common/components/IAIIconButton.tsx index 8ea06a1328..ed1514055e 100644 --- a/invokeai/frontend/web/src/common/components/IAIIconButton.tsx +++ b/invokeai/frontend/web/src/common/components/IAIIconButton.tsx @@ -29,7 +29,7 @@ const IAIIconButton = forwardRef((props: IAIIconButtonProps, forwardedRef) => { diff --git a/invokeai/frontend/web/src/common/components/IAIImageFallback.tsx b/invokeai/frontend/web/src/common/components/IAIImageFallback.tsx index 03a00d5b1c..a07071ee79 100644 --- a/invokeai/frontend/web/src/common/components/IAIImageFallback.tsx +++ b/invokeai/frontend/web/src/common/components/IAIImageFallback.tsx @@ -1,69 +1,82 @@ import { As, + ChakraProps, Flex, - FlexProps, Icon, - IconProps, + Skeleton, Spinner, - SpinnerProps, + StyleProps, + Text, } from '@chakra-ui/react'; -import { ReactElement } from 'react'; import { FaImage } from 'react-icons/fa'; +import { ImageDTO } from 'services/api/types'; -type Props = FlexProps & { - spinnerProps?: SpinnerProps; -}; +type Props = { image: ImageDTO | undefined }; + +export const IAILoadingImageFallback = (props: Props) => { + if (props.image) { + return ( + + ); + } -export const IAIImageLoadingFallback = (props: Props) => { - const { spinnerProps, ...rest } = props; - const { sx, ...restFlexProps } = rest; return ( - + ); }; type IAINoImageFallbackProps = { - flexProps?: FlexProps; - iconProps?: IconProps; - as?: As; + label?: string; + icon?: As; + boxSize?: StyleProps['boxSize']; + sx?: ChakraProps['sx']; }; -export const IAINoImageFallback = (props: IAINoImageFallbackProps) => { - const { sx: flexSx, ...restFlexProps } = props.flexProps ?? { sx: {} }; - const { sx: iconSx, ...restIconProps } = props.iconProps ?? { sx: {} }; +export const IAINoContentFallback = (props: IAINoImageFallbackProps) => { + const { icon = FaImage, boxSize = 16 } = props; + return ( - + + {props.label && {props.label}} ); }; diff --git a/invokeai/frontend/web/src/common/components/IAIMantineMultiSelect.tsx b/invokeai/frontend/web/src/common/components/IAIMantineMultiSelect.tsx index 90be25d04d..39ec6fd245 100644 --- a/invokeai/frontend/web/src/common/components/IAIMantineMultiSelect.tsx +++ b/invokeai/frontend/web/src/common/components/IAIMantineMultiSelect.tsx @@ -1,6 +1,8 @@ -import { Tooltip } from '@chakra-ui/react'; +import { Tooltip, useColorMode, useToken } from '@chakra-ui/react'; import { MultiSelect, MultiSelectProps } from '@mantine/core'; +import { useChakraThemeTokens } from 'common/hooks/useChakraThemeTokens'; import { memo } from 'react'; +import { mode } from 'theme/util/mode'; type IAIMultiSelectProps = MultiSelectProps & { tooltip?: string; @@ -8,71 +10,100 @@ type IAIMultiSelectProps = MultiSelectProps & { const IAIMantineMultiSelect = (props: IAIMultiSelectProps) => { const { searchable = true, tooltip, ...rest } = props; + const { + base50, + base100, + base200, + base300, + base400, + base500, + base600, + base700, + base800, + base900, + accent200, + accent300, + accent400, + accent500, + accent600, + } = useChakraThemeTokens(); + const [boxShadow] = useToken('shadows', ['dark-lg']); + const { colorMode } = useColorMode(); + return ( ({ label: { - color: 'var(--invokeai-colors-base-300)', + color: mode(base700, base300)(colorMode), fontWeight: 'normal', }, searchInput: { - '::placeholder': { - color: 'var(--invokeai-colors-base-700)', + ':placeholder': { + color: mode(base300, base700)(colorMode), }, }, input: { - backgroundColor: 'var(--invokeai-colors-base-900)', + backgroundColor: mode(base50, base900)(colorMode), borderWidth: '2px', - borderColor: 'var(--invokeai-colors-base-800)', - color: 'var(--invokeai-colors-base-100)', + borderColor: mode(base200, base800)(colorMode), + color: mode(base900, base100)(colorMode), paddingRight: 24, fontWeight: 600, - '&:hover': { borderColor: 'var(--invokeai-colors-base-700)' }, + '&:hover': { borderColor: mode(base300, base600)(colorMode) }, '&:focus': { - borderColor: 'var(--invokeai-colors-accent-600)', + borderColor: mode(accent300, accent600)(colorMode), + }, + '&:is(:focus, :hover)': { + borderColor: mode(base400, base500)(colorMode), }, '&:focus-within': { - borderColor: 'var(--invokeai-colors-accent-600)', + borderColor: mode(accent200, accent600)(colorMode), + }, + '&:disabled': { + backgroundColor: mode(base300, base700)(colorMode), + color: mode(base600, base400)(colorMode), }, }, value: { - backgroundColor: 'var(--invokeai-colors-base-800)', - color: 'var(--invokeai-colors-base-100)', + backgroundColor: mode(base200, base800)(colorMode), + color: mode(base900, base100)(colorMode), button: { - color: 'var(--invokeai-colors-base-100)', + color: mode(base900, base100)(colorMode), }, '&:hover': { - backgroundColor: 'var(--invokeai-colors-base-700)', + backgroundColor: mode(base300, base700)(colorMode), cursor: 'pointer', }, }, dropdown: { - backgroundColor: 'var(--invokeai-colors-base-800)', - borderColor: 'var(--invokeai-colors-base-700)', + backgroundColor: mode(base200, base800)(colorMode), + borderColor: mode(base200, base800)(colorMode), + boxShadow, }, item: { - backgroundColor: 'var(--invokeai-colors-base-800)', - color: 'var(--invokeai-colors-base-200)', + backgroundColor: mode(base200, base800)(colorMode), + color: mode(base800, base200)(colorMode), padding: 6, '&[data-hovered]': { - color: 'var(--invokeai-colors-base-100)', - backgroundColor: 'var(--invokeai-colors-base-750)', + color: mode(base900, base100)(colorMode), + backgroundColor: mode(base300, base700)(colorMode), }, '&[data-active]': { - backgroundColor: 'var(--invokeai-colors-base-750)', + backgroundColor: mode(base300, base700)(colorMode), '&:hover': { - color: 'var(--invokeai-colors-base-100)', - backgroundColor: 'var(--invokeai-colors-base-750)', + color: mode(base900, base100)(colorMode), + backgroundColor: mode(base300, base700)(colorMode), }, }, '&[data-selected]': { - color: 'var(--invokeai-colors-base-50)', - backgroundColor: 'var(--invokeai-colors-accent-650)', + backgroundColor: mode(accent400, accent600)(colorMode), + color: mode(base50, base100)(colorMode), fontWeight: 600, '&:hover': { - backgroundColor: 'var(--invokeai-colors-accent-600)', + backgroundColor: mode(accent500, accent500)(colorMode), + color: mode('white', base50)(colorMode), }, }, }, @@ -80,7 +111,7 @@ const IAIMantineMultiSelect = (props: IAIMultiSelectProps) => { width: 24, padding: 20, button: { - color: 'var(--invokeai-colors-base-100)', + color: mode(base900, base100)(colorMode), }, }, })} diff --git a/invokeai/frontend/web/src/common/components/IAIMantineSelect.tsx b/invokeai/frontend/web/src/common/components/IAIMantineSelect.tsx index 5f02140904..9b023fd2d7 100644 --- a/invokeai/frontend/web/src/common/components/IAIMantineSelect.tsx +++ b/invokeai/frontend/web/src/common/components/IAIMantineSelect.tsx @@ -1,6 +1,8 @@ -import { Tooltip } from '@chakra-ui/react'; +import { Tooltip, useColorMode, useToken } from '@chakra-ui/react'; import { Select, SelectProps } from '@mantine/core'; +import { useChakraThemeTokens } from 'common/hooks/useChakraThemeTokens'; import { memo } from 'react'; +import { mode } from 'theme/util/mode'; export type IAISelectDataType = { value: string; @@ -14,61 +16,105 @@ type IAISelectProps = SelectProps & { const IAIMantineSelect = (props: IAISelectProps) => { const { searchable = true, tooltip, ...rest } = props; + const { + base50, + base100, + base200, + base300, + base400, + base500, + base600, + base700, + base800, + base900, + accent200, + accent300, + accent400, + accent500, + accent600, + } = useChakraThemeTokens(); + + const { colorMode } = useColorMode(); + + const [boxShadow] = useToken('shadows', ['dark-lg']); + return ( ); }; diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImagePreview.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImagePreview.tsx deleted file mode 100644 index 2a05eee9b4..0000000000 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/ImageToImage/InitialImagePreview.tsx +++ /dev/null @@ -1,126 +0,0 @@ -import { Flex, Spacer, Text } from '@chakra-ui/react'; -import { createSelector } from '@reduxjs/toolkit'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { - clearInitialImage, - initialImageChanged, -} from 'features/parameters/store/generationSlice'; -import { useCallback } from 'react'; -import { generationSelector } from 'features/parameters/store/generationSelectors'; -import { defaultSelectorOptions } from 'app/store/util/defaultMemoizeOptions'; -import IAIDndImage from 'common/components/IAIDndImage'; -import { ImageDTO } from 'services/api/types'; -import { IAIImageLoadingFallback } from 'common/components/IAIImageFallback'; -import { useGetImageDTOQuery } from 'services/api/endpoints/images'; -import { skipToken } from '@reduxjs/toolkit/dist/query'; -import IAIIconButton from 'common/components/IAIIconButton'; -import { FaUndo, FaUpload } from 'react-icons/fa'; -import useImageUploader from 'common/hooks/useImageUploader'; -import { useImageUploadButton } from 'common/hooks/useImageUploadButton'; - -const selector = createSelector( - [generationSelector], - (generation) => { - const { initialImage } = generation; - return { - initialImage, - }; - }, - defaultSelectorOptions -); - -const InitialImagePreview = () => { - const { initialImage } = useAppSelector(selector); - const dispatch = useAppDispatch(); - const { openUploader } = useImageUploader(); - - const { - currentData: image, - isLoading, - isError, - isSuccess, - } = useGetImageDTOQuery(initialImage?.imageName ?? skipToken); - - const { getUploadButtonProps, getUploadInputProps } = useImageUploadButton({ - postUploadAction: { type: 'SET_INITIAL_IMAGE' }, - }); - - const handleDrop = useCallback( - (droppedImage: ImageDTO) => { - if (droppedImage.image_name === initialImage?.imageName) { - return; - } - dispatch(initialImageChanged(droppedImage)); - }, - [dispatch, initialImage] - ); - - const handleReset = useCallback(() => { - dispatch(clearInitialImage()); - }, [dispatch]); - - const handleUpload = useCallback(() => { - openUploader(); - }, [openUploader]); - - return ( - - - - Initial Image - - - } - onClick={handleUpload} - {...getUploadButtonProps()} - /> - } - onClick={handleReset} - isDisabled={!initialImage} - /> - - } - isUploadDisabled={true} - fitContainer - /> - - - ); -}; - -export default InitialImagePreview; diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Seed/ParamSeedRandomize.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Seed/ParamSeedRandomize.tsx index 6b1dd46780..f30d9215e8 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Seed/ParamSeedRandomize.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Seed/ParamSeedRandomize.tsx @@ -1,10 +1,8 @@ import { ChangeEvent, memo } from 'react'; - import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; import { setShouldRandomizeSeed } from 'features/parameters/store/generationSlice'; import { useTranslation } from 'react-i18next'; -import { FormControl, FormLabel, Switch, Tooltip } from '@chakra-ui/react'; import IAISwitch from 'common/components/IAISwitch'; const ParamSeedRandomize = () => { @@ -25,32 +23,6 @@ const ParamSeedRandomize = () => { onChange={handleChangeShouldRandomizeSeed} /> ); - - return ( - - - {t('parameters.randomizeSeed')} - - - - ); }; export default memo(ParamSeedRandomize); diff --git a/invokeai/frontend/web/src/features/parameters/components/Parameters/Seed/ParamSeedShuffle.tsx b/invokeai/frontend/web/src/features/parameters/components/Parameters/Seed/ParamSeedShuffle.tsx index 6442e34268..e71e2c36c0 100644 --- a/invokeai/frontend/web/src/features/parameters/components/Parameters/Seed/ParamSeedShuffle.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/Parameters/Seed/ParamSeedShuffle.tsx @@ -1,8 +1,6 @@ -import { Box } from '@chakra-ui/react'; import { NUMPY_RAND_MAX, NUMPY_RAND_MIN } from 'app/constants'; import { RootState } from 'app/store/store'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import IAIButton from 'common/components/IAIButton'; import IAIIconButton from 'common/components/IAIIconButton'; import randomInt from 'common/util/randomInt'; import { setSeed } from 'features/parameters/store/generationSlice'; @@ -29,16 +27,4 @@ export default function ParamSeedShuffle() { icon={} /> ); - - return ( - - {t('parameters.shuffle')} - - ); } diff --git a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx index 701a6ac4df..bb6e7e862d 100644 --- a/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx +++ b/invokeai/frontend/web/src/features/parameters/components/ProcessButtons/CancelButton.tsx @@ -1,33 +1,32 @@ +import { + ButtonGroup, + ButtonProps, + ButtonSpinner, + Menu, + MenuButton, + MenuItemOption, + MenuList, + MenuOptionGroup, +} from '@chakra-ui/react'; import { createSelector } from '@reduxjs/toolkit'; import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import IAIIconButton, { - IAIIconButtonProps, -} from 'common/components/IAIIconButton'; +import IAIIconButton from 'common/components/IAIIconButton'; import { systemSelector } from 'features/system/store/systemSelectors'; import { + CancelStrategy, SystemState, cancelScheduled, cancelTypeChanged, - CancelStrategy, } from 'features/system/store/systemSlice'; import { isEqual } from 'lodash-es'; -import { useCallback, memo, useMemo } from 'react'; -import { - ButtonSpinner, - ButtonGroup, - Menu, - MenuButton, - MenuList, - MenuOptionGroup, - MenuItemOption, -} from '@chakra-ui/react'; +import { memo, useCallback, useMemo } from 'react'; import { useHotkeys } from 'react-hotkeys-hook'; import { useTranslation } from 'react-i18next'; import { MdCancel, MdCancelScheduleSend } from 'react-icons/md'; -import { sessionCanceled } from 'services/api/thunks/session'; import { ChevronDownIcon } from '@chakra-ui/icons'; +import { sessionCanceled } from 'services/api/thunks/session'; const cancelButtonSelector = createSelector( systemSelector, @@ -55,7 +54,7 @@ interface CancelButtonProps { } const CancelButton = ( - props: CancelButtonProps & Omit + props: CancelButtonProps & Omit ) => { const dispatch = useAppDispatch(); const { btnGroupWidth = 'auto', ...rest } = props; @@ -145,6 +144,7 @@ const CancelButton = ( paddingY={0} colorScheme="error" minWidth={5} + {...rest} /> { iconButton?: boolean; @@ -24,6 +34,7 @@ export default function InvokeButton(props: InvokeButton) { const dispatch = useAppDispatch(); const isReady = useIsReadyToInvoke(); const activeTabName = useAppSelector(activeTabNameSelector); + const isProcessing = useAppSelector((state) => state.system.isProcessing); const handleInvoke = useCallback(() => { dispatch(clampSymmetrySteps()); @@ -48,6 +59,7 @@ export default function InvokeButton(props: InvokeButton) { {!isReady && ( @@ -68,13 +80,16 @@ export default function InvokeButton(props: InvokeButton) { icon={} isDisabled={!isReady} onClick={handleInvoke} - flexGrow={1} - w="100%" tooltip={t('parameters.invoke')} - tooltipProps={{ placement: 'bottom' }} + tooltipProps={{ placement: 'top' }} colorScheme="accent" id="invoke-button" {...rest} + sx={{ + w: 'full', + flexGrow: 1, + ...(isProcessing ? IN_PROGRESS_STYLES : {}), + }} /> ) : ( Invoke diff --git a/invokeai/frontend/web/src/features/system/components/ColorModeButton.tsx b/invokeai/frontend/web/src/features/system/components/ColorModeButton.tsx new file mode 100644 index 0000000000..9bf748146c --- /dev/null +++ b/invokeai/frontend/web/src/features/system/components/ColorModeButton.tsx @@ -0,0 +1,32 @@ +import { useColorMode } from '@chakra-ui/react'; +import IAIIconButton from 'common/components/IAIIconButton'; +import { useTranslation } from 'react-i18next'; +import { FaMoon, FaSun } from 'react-icons/fa'; + +const ColorModeButton = () => { + const { colorMode, toggleColorMode } = useColorMode(); + const { t } = useTranslation(); + + return ( + + ) : ( + + ) + } + onClick={toggleColorMode} + variant="link" + /> + ); +}; + +export default ColorModeButton; diff --git a/invokeai/frontend/web/src/features/system/components/ModelSelect.tsx b/invokeai/frontend/web/src/features/system/components/ModelSelect.tsx index f9eda624f2..8b098936b3 100644 --- a/invokeai/frontend/web/src/features/system/components/ModelSelect.tsx +++ b/invokeai/frontend/web/src/features/system/components/ModelSelect.tsx @@ -23,7 +23,7 @@ const ModelSelect = () => { (state: RootState) => state.generation.model ); - const { data: pipelineModels } = useListModelsQuery({ + const { data: pipelineModels, isLoading } = useListModelsQuery({ model_type: 'main', }); @@ -65,6 +65,8 @@ const ModelSelect = () => { ); useEffect(() => { + // If the selected model is not in the list of models, select the first one + // Handles first-run setting of models, and the user deleting the previously-selected model if (selectedModelId && pipelineModels?.ids.includes(selectedModelId)) { return; } @@ -78,13 +80,21 @@ const ModelSelect = () => { handleChangeModel(firstModel); }, [handleChangeModel, pipelineModels?.ids, selectedModelId]); - return ( + return isLoading ? ( + + ) : ( 0 ? 'Select a model' : 'No models detected!'} data={data} + error={data.length === 0} onChange={handleChangeModel} /> ); diff --git a/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx b/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx index 140a8b5978..34bd394214 100644 --- a/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx +++ b/invokeai/frontend/web/src/features/system/components/ProgressBar.tsx @@ -35,6 +35,7 @@ const ProgressBar = () => { aria-label={t('accessibility.invokeProgressBar')} isIndeterminate={isProcessing && !currentStatusHasSteps} height="full" + colorScheme="accent" /> ); }; diff --git a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx index dfba1da4ef..c9508bb5fe 100644 --- a/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx +++ b/invokeai/frontend/web/src/features/system/components/SettingsModal/SettingsModal.tsx @@ -1,5 +1,4 @@ import { - ChakraProps, Flex, Heading, Modal, @@ -39,6 +38,7 @@ import { UIState } from 'features/ui/store/uiTypes'; import { isEqual } from 'lodash-es'; import { ChangeEvent, + PropsWithChildren, ReactElement, cloneElement, useCallback, @@ -83,14 +83,6 @@ const selector = createSelector( } ); -const modalSectionStyles: ChakraProps['sx'] = { - flexDirection: 'column', - gap: 2, - p: 4, - bg: 'base.900', - borderRadius: 'base', -}; - type ConfigOptions = { shouldShowDeveloperSettings: boolean; shouldShowResetWebUiText: boolean; @@ -183,12 +175,12 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => { isCentered > - + {t('common.settingsLabel')} - + {t('settings.general')} { dispatch(setShouldConfirmOnDelete(e.target.checked)) } /> - + - + {t('settings.generation')} - + - + {t('settings.ui')} { ) } /> - + {shouldShowDeveloperSettings && ( - + {t('settings.developer')} { dispatch(setEnableImageDebugging(e.target.checked)) } /> - + )} - + {t('settings.resetWebUI')} {t('settings.resetWebUI')} @@ -283,7 +275,7 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => { {t('settings.resetWebUIDesc2')} )} - + @@ -319,3 +311,19 @@ const SettingsModal = ({ children, config }: SettingsModalProps) => { }; export default SettingsModal; + +const StyledFlex = (props: PropsWithChildren) => { + return ( + + {props.children} + + ); +}; diff --git a/invokeai/frontend/web/src/features/system/components/SiteHeader.tsx b/invokeai/frontend/web/src/features/system/components/SiteHeader.tsx index 66a2de325e..0c94c1d2f9 100644 --- a/invokeai/frontend/web/src/features/system/components/SiteHeader.tsx +++ b/invokeai/frontend/web/src/features/system/components/SiteHeader.tsx @@ -12,8 +12,8 @@ import InvokeAILogoComponent from './InvokeAILogoComponent'; import LanguagePicker from './LanguagePicker'; import ModelManagerModal from './ModelManager/ModelManagerModal'; import SettingsModal from './SettingsModal/SettingsModal'; -import ThemeChanger from './ThemeChanger'; import { useFeatureStatus } from '../hooks/useFeatureStatus'; +import ColorModeButton from './ColorModeButton'; const SiteHeader = () => { const { t } = useTranslation(); @@ -63,8 +63,6 @@ const SiteHeader = () => { /> - - {isLocalizationEnabled && } {isBugLinkEnabled && ( @@ -121,6 +119,8 @@ const SiteHeader = () => { )} + + { /> - - {isLocalizationEnabled && } {isBugLinkEnabled && ( diff --git a/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx b/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx index cd0a4eacc3..c5945140c3 100644 --- a/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx +++ b/invokeai/frontend/web/src/features/system/components/StatusIndicator.tsx @@ -35,6 +35,18 @@ const statusIndicatorSelector = createSelector( defaultSelectorOptions ); +const DARK_COLOR_MAP = { + ok: 'green.400', + working: 'yellow.400', + error: 'red.400', +}; + +const LIGHT_COLOR_MAP = { + ok: 'green.600', + working: 'yellow.500', + error: 'red.500', +}; + const StatusIndicator = () => { const { isConnected, @@ -46,7 +58,7 @@ const StatusIndicator = () => { const { t } = useTranslation(); const ref = useRef(null); - const statusColorScheme = useMemo(() => { + const statusString = useMemo(() => { if (isProcessing) { return 'working'; } @@ -90,9 +102,10 @@ const StatusIndicator = () => { sx={{ fontSize: 'sm', fontWeight: '600', - color: `${statusColorScheme}.400`, pb: '1px', userSelect: 'none', + color: LIGHT_COLOR_MAP[statusString], + _dark: { color: DARK_COLOR_MAP[statusString] }, }} > {t(statusTranslationKey as ResourceKey)} @@ -101,7 +114,14 @@ const StatusIndicator = () => { )} - + ); }; diff --git a/invokeai/frontend/web/src/features/system/components/ThemeChanger.tsx b/invokeai/frontend/web/src/features/system/components/ThemeChanger.tsx deleted file mode 100644 index d9426eecf2..0000000000 --- a/invokeai/frontend/web/src/features/system/components/ThemeChanger.tsx +++ /dev/null @@ -1,60 +0,0 @@ -import { - IconButton, - Menu, - MenuButton, - MenuItemOption, - MenuList, - MenuOptionGroup, - Tooltip, -} from '@chakra-ui/react'; -import { RootState } from 'app/store/store'; -import { useAppDispatch, useAppSelector } from 'app/store/storeHooks'; -import { setCurrentTheme } from 'features/ui/store/uiSlice'; -import i18n from 'i18n'; -import { map } from 'lodash-es'; -import { useTranslation } from 'react-i18next'; -import { FaPalette } from 'react-icons/fa'; - -export const THEMES = { - dark: i18n.t('common.darkTheme'), - light: i18n.t('common.lightTheme'), - green: i18n.t('common.greenTheme'), - ocean: i18n.t('common.oceanTheme'), -}; - -export default function ThemeChanger() { - const { t } = useTranslation(); - - const dispatch = useAppDispatch(); - const currentTheme = useAppSelector( - (state: RootState) => state.ui.currentTheme - ); - - return ( - - - } - variant="link" - aria-label={t('common.themeLabel')} - fontSize={20} - minWidth={8} - /> - - - - {map(THEMES, (themeName, themeKey: keyof typeof THEMES) => ( - dispatch(setCurrentTheme(themeKey))} - > - {themeName} - - ))} - - - - ); -} diff --git a/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx b/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx index c816c9b39e..3e2c2153e6 100644 --- a/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx +++ b/invokeai/frontend/web/src/features/ui/components/FloatingGalleryButton.tsx @@ -51,6 +51,7 @@ const FloatingGalleryButton = () => { w: 8, borderStartEndRadius: 0, borderEndEndRadius: 0, + shadow: '2xl', }} > diff --git a/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx b/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx index 4f4995ffa7..0969426339 100644 --- a/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx +++ b/invokeai/frontend/web/src/features/ui/components/FloatingParametersPanelButtons.tsx @@ -19,6 +19,7 @@ import { FaSlidersH } from 'react-icons/fa'; const floatingButtonStyles: ChakraProps['sx'] = { borderStartStartRadius: 0, borderEndStartRadius: 0, + shadow: '2xl', }; export const floatingParametersPanelButtonSelector = createSelector( diff --git a/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx b/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx index 420212fbd1..1b2ae81072 100644 --- a/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx +++ b/invokeai/frontend/web/src/features/ui/components/InvokeTabs.tsx @@ -32,10 +32,12 @@ import ImageGalleryContent from 'features/gallery/components/ImageGalleryContent import TextToImageTab from './tabs/TextToImage/TextToImageTab'; import UnifiedCanvasTab from './tabs/UnifiedCanvas/UnifiedCanvasTab'; import NodesTab from './tabs/Nodes/NodesTab'; -import { FaFont, FaImage } from 'react-icons/fa'; +import { FaFont, FaImage, FaLayerGroup } from 'react-icons/fa'; import ResizeHandle from './tabs/ResizeHandle'; import ImageTab from './tabs/ImageToImage/ImageToImageTab'; import AuxiliaryProgressIndicator from 'app/components/AuxiliaryProgressIndicator'; +import { useMinimumPanelSize } from '../hooks/useMinimumPanelSize'; +import BatchTab from './tabs/Batch/BatchTab'; export interface InvokeTabInfo { id: InvokeTabName; @@ -64,6 +66,11 @@ const tabs: InvokeTabInfo[] = [ icon: , content: , }, + // { + // id: 'batch', + // icon: , + // content: , + // }, ]; const enabledTabsSelector = createSelector( @@ -78,6 +85,9 @@ const enabledTabsSelector = createSelector( } ); +const MIN_GALLERY_WIDTH = 300; +const DEFAULT_GALLERY_PCT = 20; + const InvokeTabs = () => { const activeTab = useAppSelector(activeTabIndexSelector); const activeTabName = useAppSelector(activeTabNameSelector); @@ -150,6 +160,9 @@ const InvokeTabs = () => { [enabledTabs] ); + const { ref: galleryPanelRef, minSizePct: galleryMinSizePct } = + useMinimumPanelSize(MIN_GALLERY_WIDTH, DEFAULT_GALLERY_PCT, 'app'); + return ( { { <> DEFAULT_GALLERY_PCT + ? galleryMinSizePct + : DEFAULT_GALLERY_PCT + } + minSize={galleryMinSizePct} maxSize={50} > diff --git a/invokeai/frontend/web/src/features/ui/components/ParametersDrawer.tsx b/invokeai/frontend/web/src/features/ui/components/ParametersDrawer.tsx index b41017c2c9..0777463ec4 100644 --- a/invokeai/frontend/web/src/features/ui/components/ParametersDrawer.tsx +++ b/invokeai/frontend/web/src/features/ui/components/ParametersDrawer.tsx @@ -71,7 +71,15 @@ const ParametersDrawer = () => { onClose={handleClosePanel} > { - - {drawerContent} - + + {drawerContent} + ); diff --git a/invokeai/frontend/web/src/features/ui/components/ParametersPinnedWrapper.tsx b/invokeai/frontend/web/src/features/ui/components/ParametersPinnedWrapper.tsx index d47ca3e1ba..f327e10efc 100644 --- a/invokeai/frontend/web/src/features/ui/components/ParametersPinnedWrapper.tsx +++ b/invokeai/frontend/web/src/features/ui/components/ParametersPinnedWrapper.tsx @@ -42,18 +42,10 @@ const ParametersPinnedWrapper = (props: ParametersPinnedWrapperProps) => { h: 'full', w: 'full', position: 'absolute', + overflowY: 'auto', }} > - - - {props.children} - - + {props.children} { const langDirection = useTheme().direction as LangDirection; - + const { colorMode } = useColorMode(); const outsideClickRef = useRef(null); const defaultWidth = useMemo( @@ -160,11 +162,11 @@ const ResizableDrawer = ({ handleStyles={handleStyles} {...minMaxDimensions} sx={{ - borderColor: 'base.800', + borderColor: mode('base.200', 'base.800')(colorMode), p: 4, - bg: 'base.900', + bg: mode('base.100', 'base.900')(colorMode), height: 'full', - boxShadow: '0 0 4rem 0 rgba(0, 0, 0, 0.8)', + shadow: isOpen ? 'dark-lg' : undefined, ...containerStyles, ...sx, }} diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/Batch/BatchTab.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/Batch/BatchTab.tsx new file mode 100644 index 0000000000..811660c174 --- /dev/null +++ b/invokeai/frontend/web/src/features/ui/components/tabs/Batch/BatchTab.tsx @@ -0,0 +1,43 @@ +import { Box, Flex } from '@chakra-ui/react'; +import { useAppDispatch } from 'app/store/storeHooks'; +import { requestCanvasRescale } from 'features/canvas/store/thunks/requestCanvasScale'; +import InitialImageDisplay from 'features/parameters/components/Parameters/ImageToImage/InitialImageDisplay'; +import { memo, useCallback, useRef } from 'react'; +import { + ImperativePanelGroupHandle, + Panel, + PanelGroup, +} from 'react-resizable-panels'; +import ResizeHandle from '../ResizeHandle'; +import TextToImageTabMain from '../TextToImage/TextToImageTabMain'; +import BatchManager from 'features/batch/components/BatchManager'; + +const ImageToImageTab = () => { + const dispatch = useAppDispatch(); + const panelGroupRef = useRef(null); + + const handleDoubleClickHandle = useCallback(() => { + if (!panelGroupRef.current) { + return; + } + + panelGroupRef.current.setLayout([50, 50]); + }, []); + + return ( + + + + ); +}; + +export default memo(ImageToImageTab); diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/ResizeHandle.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/ResizeHandle.tsx index d53a4d4fef..7ef0b48784 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/ResizeHandle.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/ResizeHandle.tsx @@ -1,6 +1,7 @@ -import { Box, Flex, FlexProps } from '@chakra-ui/react'; +import { Box, Flex, FlexProps, useColorMode } from '@chakra-ui/react'; import { memo } from 'react'; import { PanelResizeHandle } from 'react-resizable-panels'; +import { mode } from 'theme/util/mode'; type ResizeHandleProps = FlexProps & { direction?: 'horizontal' | 'vertical'; @@ -8,6 +9,7 @@ type ResizeHandleProps = FlexProps & { const ResizeHandle = (props: ResizeHandleProps) => { const { direction = 'horizontal', ...rest } = props; + const { colorMode } = useColorMode(); if (direction === 'horizontal') { return ( @@ -21,7 +23,13 @@ const ResizeHandle = (props: ResizeHandleProps) => { }} {...rest} > - + ); @@ -38,7 +46,13 @@ const ResizeHandle = (props: ResizeHandleProps) => { }} {...rest} > - + ); diff --git a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabMain.tsx b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabMain.tsx index b6cfcf72c3..de21cb14eb 100644 --- a/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabMain.tsx +++ b/invokeai/frontend/web/src/features/ui/components/tabs/TextToImage/TextToImageTabMain.tsx @@ -4,13 +4,13 @@ import CurrentImageDisplay from 'features/gallery/components/CurrentImageDisplay const TextToImageTabMain = () => { return ( { const dispatch = useAppDispatch(); const { doesCanvasNeedScaling, shouldUseCanvasBetaLayout } = useAppSelector(selector); - const onDrop = useCallback( - (droppedImage: ImageDTO) => { - dispatch(setInitialCanvasImage(droppedImage)); - }, - [dispatch] - ); - const { isOver, setNodeRef: setDroppableRef, active, } = useDroppable({ id: 'unifiedCanvas', - data: { - handleDrop: onDrop, - }, + data: droppableData, }); useLayoutEffect(() => { @@ -67,14 +67,14 @@ const UnifiedCanvasContent = () => { if (shouldUseCanvasBetaLayout) { return ( { {doesCanvasNeedScaling ? : } - {active && } + {isValidDrop(droppableData, active) && ( + + )} @@ -110,11 +115,11 @@ const UnifiedCanvasContent = () => { ref={setDroppableRef} tabIndex={-1} sx={{ + layerStyle: 'first', w: 'full', h: 'full', - borderRadius: 'base', - bg: 'base.850', p: 4, + borderRadius: 'base', }} > { > {doesCanvasNeedScaling ? : } - {active && } + {isValidDrop(droppableData, active) && ( + + )} diff --git a/invokeai/frontend/web/src/features/ui/hooks/useMinimumPanelSize.ts b/invokeai/frontend/web/src/features/ui/hooks/useMinimumPanelSize.ts new file mode 100644 index 0000000000..b382b27329 --- /dev/null +++ b/invokeai/frontend/web/src/features/ui/hooks/useMinimumPanelSize.ts @@ -0,0 +1,70 @@ +// adapted from https://github.com/bvaughn/react-resizable-panels/issues/141#issuecomment-1540048714 + +import { + RefObject, + useCallback, + useLayoutEffect, + useRef, + useState, +} from 'react'; +import { ImperativePanelHandle } from 'react-resizable-panels'; + +export const useMinimumPanelSize = ( + minSizePx: number, + defaultSizePct: number, + groupId: string, + orientation: 'horizontal' | 'vertical' = 'horizontal' +): { ref: RefObject; minSizePct: number } => { + const ref = useRef(null); + const [minSizePct, setMinSizePct] = useState(defaultSizePct); + + const handleWindowResize = useCallback(() => { + const size = ref.current?.getSize(); + + if (size !== undefined && size < minSizePct) { + ref.current?.resize(minSizePct); + } + }, [minSizePct]); + + useLayoutEffect(() => { + const panelGroup = document.querySelector( + `[data-panel-group-id="${groupId}"]` + ); + const resizeHandles = document.querySelectorAll( + '[data-panel-resize-handle-id]' + ); + + if (!panelGroup) { + return; + } + const observer = new ResizeObserver(() => { + let dim = + orientation === 'horizontal' + ? panelGroup.getBoundingClientRect().width + : panelGroup.getBoundingClientRect().height; + + resizeHandles.forEach((resizeHandle) => { + dim -= + orientation === 'horizontal' + ? resizeHandle.getBoundingClientRect().width + : resizeHandle.getBoundingClientRect().height; + }); + + // Minimum size in pixels is a percentage of the PanelGroup's width/height + setMinSizePct((minSizePx / dim) * 100); + }); + observer.observe(panelGroup); + resizeHandles.forEach((resizeHandle) => { + observer.observe(resizeHandle); + }); + + window.addEventListener('resize', handleWindowResize); + + return () => { + observer.disconnect(); + window.removeEventListener('resize', handleWindowResize); + }; + }, [groupId, handleWindowResize, minSizePct, minSizePx, orientation]); + + return { ref, minSizePct }; +}; diff --git a/invokeai/frontend/web/src/features/ui/store/tabMap.ts b/invokeai/frontend/web/src/features/ui/store/tabMap.ts index becf52886e..4f683c95cb 100644 --- a/invokeai/frontend/web/src/features/ui/store/tabMap.ts +++ b/invokeai/frontend/web/src/features/ui/store/tabMap.ts @@ -4,6 +4,7 @@ export const tabMap = [ // 'generate', 'unifiedCanvas', 'nodes', + 'batch', // 'postprocessing', // 'training', ] as const; diff --git a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts index 36c514e995..38af668cac 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiSlice.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiSlice.ts @@ -8,7 +8,6 @@ import { SchedulerParam } from 'features/parameters/store/parameterZodSchemas'; export const initialUIState: UIState = { activeTab: 0, - currentTheme: 'dark', shouldPinParametersPanel: true, shouldShowParametersPanel: true, shouldShowImageDetails: false, @@ -30,9 +29,6 @@ export const uiSlice = createSlice({ setActiveTab: (state, action: PayloadAction) => { setActiveTabReducer(state, action.payload); }, - setCurrentTheme: (state, action: PayloadAction) => { - state.currentTheme = action.payload; - }, setShouldPinParametersPanel: (state, action: PayloadAction) => { state.shouldPinParametersPanel = action.payload; state.shouldShowParametersPanel = true; @@ -110,7 +106,6 @@ export const uiSlice = createSlice({ export const { setActiveTab, - setCurrentTheme, setShouldPinParametersPanel, setShouldShowParametersPanel, setShouldShowImageDetails, diff --git a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts index 2a9a82fbe8..d55a1d8fcf 100644 --- a/invokeai/frontend/web/src/features/ui/store/uiTypes.ts +++ b/invokeai/frontend/web/src/features/ui/store/uiTypes.ts @@ -16,7 +16,6 @@ export type Rect = Coordinates & Dimensions; export interface UIState { activeTab: number; - currentTheme: string; shouldPinParametersPanel: boolean; shouldShowParametersPanel: boolean; shouldShowImageDetails: boolean; diff --git a/invokeai/frontend/web/src/index.ts b/invokeai/frontend/web/src/index.ts index 274f9d5a0b..e70e756ed9 100644 --- a/invokeai/frontend/web/src/index.ts +++ b/invokeai/frontend/web/src/index.ts @@ -1,9 +1,9 @@ -export { default as InvokeAiLogoComponent } from './features/system/components/InvokeAILogoComponent'; -export { default as ThemeChanger } from './features/system/components/ThemeChanger'; -export { default as IAIPopover } from './common/components/IAIPopover'; -export { default as IAIIconButton } from './common/components/IAIIconButton'; -export { default as SettingsModal } from './features/system/components/SettingsModal/SettingsModal'; -export { default as StatusIndicator } from './features/system/components/StatusIndicator'; -export { default as ModelSelect } from './features/system/components/ModelSelect'; export { default as InvokeAIUI } from './app/components/InvokeAIUI'; export type { PartialAppConfig } from './app/types/invokeai'; +export { default as IAIIconButton } from './common/components/IAIIconButton'; +export { default as IAIPopover } from './common/components/IAIPopover'; +export { default as InvokeAiLogoComponent } from './features/system/components/InvokeAILogoComponent'; +export { default as ModelSelect } from './features/system/components/ModelSelect'; +export { default as SettingsModal } from './features/system/components/SettingsModal/SettingsModal'; +export { default as StatusIndicator } from './features/system/components/StatusIndicator'; +export { default as ColorModeButton } from './features/system/components/ColorModeButton'; diff --git a/invokeai/frontend/web/src/mantine-theme/theme.ts b/invokeai/frontend/web/src/mantine-theme/theme.ts index 081b2c3457..21dbd285f1 100644 --- a/invokeai/frontend/web/src/mantine-theme/theme.ts +++ b/invokeai/frontend/web/src/mantine-theme/theme.ts @@ -2,7 +2,7 @@ import { MantineThemeOverride } from '@mantine/core'; export const mantineTheme: MantineThemeOverride = { colorScheme: 'dark', - fontFamily: `'InterVariable', sans-serif`, + fontFamily: `'Inter Variable', sans-serif`, components: { ScrollArea: { defaultProps: { diff --git a/invokeai/frontend/web/src/services/api/endpoints/boardImages.ts b/invokeai/frontend/web/src/services/api/endpoints/boardImages.ts index cef9ab7cae..a0db3f3dff 100644 --- a/invokeai/frontend/web/src/services/api/endpoints/boardImages.ts +++ b/invokeai/frontend/web/src/services/api/endpoints/boardImages.ts @@ -1,6 +1,7 @@ import { OffsetPaginatedResults_ImageDTO_ } from 'services/api/types'; import { api } from '..'; import { paths } from '../schema'; +import { imagesApi } from './images'; type ListBoardImagesArg = paths['/api/v1/board_images/{board_id}']['get']['parameters']['path'] & @@ -41,8 +42,22 @@ export const boardImagesApi = api.injectEndpoints({ }), invalidatesTags: (result, error, arg) => [ { type: 'Board', id: arg.board_id }, - { type: 'Image', id: arg.image_name }, ], + async onQueryStarted( + { image_name, ...patch }, + { dispatch, queryFulfilled } + ) { + const patchResult = dispatch( + imagesApi.util.updateQueryData('getImageDTO', image_name, (draft) => { + Object.assign(draft, patch); + }) + ); + try { + await queryFulfilled; + } catch { + patchResult.undo(); + } + }, }), removeImageFromBoard: build.mutation({ @@ -53,8 +68,22 @@ export const boardImagesApi = api.injectEndpoints({ }), invalidatesTags: (result, error, arg) => [ { type: 'Board', id: arg.board_id }, - { type: 'Image', id: arg.image_name }, ], + async onQueryStarted( + { image_name, ...patch }, + { dispatch, queryFulfilled } + ) { + const patchResult = dispatch( + imagesApi.util.updateQueryData('getImageDTO', image_name, (draft) => { + Object.assign(draft, { board_id: null }); + }) + ); + try { + await queryFulfilled; + } catch { + patchResult.undo(); + } + }, }), }), }); diff --git a/invokeai/frontend/web/src/services/api/schema.d.ts b/invokeai/frontend/web/src/services/api/schema.d.ts index 767fe7b2b3..e542cd4ba2 100644 --- a/invokeai/frontend/web/src/services/api/schema.d.ts +++ b/invokeai/frontend/web/src/services/api/schema.d.ts @@ -76,10 +76,10 @@ export type paths = { */ get: operations["list_models"]; /** - * Update Model + * Import Model * @description Add Model */ - post: operations["update_model"]; + post: operations["import_model"]; }; "/api/v1/models/{model_name}": { /** @@ -650,7 +650,7 @@ export type components = { end_step_percent: number; /** * Control Mode - * @description The contorl mode to use + * @description The control mode to use * @default balanced * @enum {string} */ @@ -1030,7 +1030,7 @@ export type components = { * @description The nodes in this graph */ nodes?: { - [key: string]: (components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["PipelineModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["UpscaleInvocation"] | components["schemas"]["RestoreFaceInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"]) | undefined; + [key: string]: (components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["PipelineModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["UpscaleInvocation"] | components["schemas"]["RestoreFaceInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"]) | undefined; }; /** * Edges @@ -1073,7 +1073,7 @@ export type components = { * @description The results of node executions */ results: { - [key: string]: (components["schemas"]["ImageOutput"] | components["schemas"]["MaskOutput"] | components["schemas"]["ControlOutput"] | components["schemas"]["ModelLoaderOutput"] | components["schemas"]["LoraLoaderOutput"] | components["schemas"]["PromptOutput"] | components["schemas"]["PromptCollectionOutput"] | components["schemas"]["CompelOutput"] | components["schemas"]["IntOutput"] | components["schemas"]["FloatOutput"] | components["schemas"]["LatentsOutput"] | components["schemas"]["IntCollectionOutput"] | components["schemas"]["FloatCollectionOutput"] | components["schemas"]["NoiseOutput"] | components["schemas"]["GraphInvocationOutput"] | components["schemas"]["IterateInvocationOutput"] | components["schemas"]["CollectInvocationOutput"]) | undefined; + [key: string]: (components["schemas"]["ImageOutput"] | components["schemas"]["MaskOutput"] | components["schemas"]["ControlOutput"] | components["schemas"]["ModelLoaderOutput"] | components["schemas"]["LoraLoaderOutput"] | components["schemas"]["PromptOutput"] | components["schemas"]["PromptCollectionOutput"] | components["schemas"]["CompelOutput"] | components["schemas"]["IntOutput"] | components["schemas"]["FloatOutput"] | components["schemas"]["LatentsOutput"] | components["schemas"]["IntCollectionOutput"] | components["schemas"]["FloatCollectionOutput"] | components["schemas"]["ImageCollectionOutput"] | components["schemas"]["NoiseOutput"] | components["schemas"]["GraphInvocationOutput"] | components["schemas"]["IterateInvocationOutput"] | components["schemas"]["CollectInvocationOutput"]) | undefined; }; /** * Errors @@ -1276,6 +1276,53 @@ export type components = { */ channel?: "A" | "R" | "G" | "B"; }; + /** + * ImageCollectionInvocation + * @description Load a collection of images and provide it as output. + */ + ImageCollectionInvocation: { + /** + * Id + * @description The id of this node. Must be unique among all nodes. + */ + id: string; + /** + * Is Intermediate + * @description Whether or not this node is an intermediate node. + * @default false + */ + is_intermediate?: boolean; + /** + * Type + * @default image_collection + * @enum {string} + */ + type?: "image_collection"; + /** + * Images + * @description The image collection to load + * @default [] + */ + images?: (components["schemas"]["ImageField"])[]; + }; + /** + * ImageCollectionOutput + * @description A collection of images + */ + ImageCollectionOutput: { + /** + * Type + * @default image_collection + * @enum {string} + */ + type: "image_collection"; + /** + * Collection + * @description The output images + * @default [] + */ + collection: (components["schemas"]["ImageField"])[]; + }; /** * ImageConvertInvocation * @description Converts an image to a different mode. @@ -1928,6 +1975,20 @@ export type components = { */ thumbnail_url: string; }; + /** ImportModelRequest */ + ImportModelRequest: { + /** + * Name + * @description A model path, repo_id or URL to import + */ + name: string; + /** + * Prediction Type + * @description Prediction type for SDv2 checkpoint files + * @enum {string} + */ + prediction_type?: "epsilon" | "v_prediction" | "sample"; + }; /** * InfillColorInvocation * @description Infills transparent areas of an image with a solid color @@ -2440,6 +2501,64 @@ export type components = { */ strength?: number; }; + /** + * LeresImageProcessorInvocation + * @description Applies leres processing to image + */ + LeresImageProcessorInvocation: { + /** + * Id + * @description The id of this node. Must be unique among all nodes. + */ + id: string; + /** + * Is Intermediate + * @description Whether or not this node is an intermediate node. + * @default false + */ + is_intermediate?: boolean; + /** + * Type + * @default leres_image_processor + * @enum {string} + */ + type?: "leres_image_processor"; + /** + * Image + * @description The image to process + */ + image?: components["schemas"]["ImageField"]; + /** + * Thr A + * @description Leres parameter `thr_a` + * @default 0 + */ + thr_a?: number; + /** + * Thr B + * @description Leres parameter `thr_b` + * @default 0 + */ + thr_b?: number; + /** + * Boost + * @description Whether to use boost mode + * @default false + */ + boost?: boolean; + /** + * Detect Resolution + * @description The pixel resolution for detection + * @default 512 + */ + detect_resolution?: number; + /** + * Image Resolution + * @description The pixel resolution for the output image + * @default 512 + */ + image_resolution?: number; + }; /** * LineartAnimeImageProcessorInvocation * @description Applies line art anime processing to image @@ -2907,7 +3026,7 @@ export type components = { * @description An enumeration. * @enum {string} */ - ModelType: "pipeline" | "vae" | "lora" | "controlnet" | "embedding"; + ModelType: "main" | "vae" | "lora" | "controlnet" | "embedding"; /** * ModelVariantType * @description An enumeration. @@ -2993,12 +3112,6 @@ export type components = { * @default 512 */ height?: number; - /** - * Perlin - * @description The amount of perlin noise to add to the noise - * @default 0 - */ - perlin?: number; /** * Use Cpu * @description Use CPU for noise generation (for reproducible results across platforms) @@ -3697,11 +3810,33 @@ export type components = { antialias?: boolean; }; /** - * SchedulerPredictionType - * @description An enumeration. - * @enum {string} + * SegmentAnythingProcessorInvocation + * @description Applies segment anything processing to image */ - SchedulerPredictionType: "epsilon" | "v_prediction" | "sample"; + SegmentAnythingProcessorInvocation: { + /** + * Id + * @description The id of this node. Must be unique among all nodes. + */ + id: string; + /** + * Is Intermediate + * @description Whether or not this node is an intermediate node. + * @default false + */ + is_intermediate?: boolean; + /** + * Type + * @default segment_anything_processor + * @enum {string} + */ + type?: "segment_anything_processor"; + /** + * Image + * @description The image to process + */ + image?: components["schemas"]["ImageField"]; + }; /** * ShowImageInvocation * @description Displays a provided image, and passes it forward in the pipeline. @@ -3739,7 +3874,7 @@ export type components = { * Type * @enum {string} */ - type: "pipeline"; + type: "main"; /** Path */ path: string; /** Description */ @@ -3753,7 +3888,7 @@ export type components = { /** Vae */ vae?: string; /** Config */ - config?: string; + config: string; variant: components["schemas"]["ModelVariantType"]; }; /** StableDiffusion1ModelDiffusersConfig */ @@ -3765,7 +3900,7 @@ export type components = { * Type * @enum {string} */ - type: "pipeline"; + type: "main"; /** Path */ path: string; /** Description */ @@ -3789,7 +3924,7 @@ export type components = { * Type * @enum {string} */ - type: "pipeline"; + type: "main"; /** Path */ path: string; /** Description */ @@ -3803,11 +3938,8 @@ export type components = { /** Vae */ vae?: string; /** Config */ - config?: string; + config: string; variant: components["schemas"]["ModelVariantType"]; - prediction_type: components["schemas"]["SchedulerPredictionType"]; - /** Upcast Attention */ - upcast_attention: boolean; }; /** StableDiffusion2ModelDiffusersConfig */ StableDiffusion2ModelDiffusersConfig: { @@ -3818,7 +3950,7 @@ export type components = { * Type * @enum {string} */ - type: "pipeline"; + type: "main"; /** Path */ path: string; /** Description */ @@ -3832,9 +3964,6 @@ export type components = { /** Vae */ vae?: string; variant: components["schemas"]["ModelVariantType"]; - prediction_type: components["schemas"]["SchedulerPredictionType"]; - /** Upcast Attention */ - upcast_attention: boolean; }; /** * StepParamEasingInvocation @@ -4044,6 +4173,40 @@ export type components = { model_format: null; error?: components["schemas"]["ModelError"]; }; + /** + * TileResamplerProcessorInvocation + * @description Base class for invocations that preprocess images for ControlNet + */ + TileResamplerProcessorInvocation: { + /** + * Id + * @description The id of this node. Must be unique among all nodes. + */ + id: string; + /** + * Is Intermediate + * @description Whether or not this node is an intermediate node. + * @default false + */ + is_intermediate?: boolean; + /** + * Type + * @default tile_image_processor + * @enum {string} + */ + type?: "tile_image_processor"; + /** + * Image + * @description The image to process + */ + image?: components["schemas"]["ImageField"]; + /** + * Down Sampling Rate + * @description Down sampling rate + * @default 1 + */ + down_sampling_rate?: number; + }; /** UNetField */ UNetField: { /** @@ -4311,7 +4474,7 @@ export type operations = { }; requestBody: { content: { - "application/json": components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["PipelineModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["UpscaleInvocation"] | components["schemas"]["RestoreFaceInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"]; + "application/json": components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["PipelineModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["UpscaleInvocation"] | components["schemas"]["RestoreFaceInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"]; }; }; responses: { @@ -4348,7 +4511,7 @@ export type operations = { }; requestBody: { content: { - "application/json": components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["PipelineModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["UpscaleInvocation"] | components["schemas"]["RestoreFaceInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"]; + "application/json": components["schemas"]["LoadImageInvocation"] | components["schemas"]["ShowImageInvocation"] | components["schemas"]["ImageCropInvocation"] | components["schemas"]["ImagePasteInvocation"] | components["schemas"]["MaskFromAlphaInvocation"] | components["schemas"]["ImageMultiplyInvocation"] | components["schemas"]["ImageChannelInvocation"] | components["schemas"]["ImageConvertInvocation"] | components["schemas"]["ImageBlurInvocation"] | components["schemas"]["ImageResizeInvocation"] | components["schemas"]["ImageScaleInvocation"] | components["schemas"]["ImageLerpInvocation"] | components["schemas"]["ImageInverseLerpInvocation"] | components["schemas"]["ControlNetInvocation"] | components["schemas"]["ImageProcessorInvocation"] | components["schemas"]["PipelineModelLoaderInvocation"] | components["schemas"]["LoraLoaderInvocation"] | components["schemas"]["DynamicPromptInvocation"] | components["schemas"]["CompelInvocation"] | components["schemas"]["AddInvocation"] | components["schemas"]["SubtractInvocation"] | components["schemas"]["MultiplyInvocation"] | components["schemas"]["DivideInvocation"] | components["schemas"]["RandomIntInvocation"] | components["schemas"]["ParamIntInvocation"] | components["schemas"]["ParamFloatInvocation"] | components["schemas"]["TextToLatentsInvocation"] | components["schemas"]["LatentsToImageInvocation"] | components["schemas"]["ResizeLatentsInvocation"] | components["schemas"]["ScaleLatentsInvocation"] | components["schemas"]["ImageToLatentsInvocation"] | components["schemas"]["CvInpaintInvocation"] | components["schemas"]["RangeInvocation"] | components["schemas"]["RangeOfSizeInvocation"] | components["schemas"]["RandomRangeInvocation"] | components["schemas"]["ImageCollectionInvocation"] | components["schemas"]["FloatLinearRangeInvocation"] | components["schemas"]["StepParamEasingInvocation"] | components["schemas"]["NoiseInvocation"] | components["schemas"]["UpscaleInvocation"] | components["schemas"]["RestoreFaceInvocation"] | components["schemas"]["InpaintInvocation"] | components["schemas"]["InfillColorInvocation"] | components["schemas"]["InfillTileInvocation"] | components["schemas"]["InfillPatchMatchInvocation"] | components["schemas"]["GraphInvocation"] | components["schemas"]["IterateInvocation"] | components["schemas"]["CollectInvocation"] | components["schemas"]["CannyImageProcessorInvocation"] | components["schemas"]["HedImageProcessorInvocation"] | components["schemas"]["LineartImageProcessorInvocation"] | components["schemas"]["LineartAnimeImageProcessorInvocation"] | components["schemas"]["OpenposeImageProcessorInvocation"] | components["schemas"]["MidasDepthImageProcessorInvocation"] | components["schemas"]["NormalbaeImageProcessorInvocation"] | components["schemas"]["MlsdImageProcessorInvocation"] | components["schemas"]["PidiImageProcessorInvocation"] | components["schemas"]["ContentShuffleImageProcessorInvocation"] | components["schemas"]["ZoeDepthImageProcessorInvocation"] | components["schemas"]["MediapipeFaceProcessorInvocation"] | components["schemas"]["LeresImageProcessorInvocation"] | components["schemas"]["TileResamplerProcessorInvocation"] | components["schemas"]["SegmentAnythingProcessorInvocation"] | components["schemas"]["LatentsToLatentsInvocation"]; }; }; responses: { @@ -4568,13 +4731,13 @@ export type operations = { }; }; /** - * Update Model + * Import Model * @description Add Model */ - update_model: { + import_model: { requestBody: { content: { - "application/json": components["schemas"]["CreateModelRequest"]; + "application/json": components["schemas"]["ImportModelRequest"]; }; }; responses: { @@ -4947,6 +5110,10 @@ export type operations = { */ delete_board: { parameters: { + query?: { + /** @description Permanently delete all images on the board */ + include_images?: boolean; + }; path: { /** @description The id of board to delete */ board_id: string; diff --git a/invokeai/frontend/web/src/services/api/thunks/image.ts b/invokeai/frontend/web/src/services/api/thunks/image.ts index a8b3dec5a7..d6e502bc54 100644 --- a/invokeai/frontend/web/src/services/api/thunks/image.ts +++ b/invokeai/frontend/web/src/services/api/thunks/image.ts @@ -1,6 +1,6 @@ import queryString from 'query-string'; import { createAppAsyncThunk } from 'app/store/storeUtils'; -import { selectImagesAll } from 'features/gallery/store/imagesSlice'; +import { selectImagesAll } from 'features/gallery/store/gallerySlice'; import { size } from 'lodash-es'; import { paths } from 'services/api/schema'; import { $client } from 'services/api/client'; @@ -112,6 +112,10 @@ type UploadedToastAction = { type: 'TOAST_UPLOADED'; }; +type AddToBatchAction = { + type: 'ADD_TO_BATCH'; +}; + export type PostUploadAction = | ControlNetAction | InitialImageAction @@ -119,12 +123,12 @@ export type PostUploadAction = | CanvasInitialImageAction | CanvasMergedAction | CanvasSavedToGalleryAction - | UploadedToastAction; + | UploadedToastAction + | AddToBatchAction; type UploadImageArg = paths['/api/v1/images/']['post']['parameters']['query'] & { file: File; - // file: paths['/api/v1/images/']['post']['requestBody']['content']['multipart/form-data']['file']; postUploadAction?: PostUploadAction; }; @@ -284,8 +288,7 @@ export const receivedPageOfImages = createAppAsyncThunk< const { get } = $client.get(); const state = getState(); - const { categories } = state.images; - const { selectedBoardId } = state.boards; + const { categories, selectedBoardId } = state.gallery; const images = selectImagesAll(state).filter((i) => { const isInCategory = categories.includes(i.image_category); diff --git a/invokeai/frontend/web/src/services/api/thunks/schema.ts b/invokeai/frontend/web/src/services/api/thunks/schema.ts index b63a78943b..86d9f06eb4 100644 --- a/invokeai/frontend/web/src/services/api/thunks/schema.ts +++ b/invokeai/frontend/web/src/services/api/thunks/schema.ts @@ -1,7 +1,5 @@ -import SwaggerParser from '@apidevtools/swagger-parser'; import { createAsyncThunk } from '@reduxjs/toolkit'; import { log } from 'app/logging/useLogger'; -import { OpenAPIV3 } from 'openapi-types'; const schemaLog = log.child({ namespace: 'schema' }); @@ -29,12 +27,13 @@ export const receivedOpenAPISchema = createAsyncThunk( 'nodes/receivedOpenAPISchema', async (_, { dispatch, rejectWithValue }) => { try { - const dereferencedSchema = (await SwaggerParser.dereference( - 'openapi.json' - )) as OpenAPIV3.Document; + const response = await fetch(`openapi.json`); + const openAPISchema = await response.json(); + + schemaLog.info({ openAPISchema }, 'Received OpenAPI schema'); const schemaJSON = JSON.parse( - JSON.stringify(dereferencedSchema, getCircularReplacer()) + JSON.stringify(openAPISchema, getCircularReplacer()) ); return schemaJSON; diff --git a/invokeai/frontend/web/src/services/api/types.d.ts b/invokeai/frontend/web/src/services/api/types.d.ts index 2a2f90f434..12c072509b 100644 --- a/invokeai/frontend/web/src/services/api/types.d.ts +++ b/invokeai/frontend/web/src/services/api/types.d.ts @@ -58,6 +58,7 @@ export type LatentsToLatentsInvocation = N<'LatentsToLatentsInvocation'>; export type ImageToLatentsInvocation = N<'ImageToLatentsInvocation'>; export type LatentsToImageInvocation = N<'LatentsToImageInvocation'>; export type PipelineModelLoaderInvocation = N<'PipelineModelLoaderInvocation'>; +export type ImageCollectionInvocation = N<'ImageCollectionInvocation'>; // ControlNet Nodes export type ControlNetInvocation = N<'ControlNetInvocation'>; diff --git a/invokeai/frontend/web/src/theme/colors/colors.ts b/invokeai/frontend/web/src/theme/colors/colors.ts new file mode 100644 index 0000000000..bcb2e43c0b --- /dev/null +++ b/invokeai/frontend/web/src/theme/colors/colors.ts @@ -0,0 +1,24 @@ +import { InvokeAIThemeColors } from 'theme/themeTypes'; +import { generateColorPalette } from 'theme/util/generateColorPalette'; + +const BASE = { H: 220, S: 16 }; +const ACCENT = { H: 250, S: 52 }; +const WORKING = { H: 47, S: 50 }; +const WARNING = { H: 28, S: 50 }; +const OK = { H: 113, S: 50 }; +const ERROR = { H: 0, S: 50 }; + +export const InvokeAIColors: InvokeAIThemeColors = { + base: generateColorPalette(BASE.H, BASE.S), + baseAlpha: generateColorPalette(BASE.H, BASE.S, true), + accent: generateColorPalette(ACCENT.H, ACCENT.S), + accentAlpha: generateColorPalette(ACCENT.H, ACCENT.S, true), + working: generateColorPalette(WORKING.H, WORKING.S), + workingAlpha: generateColorPalette(WORKING.H, WORKING.S, true), + warning: generateColorPalette(WARNING.H, WARNING.S), + warningAlpha: generateColorPalette(WARNING.H, WARNING.S, true), + ok: generateColorPalette(OK.H, OK.S), + okAlpha: generateColorPalette(OK.H, OK.S, true), + error: generateColorPalette(ERROR.H, ERROR.S), + errorAlpha: generateColorPalette(ERROR.H, ERROR.S, true), +}; diff --git a/invokeai/frontend/web/src/theme/colors/greenTea.ts b/invokeai/frontend/web/src/theme/colors/greenTea.ts deleted file mode 100644 index 318aecbc61..0000000000 --- a/invokeai/frontend/web/src/theme/colors/greenTea.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { InvokeAIThemeColors } from 'theme/themeTypes'; -import { generateColorPalette } from '../util/generateColorPalette'; - -export const greenTeaThemeColors: InvokeAIThemeColors = { - base: generateColorPalette(223, 10), - baseAlpha: generateColorPalette(223, 10, false, true), - accent: generateColorPalette(160, 60), - accentAlpha: generateColorPalette(160, 60, false, true), - working: generateColorPalette(47, 68), - workingAlpha: generateColorPalette(47, 68, false, true), - warning: generateColorPalette(28, 75), - warningAlpha: generateColorPalette(28, 75, false, true), - ok: generateColorPalette(122, 49), - okAlpha: generateColorPalette(122, 49, false, true), - error: generateColorPalette(0, 50), - errorAlpha: generateColorPalette(0, 50, false, true), - gridLineColor: 'rgba(255, 255, 255, 0.15)', -}; diff --git a/invokeai/frontend/web/src/theme/colors/invokeAI.ts b/invokeai/frontend/web/src/theme/colors/invokeAI.ts deleted file mode 100644 index 82db58bd35..0000000000 --- a/invokeai/frontend/web/src/theme/colors/invokeAI.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { InvokeAIThemeColors } from 'theme/themeTypes'; -import { generateColorPalette } from 'theme/util/generateColorPalette'; - -export const invokeAIThemeColors: InvokeAIThemeColors = { - base: generateColorPalette(220, 15), - baseAlpha: generateColorPalette(220, 15, false, true), - accent: generateColorPalette(250, 50), - accentAlpha: generateColorPalette(250, 50, false, true), - working: generateColorPalette(47, 67), - workingAlpha: generateColorPalette(47, 67, false, true), - warning: generateColorPalette(28, 75), - warningAlpha: generateColorPalette(28, 75, false, true), - ok: generateColorPalette(113, 70), - okAlpha: generateColorPalette(113, 70, false, true), - error: generateColorPalette(0, 76), - errorAlpha: generateColorPalette(0, 76, false, true), - gridLineColor: 'rgba(150, 150, 180, 0.15)', -}; diff --git a/invokeai/frontend/web/src/theme/colors/lightTheme.ts b/invokeai/frontend/web/src/theme/colors/lightTheme.ts deleted file mode 100644 index 2fdbd1a769..0000000000 --- a/invokeai/frontend/web/src/theme/colors/lightTheme.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { InvokeAIThemeColors } from 'theme/themeTypes'; -import { generateColorPalette } from '../util/generateColorPalette'; - -export const lightThemeColors: InvokeAIThemeColors = { - base: generateColorPalette(223, 10, true), - baseAlpha: generateColorPalette(223, 10, true, true), - accent: generateColorPalette(40, 80, true), - accentAlpha: generateColorPalette(40, 80, true, true), - working: generateColorPalette(47, 68, true), - workingAlpha: generateColorPalette(47, 68, true, true), - warning: generateColorPalette(28, 75, true), - warningAlpha: generateColorPalette(28, 75, true, true), - ok: generateColorPalette(122, 49, true), - okAlpha: generateColorPalette(122, 49, true, true), - error: generateColorPalette(0, 50, true), - errorAlpha: generateColorPalette(0, 50, true, true), - gridLineColor: 'rgba(0, 0, 0, 0.15)', -}; diff --git a/invokeai/frontend/web/src/theme/colors/oceanBlue.ts b/invokeai/frontend/web/src/theme/colors/oceanBlue.ts deleted file mode 100644 index 952e0a5066..0000000000 --- a/invokeai/frontend/web/src/theme/colors/oceanBlue.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { InvokeAIThemeColors } from 'theme/themeTypes'; -import { generateColorPalette } from '../util/generateColorPalette'; - -export const oceanBlueColors: InvokeAIThemeColors = { - base: generateColorPalette(220, 30), - baseAlpha: generateColorPalette(220, 30, false, true), - accent: generateColorPalette(210, 80), - accentAlpha: generateColorPalette(210, 80, false, true), - working: generateColorPalette(47, 68), - workingAlpha: generateColorPalette(47, 68, false, true), - warning: generateColorPalette(28, 75), - warningAlpha: generateColorPalette(28, 75, false, true), - ok: generateColorPalette(122, 49), - okAlpha: generateColorPalette(122, 49, false, true), - error: generateColorPalette(0, 100), - errorAlpha: generateColorPalette(0, 100, false, true), - gridLineColor: 'rgba(136, 148, 184, 0.15)', -}; diff --git a/invokeai/frontend/web/src/theme/components/accordion.ts b/invokeai/frontend/web/src/theme/components/accordion.ts index 3477548c70..912e55d35b 100644 --- a/invokeai/frontend/web/src/theme/components/accordion.ts +++ b/invokeai/frontend/web/src/theme/components/accordion.ts @@ -3,6 +3,7 @@ import { createMultiStyleConfigHelpers, defineStyle, } from '@chakra-ui/styled-system'; +import { mode } from '@chakra-ui/theme-tools'; const { definePartsStyle, defineMultiStyleConfig } = createMultiStyleConfigHelpers(parts.keys); @@ -18,16 +19,16 @@ const invokeAIButton = defineStyle((props) => { fontSize: 'sm', border: 'none', borderRadius: 'base', - bg: `${c}.800`, - color: 'base.100', + bg: mode(`${c}.200`, `${c}.700`)(props), + color: mode(`${c}.900`, `${c}.100`)(props), _hover: { - bg: `${c}.700`, + bg: mode(`${c}.250`, `${c}.650`)(props), }, _expanded: { - bg: `${c}.750`, + bg: mode(`${c}.250`, `${c}.650`)(props), borderBottomRadius: 'none', _hover: { - bg: `${c}.700`, + bg: mode(`${c}.300`, `${c}.600`)(props), }, }, }; @@ -36,7 +37,7 @@ const invokeAIButton = defineStyle((props) => { const invokeAIPanel = defineStyle((props) => { const { colorScheme: c } = props; return { - bg: `${c}.800`, + bg: mode(`${c}.100`, `${c}.800`)(props), borderRadius: 'base', borderTopRadius: 'none', }; diff --git a/invokeai/frontend/web/src/theme/components/button.ts b/invokeai/frontend/web/src/theme/components/button.ts index 879b3dba96..7bb8a39a71 100644 --- a/invokeai/frontend/web/src/theme/components/button.ts +++ b/invokeai/frontend/web/src/theme/components/button.ts @@ -1,47 +1,81 @@ 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: `${c}.600`, - color: `${c}.100`, - svg: { - fill: `${c}.100`, - }, - }; - return { - bg: `${c}.700`, - color: `${c}.100`, - borderRadius: 'base', - svg: { - fill: `${c}.100`, - }, - _disabled, - _hover: { - bg: `${c}.650`, - color: `${c}.50`, + if (c === 'base') { + const _disabled = { + bg: mode('base.150', 'base.700')(props), + color: mode('base.500', 'base.500')(props), svg: { - fill: `${c}.50`, + fill: mode('base.500', 'base.500')(props), }, - _disabled, - }, - _checked: { - bg: 'accent.700', - color: 'accent.100', + opacity: 1, + }; + + return { + bg: mode('base.200', 'base.600')(props), + color: mode('base.850', 'base.100')(props), + borderRadius: 'base', + textShadow: mode( + '0 0 0.3rem var(--invokeai-colors-base-50)', + '0 0 0.3rem var(--invokeai-colors-base-900)' + )(props), svg: { - fill: 'accent.100', + fill: mode('base.850', 'base.100')(props), + filter: mode( + 'drop-shadow(0px 0px 0.3rem var(--invokeai-colors-base-100))', + 'drop-shadow(0px 0px 0.3rem var(--invokeai-colors-base-800))' + )(props), }, - _disabled, _hover: { - bg: 'accent.600', - color: 'accent.50', + bg: mode('base.300', 'base.500')(props), + color: mode('base.900', 'base.50')(props), svg: { - fill: 'accent.50', + fill: mode('base.900', 'base.50')(props), }, _disabled, }, + _disabled, + }; + } + + const _disabled = { + bg: mode(`${c}.250`, `${c}.700`)(props), + color: mode(`${c}.50`, `${c}.500`)(props), + svg: { + fill: mode(`${c}.50`, `${c}.500`)(props), + filter: 'unset', + }, + opacity: 1, + filter: mode(undefined, 'saturate(65%)')(props), + }; + + return { + bg: mode(`${c}.400`, `${c}.600`)(props), + color: mode(`base.50`, `base.100`)(props), + borderRadius: 'base', + textShadow: mode( + `0 0 0.3rem var(--invokeai-colors-${c}-600)`, + `0 0 0.3rem var(--invokeai-colors-${c}-800)` + )(props), + svg: { + fill: mode(`base.50`, `base.100`)(props), + filter: mode( + `drop-shadow(0px 0px 0.3rem var(--invokeai-colors-${c}-600))`, + `drop-shadow(0px 0px 0.3rem var(--invokeai-colors-${c}-800))` + )(props), + }, + _disabled, + _hover: { + bg: mode(`${c}.500`, `${c}.500`)(props), + color: mode('white', `base.50`)(props), + svg: { + fill: mode('white', `base.50`)(props), + }, + _disabled, }, }; }); diff --git a/invokeai/frontend/web/src/theme/components/checkbox.ts b/invokeai/frontend/web/src/theme/components/checkbox.ts index ec61706715..58871237e5 100644 --- a/invokeai/frontend/web/src/theme/components/checkbox.ts +++ b/invokeai/frontend/web/src/theme/components/checkbox.ts @@ -3,6 +3,7 @@ import { createMultiStyleConfigHelpers, defineStyle, } from '@chakra-ui/styled-system'; +import { mode } from '@chakra-ui/theme-tools'; const { definePartsStyle, defineMultiStyleConfig } = createMultiStyleConfigHelpers(parts.keys); @@ -11,14 +12,18 @@ const invokeAIControl = defineStyle((props) => { const { colorScheme: c } = props; return { + bg: mode('base.200', 'base.700')(props), + borderColor: mode('base.200', 'base.700')(props), + color: mode('base.900', 'base.100')(props), + _checked: { - bg: `${c}.200`, - borderColor: `${c}.200`, - color: 'base.900', + bg: mode(`${c}.300`, `${c}.600`)(props), + borderColor: mode(`${c}.300`, `${c}.600`)(props), + color: mode(`${c}.900`, `${c}.100`)(props), _hover: { - bg: `${c}.300`, - borderColor: `${c}.300`, + bg: mode(`${c}.400`, `${c}.500`)(props), + borderColor: mode(`${c}.400`, `${c}.500`)(props), }, _disabled: { @@ -29,9 +34,9 @@ const invokeAIControl = defineStyle((props) => { }, _indeterminate: { - bg: `${c}.200`, - borderColor: `${c}.200`, - color: 'base.900', + bg: mode(`${c}.300`, `${c}.600`)(props), + borderColor: mode(`${c}.300`, `${c}.600`)(props), + color: mode(`${c}.900`, `${c}.100`)(props), }, _disabled: { @@ -44,7 +49,7 @@ const invokeAIControl = defineStyle((props) => { }, _invalid: { - borderColor: 'red.300', + borderColor: mode('error.600', 'error.300')(props), }, }; }); diff --git a/invokeai/frontend/web/src/theme/components/formLabel.ts b/invokeai/frontend/web/src/theme/components/formLabel.ts index 0ff7c6cdea..866bb7beb1 100644 --- a/invokeai/frontend/web/src/theme/components/formLabel.ts +++ b/invokeai/frontend/web/src/theme/components/formLabel.ts @@ -1,6 +1,7 @@ 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, @@ -12,7 +13,7 @@ const invokeAI = defineStyle((_props) => { _disabled: { opacity: 0.4, }, - color: 'base.300', + color: mode('base.700', 'base.300')(props), }; }); diff --git a/invokeai/frontend/web/src/theme/components/menu.ts b/invokeai/frontend/web/src/theme/components/menu.ts index 597e989953..324720a040 100644 --- a/invokeai/frontend/web/src/theme/components/menu.ts +++ b/invokeai/frontend/web/src/theme/components/menu.ts @@ -1,38 +1,42 @@ import { menuAnatomy } from '@chakra-ui/anatomy'; import { createMultiStyleConfigHelpers } from '@chakra-ui/react'; +import { mode } from '@chakra-ui/theme-tools'; const { definePartsStyle, defineMultiStyleConfig } = createMultiStyleConfigHelpers(menuAnatomy.keys); // define the base component styles -const invokeAI = definePartsStyle({ +const invokeAI = definePartsStyle((props) => ({ // define the part you're going to style button: { // this will style the MenuButton component - fontWeight: '600', - bg: 'base.500', - color: 'base.200', + fontWeight: 500, + bg: mode('base.300', 'base.500')(props), + color: mode('base.900', 'base.100')(props), _hover: { - bg: 'base.600', - color: 'white', + bg: mode('base.400', 'base.600')(props), + color: mode('base.900', 'base.50')(props), + fontWeight: 600, }, }, list: { zIndex: 9999, - bg: 'base.800', + bg: mode('base.200', 'base.800')(props), + shadow: 'dark-lg', + border: 'none', }, item: { // this will style the MenuItem and MenuItemOption components fontSize: 'sm', - bg: 'base.800', + bg: mode('base.200', 'base.800')(props), _hover: { - bg: 'base.750', + bg: mode('base.300', 'base.700')(props), }, _focus: { - bg: 'base.700', + bg: mode('base.400', 'base.600')(props), }, }, -}); +})); export const menuTheme = defineMultiStyleConfig({ variants: { diff --git a/invokeai/frontend/web/src/theme/components/modal.ts b/invokeai/frontend/web/src/theme/components/modal.ts index 1f6900278a..8310d9d46c 100644 --- a/invokeai/frontend/web/src/theme/components/modal.ts +++ b/invokeai/frontend/web/src/theme/components/modal.ts @@ -3,28 +3,31 @@ import { createMultiStyleConfigHelpers, defineStyle, } from '@chakra-ui/styled-system'; +import { mode } from '@chakra-ui/theme-tools'; const { defineMultiStyleConfig, definePartsStyle } = createMultiStyleConfigHelpers(parts.keys); -const invokeAIOverlay = defineStyle({ - bg: 'blackAlpha.600', -}); +const invokeAIOverlay = defineStyle((props) => ({ + bg: mode('blackAlpha.700', 'blackAlpha.700')(props), +})); const invokeAIDialogContainer = defineStyle({}); -const invokeAIDialog = defineStyle((_props) => { +const invokeAIDialog = defineStyle((props) => { return { - bg: 'base.850', + layerStyle: 'first', maxH: '80vh', }; }); -const invokeAIHeader = defineStyle((_props) => { +const invokeAIHeader = defineStyle((props) => { return { fontWeight: '600', fontSize: 'lg', - color: 'base.200', + layerStyle: 'first', + borderTopRadius: 'base', + borderInlineEndRadius: 'base', }; }); @@ -37,7 +40,7 @@ const invokeAIBody = defineStyle({ const invokeAIFooter = defineStyle({}); export const invokeAI = definePartsStyle((props) => ({ - overlay: invokeAIOverlay, + overlay: invokeAIOverlay(props), dialogContainer: invokeAIDialogContainer, dialog: invokeAIDialog(props), header: invokeAIHeader(props), diff --git a/invokeai/frontend/web/src/theme/components/numberInput.ts b/invokeai/frontend/web/src/theme/components/numberInput.ts index 935f21077b..681fa6f566 100644 --- a/invokeai/frontend/web/src/theme/components/numberInput.ts +++ b/invokeai/frontend/web/src/theme/components/numberInput.ts @@ -5,6 +5,7 @@ import { } from '@chakra-ui/styled-system'; import { getInputOutlineStyles } from '../util/getInputOutlineStyles'; +import { mode } from '@chakra-ui/theme-tools'; const { defineMultiStyleConfig, definePartsStyle } = createMultiStyleConfigHelpers(parts.keys); @@ -33,7 +34,7 @@ const invokeAIStepperGroup = defineStyle((_props) => { }; }); -const invokeAIStepper = defineStyle((_props) => { +const invokeAIStepper = defineStyle((props) => { return { border: 'none', // expand arrow hitbox @@ -43,11 +44,11 @@ const invokeAIStepper = defineStyle((_props) => { my: 0, svg: { - color: 'base.300', + color: mode('base.700', 'base.300')(props), width: 2.5, height: 2.5, _hover: { - color: 'base.50', + color: mode('base.900', 'base.100')(props), }, }, }; diff --git a/invokeai/frontend/web/src/theme/components/popover.ts b/invokeai/frontend/web/src/theme/components/popover.ts index c8d6ae20d8..a28e2bfbc4 100644 --- a/invokeai/frontend/web/src/theme/components/popover.ts +++ b/invokeai/frontend/web/src/theme/components/popover.ts @@ -3,7 +3,7 @@ import { createMultiStyleConfigHelpers, defineStyle, } from '@chakra-ui/styled-system'; -import { cssVar } from '@chakra-ui/theme-tools'; +import { cssVar, mode } from '@chakra-ui/theme-tools'; const { defineMultiStyleConfig, definePartsStyle } = createMultiStyleConfigHelpers(parts.keys); @@ -12,15 +12,20 @@ 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`, - [$arrowShadowColor.variable]: `colors.base.600`, + [$arrowBg.variable]: mode('colors.base.100', 'colors.base.800')(props), + [$popperBg.variable]: mode('colors.base.100', 'colors.base.800')(props), + [$arrowShadowColor.variable]: mode( + 'colors.base.400', + 'colors.base.600' + )(props), minW: 'unset', width: 'unset', p: 4, - bg: 'base.800', + bg: mode('base.100', 'base.800')(props), + border: 'none', + shadow: 'dark-lg', }; }); diff --git a/invokeai/frontend/web/src/theme/components/progress.ts b/invokeai/frontend/web/src/theme/components/progress.ts index 87b6b7af01..71231869ce 100644 --- a/invokeai/frontend/web/src/theme/components/progress.ts +++ b/invokeai/frontend/web/src/theme/components/progress.ts @@ -3,24 +3,19 @@ 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: 'accent.600', - // TODO: the animation is nice but looks weird bc it is substantially longer than each step - // so we get to 100% long before it finishes - // transition: 'width 0.2s ease-in-out', - _indeterminate: { - bgGradient: - 'linear(to-r, transparent 0%, accent.600 50%, transparent 100%);', - }, + bg: 'accentAlpha.500', })); const invokeAITrack = defineStyle((_props) => { + const { colorScheme: c } = _props; return { - bg: 'none', + bg: mode(`${c}.200`, `${c}.700`)(_props), }; }); diff --git a/invokeai/frontend/web/src/theme/components/select.ts b/invokeai/frontend/web/src/theme/components/select.ts index 2fad17e1b4..72bb896238 100644 --- a/invokeai/frontend/web/src/theme/components/select.ts +++ b/invokeai/frontend/web/src/theme/components/select.ts @@ -1,13 +1,14 @@ 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: 'base.300', + color: mode('base.200', 'base.300')(props), }; }); diff --git a/invokeai/frontend/web/src/theme/components/skeleton.ts b/invokeai/frontend/web/src/theme/components/skeleton.ts new file mode 100644 index 0000000000..8ee97e0fb8 --- /dev/null +++ b/invokeai/frontend/web/src/theme/components/skeleton.ts @@ -0,0 +1,25 @@ +import { defineStyle, defineStyleConfig, cssVar } from '@chakra-ui/react'; + +const $startColor = cssVar('skeleton-start-color'); +const $endColor = cssVar('skeleton-end-color'); + +const invokeAI = defineStyle({ + borderRadius: 'base', + maxW: 'full', + maxH: 'full', + _light: { + [$startColor.variable]: 'colors.base.250', + [$endColor.variable]: 'colors.base.450', + }, + _dark: { + [$startColor.variable]: 'colors.base.700', + [$endColor.variable]: 'colors.base.500', + }, +}); + +export const skeletonTheme = defineStyleConfig({ + variants: { invokeAI }, + defaultProps: { + variant: 'invokeAI', + }, +}); diff --git a/invokeai/frontend/web/src/theme/components/slider.ts b/invokeai/frontend/web/src/theme/components/slider.ts index e706aab7b8..397dea786a 100644 --- a/invokeai/frontend/web/src/theme/components/slider.ts +++ b/invokeai/frontend/web/src/theme/components/slider.ts @@ -1,12 +1,13 @@ 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: 'base.400', + bg: mode('base.400', 'base.600')(props), h: 1.5, }; }); @@ -14,23 +15,24 @@ const invokeAITrack = defineStyle((_props) => { const invokeAIFilledTrack = defineStyle((props) => { const { colorScheme: c } = props; return { - bg: `${c}.600`, + bg: mode(`${c}.400`, `${c}.600`)(props), h: 1.5, }; }); -const invokeAIThumb = defineStyle((_props) => { +const invokeAIThumb = defineStyle((props) => { return { w: 2, h: 4, + bg: mode('base.50', 'base.100')(props), }; }); -const invokeAIMark = defineStyle((_props) => { +const invokeAIMark = defineStyle((props) => { return { fontSize: 'xs', fontWeight: '500', - color: 'base.400', + color: mode('base.700', 'base.400')(props), mt: 2, insetInlineStart: 'unset', }; diff --git a/invokeai/frontend/web/src/theme/components/switch.ts b/invokeai/frontend/web/src/theme/components/switch.ts index 6f13888442..b803e58b3b 100644 --- a/invokeai/frontend/web/src/theme/components/switch.ts +++ b/invokeai/frontend/web/src/theme/components/switch.ts @@ -3,6 +3,7 @@ import { createMultiStyleConfigHelpers, defineStyle, } from '@chakra-ui/styled-system'; +import { mode } from '@chakra-ui/theme-tools'; const { defineMultiStyleConfig, definePartsStyle } = createMultiStyleConfigHelpers(parts.keys); @@ -11,13 +12,13 @@ const invokeAITrack = defineStyle((props) => { const { colorScheme: c } = props; return { - bg: 'base.600', + bg: mode('base.300', 'base.600')(props), _focusVisible: { boxShadow: 'none', }, _checked: { - bg: `${c}.600`, + bg: mode(`${c}.400`, `${c}.500`)(props), }, }; }); @@ -26,7 +27,7 @@ const invokeAIThumb = defineStyle((props) => { const { colorScheme: c } = props; return { - bg: `${c}.50`, + bg: mode(`${c}.50`, `${c}.50`)(props), }; }); diff --git a/invokeai/frontend/web/src/theme/components/tabs.ts b/invokeai/frontend/web/src/theme/components/tabs.ts index daf6e18cab..adcce73bbc 100644 --- a/invokeai/frontend/web/src/theme/components/tabs.ts +++ b/invokeai/frontend/web/src/theme/components/tabs.ts @@ -3,6 +3,7 @@ import { createMultiStyleConfigHelpers, defineStyle, } from '@chakra-ui/styled-system'; +import { mode } from '@chakra-ui/theme-tools'; const { defineMultiStyleConfig, definePartsStyle } = createMultiStyleConfigHelpers(parts.keys); @@ -16,30 +17,53 @@ const invokeAIRoot = defineStyle((_props) => { const invokeAITab = defineStyle((_props) => ({})); -const invokeAITablist = defineStyle((_props) => ({ - display: 'flex', - flexDirection: 'column', - gap: 1, - color: 'base.700', - button: { - fontSize: 'sm', - padding: 2, - borderRadius: 'base', - _selected: { - borderBottomColor: 'base.800', - bg: 'accent.700', - color: 'accent.100', +const invokeAITablist = defineStyle((props) => { + const { colorScheme: c } = props; + + return { + display: 'flex', + flexDirection: 'column', + gap: 1, + color: mode('base.700', 'base.400')(props), + button: { + fontSize: 'sm', + padding: 2, + borderRadius: 'base', + textShadow: mode( + `0 0 0.3rem var(--invokeai-colors-accent-100)`, + `0 0 0.3rem var(--invokeai-colors-accent-900)` + )(props), + svg: { + fill: mode('base.700', 'base.300')(props), + }, + _selected: { + bg: mode('accent.400', 'accent.600')(props), + color: mode('base.50', 'base.100')(props), + svg: { + fill: mode(`base.50`, `base.100`)(props), + filter: mode( + `drop-shadow(0px 0px 0.3rem var(--invokeai-colors-${c}-600))`, + `drop-shadow(0px 0px 0.3rem var(--invokeai-colors-${c}-800))` + )(props), + }, + _hover: { + bg: mode('accent.500', 'accent.500')(props), + color: mode('white', 'base.50')(props), + svg: { + fill: mode('white', 'base.50')(props), + }, + }, + }, _hover: { - bg: 'accent.600', - color: 'accent.50', + bg: mode('base.100', 'base.800')(props), + color: mode('base.900', 'base.50')(props), + svg: { + fill: mode(`base.800`, `base.100`)(props), + }, }, }, - _hover: { - bg: 'base.600', - color: 'base.50', - }, - }, -})); + }; +}); const invokeAITabpanel = defineStyle((_props) => ({ padding: 0, @@ -59,5 +83,6 @@ export const tabsTheme = defineMultiStyleConfig({ }, defaultProps: { variant: 'invokeAI', + colorScheme: 'accent', }, }); diff --git a/invokeai/frontend/web/src/theme/components/text.ts b/invokeai/frontend/web/src/theme/components/text.ts index 88f5f23f7e..2404bf0594 100644 --- a/invokeai/frontend/web/src/theme/components/text.ts +++ b/invokeai/frontend/web/src/theme/components/text.ts @@ -1,7 +1,8 @@ import { defineStyle, defineStyleConfig } from '@chakra-ui/react'; +import { mode } from '@chakra-ui/theme-tools'; -const subtext = defineStyle((_props) => ({ - color: 'base.400', +const subtext = defineStyle((props) => ({ + color: mode('colors.base.500', 'colors.base.400')(props), })); export const textTheme = defineStyleConfig({ diff --git a/invokeai/frontend/web/src/theme/components/tooltip.ts b/invokeai/frontend/web/src/theme/components/tooltip.ts new file mode 100644 index 0000000000..511e0fecf0 --- /dev/null +++ b/invokeai/frontend/web/src/theme/components/tooltip.ts @@ -0,0 +1,17 @@ +import { defineStyle, defineStyleConfig } from '@chakra-ui/react'; +import { mode } from '@chakra-ui/theme-tools'; +import { cssVar } from '@chakra-ui/theme-tools'; + +const $arrowBg = cssVar('popper-arrow-bg'); + +// define the base component styles +const baseStyle = defineStyle((props) => ({ + borderRadius: 'base', + shadow: 'dark-lg', + bg: mode('base.700', 'base.200')(props), + [$arrowBg.variable]: mode('colors.base.700', 'colors.base.200')(props), + pb: 1.5, +})); + +// export the component theme +export const tooltipTheme = defineStyleConfig({ baseStyle }); diff --git a/invokeai/frontend/web/src/theme/theme.ts b/invokeai/frontend/web/src/theme/theme.ts index 90f26387ab..03d1f640ac 100644 --- a/invokeai/frontend/web/src/theme/theme.ts +++ b/invokeai/frontend/web/src/theme/theme.ts @@ -1,7 +1,6 @@ import { ThemeOverride } from '@chakra-ui/react'; -import type { StyleFunctionProps } from '@chakra-ui/styled-system'; -import { invokeAIThemeColors } from 'theme/colors/invokeAI'; +import { InvokeAIColors } from './colors/colors'; import { accordionTheme } from './components/accordion'; import { buttonTheme } from './components/button'; import { checkboxTheme } from './components/checkbox'; @@ -12,13 +11,15 @@ import { modalTheme } from './components/modal'; import { numberInputTheme } from './components/numberInput'; import { popoverTheme } from './components/popover'; import { progressTheme } from './components/progress'; -import { no_scrollbar, scrollbar as _scrollbar } from './components/scrollbar'; +import { no_scrollbar } from './components/scrollbar'; import { selectTheme } from './components/select'; import { sliderTheme } from './components/slider'; import { switchTheme } from './components/switch'; import { tabsTheme } from './components/tabs'; import { textTheme } from './components/text'; import { textareaTheme } from './components/textarea'; +import { tooltipTheme } from './components/tooltip'; +import { skeletonTheme } from './components/skeleton'; export const theme: ThemeOverride = { config: { @@ -26,30 +27,32 @@ export const theme: ThemeOverride = { initialColorMode: 'dark', useSystemColorMode: false, }, + layerStyles: { + body: { + bg: 'base.50', + color: 'base.900', + '.chakra-ui-dark &': { bg: 'base.900', color: 'base.50' }, + }, + first: { + bg: 'base.100', + color: 'base.900', + '.chakra-ui-dark &': { bg: 'base.850', color: 'base.100' }, + }, + second: { + bg: 'base.200', + color: 'base.900', + '.chakra-ui-dark &': { bg: 'base.800', color: 'base.100' }, + }, + }, styles: { - global: (_props: StyleFunctionProps) => ({ - body: { - bg: 'base.900', - color: 'base.50', - overflow: { - base: 'scroll', - xl: 'hidden', - }, - }, + global: () => ({ + layerStyle: 'body', '*': { ...no_scrollbar }, }), }, direction: 'ltr', fonts: { - body: `'InterVariable', sans-serif`, - }, - breakpoints: { - base: '0em', // 0px and onwards - sm: '30em', // 480px and onwards - md: '48em', // 768px and onwards - lg: '62em', // 992px and onwards - xl: '80em', // 1280px and onwards - '2xl': '96em', // 1536px and onwards + body: `'Inter Variable', sans-serif`, }, shadows: { light: { @@ -66,11 +69,14 @@ export const theme: ThemeOverride = { working: `0 0 7px var(--invokeai-colors-working-400)`, error: `0 0 7px var(--invokeai-colors-error-400)`, }, + selected: { + light: + '0px 0px 0px 1px var(--invokeai-colors-base-150), 0px 0px 0px 4px var(--invokeai-colors-accent-400)', + dark: '0px 0px 0px 1px var(--invokeai-colors-base-900), 0px 0px 0px 4px var(--invokeai-colors-accent-400)', + }, nodeSelectedOutline: `0 0 0 2px var(--invokeai-colors-base-500)`, }, - colors: { - ...invokeAIThemeColors, - }, + colors: InvokeAIColors, components: { Button: buttonTheme, // Button and IconButton Input: inputTheme, @@ -82,11 +88,13 @@ export const theme: ThemeOverride = { Switch: switchTheme, NumberInput: numberInputTheme, Select: selectTheme, + Skeleton: skeletonTheme, Slider: sliderTheme, Popover: popoverTheme, Modal: modalTheme, Checkbox: checkboxTheme, Menu: menuTheme, Text: textTheme, + Tooltip: tooltipTheme, }, }; diff --git a/invokeai/frontend/web/src/theme/themeTypes.d.ts b/invokeai/frontend/web/src/theme/themeTypes.d.ts index 46144f39ab..c85ebd33ce 100644 --- a/invokeai/frontend/web/src/theme/themeTypes.d.ts +++ b/invokeai/frontend/web/src/theme/themeTypes.d.ts @@ -11,7 +11,6 @@ export type InvokeAIThemeColors = { okAlpha: Partial; error: Partial; errorAlpha: Partial; - gridLineColor: string; }; export type InvokeAIPaletteSteps = { diff --git a/invokeai/frontend/web/src/theme/util/generateColorPalette.ts b/invokeai/frontend/web/src/theme/util/generateColorPalette.ts index 4cb5fbd57d..6d90a070c0 100644 --- a/invokeai/frontend/web/src/theme/util/generateColorPalette.ts +++ b/invokeai/frontend/web/src/theme/util/generateColorPalette.ts @@ -2,46 +2,35 @@ import { InvokeAIPaletteSteps } from 'theme/themeTypes'; /** * Add two numbers together - * @param {String | Number} hue Hue of the color (0-360) - Reds 0, Greens 120, Blues 240 - * @param {String | Number} saturation Saturation of the color (0-100) - * @param {boolean} light True to generate light color palette + * @param {String | Number} H Hue of the color (0-360) - Reds 0, Greens 120, Blues 240 + * @param {String | Number} L Saturation of the color (0-100) + * @param {Boolean} alpha Whether or not to generate this palette as a transparency palette */ export function generateColorPalette( - hue: string | number, - saturation: string | number, - light = false, + H: string | number, + S: string | number, alpha = false ) { - hue = String(hue); - saturation = String(saturation); + H = String(H); + S = String(S); const colorSteps = Array.from({ length: 21 }, (_, i) => i * 50); + const lightnessSteps = [ 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 59, 64, 68, 73, 77, 82, 86, 95, 100, ]; - const darkPalette: Partial = {}; - const lightPalette: Partial = {}; - - colorSteps.forEach((colorStep, index) => { + const p = colorSteps.reduce((palette, step, index) => { const A = alpha ? lightnessSteps[index] / 100 : 1; // Lightness should be 50% for alpha colors - const darkPaletteLightness = alpha - ? 50 - : lightnessSteps[colorSteps.length - 1 - index]; + const L = alpha ? 50 : lightnessSteps[colorSteps.length - 1 - index]; - darkPalette[ - colorStep as keyof typeof darkPalette - ] = `hsl(${hue} ${saturation}% ${darkPaletteLightness}% / ${A})`; + palette[step as keyof typeof palette] = `hsl(${H} ${S}% ${L}% / ${A})`; - const lightPaletteLightness = alpha ? 50 : lightnessSteps[index]; + return palette; + }, {} as InvokeAIPaletteSteps); - lightPalette[ - colorStep as keyof typeof lightPalette - ] = `hsl(${hue} ${saturation}% ${lightPaletteLightness}% / ${A})`; - }); - - return light ? lightPalette : darkPalette; + return p; } diff --git a/invokeai/frontend/web/src/theme/util/getInputOutlineStyles.ts b/invokeai/frontend/web/src/theme/util/getInputOutlineStyles.ts index 7d818cb6a4..8cf64cbd94 100644 --- a/invokeai/frontend/web/src/theme/util/getInputOutlineStyles.ts +++ b/invokeai/frontend/web/src/theme/util/getInputOutlineStyles.ts @@ -1,40 +1,40 @@ -import { StyleFunctionProps } from '@chakra-ui/theme-tools'; +import { StyleFunctionProps, mode } from '@chakra-ui/theme-tools'; -export const getInputOutlineStyles = (_props?: StyleFunctionProps) => ({ +export const getInputOutlineStyles = (props: StyleFunctionProps) => ({ outline: 'none', borderWidth: 2, borderStyle: 'solid', - borderColor: 'base.800', - bg: 'base.900', + borderColor: mode('base.200', 'base.800')(props), + bg: mode('base.50', 'base.900')(props), borderRadius: 'base', - color: 'base.100', + color: mode('base.900', 'base.100')(props), boxShadow: 'none', _hover: { - borderColor: 'base.600', + borderColor: mode('base.300', 'base.600')(props), }, _focus: { - borderColor: 'accent.700', + borderColor: mode('accent.200', 'accent.600')(props), boxShadow: 'none', _hover: { - borderColor: 'accent.600', + borderColor: mode('accent.300', 'accent.500')(props), }, }, _invalid: { - borderColor: 'error.700', + borderColor: mode('error.300', 'error.600')(props), boxShadow: 'none', _hover: { - borderColor: 'error.600', + borderColor: mode('error.400', 'error.500')(props), }, }, _disabled: { - borderColor: 'base.700', - bg: 'base.700', - color: 'base.400', + borderColor: mode('base.300', 'base.700')(props), + bg: mode('base.300', 'base.700')(props), + color: mode('base.600', 'base.400')(props), _hover: { - borderColor: 'base.700', + borderColor: mode('base.300', 'base.700')(props), }, }, _placeholder: { - color: 'base.500', + color: mode('base.700', 'base.400')(props), }, }); diff --git a/invokeai/frontend/web/src/theme/util/mode.ts b/invokeai/frontend/web/src/theme/util/mode.ts new file mode 100644 index 0000000000..fbaabecb6c --- /dev/null +++ b/invokeai/frontend/web/src/theme/util/mode.ts @@ -0,0 +1,3 @@ +export const mode = + (light: string, dark: string) => (colorMode: 'light' | 'dark') => + colorMode === 'light' ? light : dark; diff --git a/invokeai/frontend/web/yarn.lock b/invokeai/frontend/web/yarn.lock index bdd20af86a..64841bc39f 100644 --- a/invokeai/frontend/web/yarn.lock +++ b/invokeai/frontend/web/yarn.lock @@ -2,15 +2,6 @@ # yarn lockfile v1 -"@apidevtools/json-schema-ref-parser@9.0.6": - version "9.0.6" - resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.6.tgz#5d9000a3ac1fd25404da886da6b266adcd99cf1c" - integrity sha512-M3YgsLjI0lZxvrpeGVk9Ap032W6TPQkH6pRAZz81Ac3WUNF79VQooAFnp8umjvVzUmD93NkogxEwbSce7qMsUg== - dependencies: - "@jsdevtools/ono" "^7.1.3" - call-me-maybe "^1.0.1" - js-yaml "^3.13.1" - "@apidevtools/json-schema-ref-parser@9.0.9": version "9.0.9" resolved "https://registry.yarnpkg.com/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.9.tgz#d720f9256e3609621280584f2b47ae165359268b" @@ -21,29 +12,6 @@ call-me-maybe "^1.0.1" js-yaml "^4.1.0" -"@apidevtools/openapi-schemas@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz#9fa08017fb59d80538812f03fc7cac5992caaa17" - integrity sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ== - -"@apidevtools/swagger-methods@^3.0.2": - version "3.0.2" - resolved "https://registry.yarnpkg.com/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz#b789a362e055b0340d04712eafe7027ddc1ac267" - integrity sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg== - -"@apidevtools/swagger-parser@^10.1.0": - version "10.1.0" - resolved "https://registry.yarnpkg.com/@apidevtools/swagger-parser/-/swagger-parser-10.1.0.tgz#a987d71e5be61feb623203be0c96e5985b192ab6" - integrity sha512-9Kt7EuS/7WbMAUv2gSziqjvxwDbFSg3Xeyfuj5laUODX8o/k/CpsAKiQ8W7/R88eXFTMbJYg6+7uAmOWNKmwnw== - dependencies: - "@apidevtools/json-schema-ref-parser" "9.0.6" - "@apidevtools/openapi-schemas" "^2.1.0" - "@apidevtools/swagger-methods" "^3.0.2" - "@jsdevtools/ono" "^7.1.3" - ajv "^8.6.3" - ajv-draft-04 "^1.0.0" - call-me-maybe "^1.0.1" - "@babel/code-frame@^7.0.0": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.5.tgz#234d98e1551960604f1246e6475891a570ad5658" @@ -1621,15 +1589,6 @@ globalthis "^1.0.2" liqe "^3.6.0" -"@rollup/plugin-inject@^5.0.3": - version "5.0.3" - resolved "https://registry.yarnpkg.com/@rollup/plugin-inject/-/plugin-inject-5.0.3.tgz#0783711efd93a9547d52971db73b2fb6140a67b1" - integrity sha512-411QlbL+z2yXpRWFXSmw/teQRMkXcAAC8aYTemc15gwJRpvEVDQwoe+N/HTFD8RFG8+88Bme9DK2V9CVm7hJdA== - dependencies: - "@rollup/pluginutils" "^5.0.1" - estree-walker "^2.0.2" - magic-string "^0.27.0" - "@rollup/pluginutils@^4.2.1": version "4.2.1" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-4.2.1.tgz#e6c6c3aba0744edce3fb2074922d3776c0af2a6d" @@ -1638,7 +1597,7 @@ estree-walker "^2.0.1" picomatch "^2.2.2" -"@rollup/pluginutils@^5.0.1", "@rollup/pluginutils@^5.0.2": +"@rollup/pluginutils@^5.0.2": version "5.0.2" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.0.2.tgz#012b8f53c71e4f6f9cb317e311df1404f56e7a33" integrity sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA== @@ -2269,11 +2228,6 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv-draft-04@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz#3b64761b268ba0b9e668f0b41ba53fce0ad77fc8" - integrity sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw== - ajv@^6.10.0, ajv@^6.11.0, ajv@^6.12.4, ajv@~6.12.6: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -2284,16 +2238,6 @@ ajv@^6.10.0, ajv@^6.11.0, ajv@^6.12.4, ajv@~6.12.6: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ajv@^8.6.3: - version "8.12.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" - integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - ansi-colors@^4.1.3: version "4.1.3" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b" @@ -2353,18 +2297,18 @@ app-module-path@^2.2.0: resolved "https://registry.yarnpkg.com/app-module-path/-/app-module-path-2.2.0.tgz#641aa55dfb7d6a6f0a8141c4b9c0aa50b6c24dd5" integrity sha512-gkco+qxENJV+8vFcDiiFhuoSvRXb2a/QPqpSoWhVz829VNJfOTnELbBmPmNKFxf3xdNnw4DWCkzkDaavcX/1YQ== -argparse@^1.0.7, argparse@~1.0.9: +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +argparse@~1.0.9: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" -argparse@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" - integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== - aria-hidden@^1.1.3, aria-hidden@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.3.tgz#14aeb7fb692bbb72d69bebfa47279c1fd725e954" @@ -2417,26 +2361,6 @@ array.prototype.tosorted@^1.1.1: es-shim-unscopables "^1.0.0" get-intrinsic "^1.1.3" -asn1.js@^5.2.0: - version "5.4.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-5.4.1.tgz#11a980b84ebb91781ce35b0fdc2ee294e3783f07" - integrity sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - safer-buffer "^2.1.0" - -assert@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-2.0.0.tgz#95fc1c616d48713510680f2eaf2d10dd22e02d32" - integrity sha512-se5Cd+js9dXJnu6Ag2JFc00t+HmHOen+8Q+L7O9zI0PqQXr20uk2J0XQqMxZEeo5U50o8Nvmmx7dZrl+Ufr35A== - dependencies: - es6-object-assign "^1.1.0" - is-nan "^1.2.1" - object-is "^1.0.1" - util "^0.12.0" - ast-module-types@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/ast-module-types/-/ast-module-types-2.7.1.tgz#3f7989ef8dfa1fdb82dfe0ab02bdfc7c77a57dd3" @@ -2527,16 +2451,6 @@ bl@^4.1.0: inherits "^2.0.4" readable-stream "^3.4.0" -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.11.9: - version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== - -bn.js@^5.0.0, bn.js@^5.1.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.2.1.tgz#0bc527a6a0d18d0aa8d5b0538ce4a77dccfa7b70" - integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== - boolean@^3.1.4: version "3.2.0" resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b" @@ -2564,90 +2478,12 @@ braces@^3.0.2, braces@~3.0.2: dependencies: fill-range "^7.0.1" -brorand@^1.0.1, brorand@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w== - -browser-resolve@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-2.0.0.tgz#99b7304cb392f8d73dba741bb2d7da28c6d7842b" - integrity sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ== - dependencies: - resolve "^1.17.0" - -browserify-aes@^1.0.0, browserify-aes@^1.0.4: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0, browserify-rsa@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.1.0.tgz#b2fd06b5b75ae297f7ce2dc651f918f5be158c8d" - integrity sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog== - dependencies: - bn.js "^5.0.0" - randombytes "^2.0.1" - -browserify-sign@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.2.1.tgz#eaf4add46dd54be3bb3b36c0cf15abbeba7956c3" - integrity sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg== - dependencies: - bn.js "^5.1.1" - browserify-rsa "^4.0.1" - create-hash "^1.2.0" - create-hmac "^1.1.7" - elliptic "^6.5.3" - inherits "^2.0.4" - parse-asn1 "^5.1.5" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -browserify-zlib@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== - dependencies: - pako "~1.0.5" - buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== - -buffer@^5.5.0, buffer@^5.7.1: +buffer@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -2655,11 +2491,6 @@ buffer@^5.5.0, buffer@^5.7.1: base64-js "^1.3.1" ieee754 "^1.1.13" -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ== - busboy@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" @@ -2745,14 +2576,6 @@ ci-info@^3.7.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91" integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw== -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - classcat@^5.0.3, classcat@^5.0.4: version "5.0.4" resolved "https://registry.yarnpkg.com/classcat/-/classcat-5.0.4.tgz#e12d1dfe6df6427f260f03b80dc63571a5107ba6" @@ -2953,16 +2776,6 @@ concurrently@^8.2.0: tree-kill "^1.2.2" yargs "^17.7.2" -console-browserify@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" - integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== - -constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ== - convert-source-map@^1.5.0: version "1.9.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" @@ -2986,42 +2799,6 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" -create-ecdh@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.4.tgz#d6e7f4bffa66736085a0762fd3a632684dabcc4e" - integrity sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A== - dependencies: - bn.js "^4.1.0" - elliptic "^6.5.3" - -create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -create-require@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" - integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== - cross-fetch@3.1.6: version "3.1.6" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.6.tgz#bae05aa31a4da760969756318feeee6e70f15d6c" @@ -3038,23 +2815,6 @@ cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -crypto-browserify@^3.11.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - css-box-model@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/css-box-model/-/css-box-model-1.2.1.tgz#59951d3b81fd6b2074a62d49444415b0d2b4d7c1" @@ -3229,14 +2989,6 @@ dependency-tree@^9.0.0: precinct "^9.0.0" typescript "^4.0.0" -des.js@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.1.0.tgz#1d37f5766f3bbff4ee9638e871a8768c173b81da" - integrity sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg== - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - detect-node-es@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" @@ -3387,15 +3139,6 @@ detective-typescript@^9.0.0, detective-typescript@^9.1.1: node-source-walk "^5.0.1" typescript "^4.9.5" -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -3422,11 +3165,6 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -domain-browser@^4.22.0: - version "4.22.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-4.22.0.tgz#6ddd34220ec281f9a65d3386d267ddd35c491f9f" - integrity sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw== - downshift@^7.6.0: version "7.6.0" resolved "https://registry.yarnpkg.com/downshift/-/downshift-7.6.0.tgz#de04fb2962bd6c4ea94589c797c91f34aa9816f3" @@ -3443,19 +3181,6 @@ eastasianwidth@^0.2.0: resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== -elliptic@^6.5.3: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -3569,11 +3294,6 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" -es6-object-assign@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/es6-object-assign/-/es6-object-assign-1.1.0.tgz#c2c3582656247c39ea107cb1e6652b6f9f24523c" - integrity sha512-MEl9uirslVwqQU369iHNWZXsI8yaZYGg/D65aOgZkeyFJwHYSxilf7rQzXKI7DdDuBPrBXbfk3sl9hJhmd5AUw== - esbuild@^0.17.18, esbuild@^0.17.5: version "0.17.19" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.19.tgz#087a727e98299f0462a3d0bcdd9cd7ff100bd955" @@ -3786,19 +3506,6 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== -events@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - execa@^7.0.0: version "7.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-7.1.1.tgz#3eb3c83d239488e7b409d48e8813b76bb55c9c43" @@ -4294,32 +4001,6 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -hash-base@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.1.0.tgz#55c381d9e06e1d2997a883b4a3fddfe7f0d3af33" - integrity sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA== - dependencies: - inherits "^2.0.4" - readable-stream "^3.6.0" - safe-buffer "^5.2.0" - -hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - -hmac-drbg@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg== - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" @@ -4334,11 +4015,6 @@ html-parse-stringify@^3.0.1: dependencies: void-elements "3.1.0" -https-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg== - human-signals@^4.3.0: version "4.3.1" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-4.3.1.tgz#ab7f811e851fca97ffbd2c1fe9a958964de321b2" @@ -4426,7 +4102,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.4: +inherits@2, inherits@^2.0.3, inherits@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -4460,14 +4136,6 @@ invariant@^2.2.4: dependencies: loose-envify "^1.0.0" -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" @@ -4548,13 +4216,6 @@ is-fullwidth-code-point@^4.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== -is-generator-function@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - is-glob@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" @@ -4581,14 +4242,6 @@ is-invalid-path@^0.1.0: dependencies: is-glob "^2.0.0" -is-nan@^1.2.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" - integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - is-negative-zero@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" @@ -4660,7 +4313,7 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.10, is-typed-array@^1.1.3, is-typed-array@^1.1.9: +is-typed-array@^1.1.10, is-typed-array@^1.1.9: version "1.1.10" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== @@ -4712,11 +4365,6 @@ isexe@^2.0.0: resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== -isomorphic-timers-promises@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/isomorphic-timers-promises/-/isomorphic-timers-promises-1.0.1.tgz#e4137c24dbc54892de8abae3a4b5c1ffff381598" - integrity sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ== - its-fine@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/its-fine/-/its-fine-1.1.1.tgz#e74b93fddd487441f978a50f64f0f5af4d2fc38e" @@ -4739,14 +4387,6 @@ js-cookie@^2.2.1: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^3.13.1: - version "3.14.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" - integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -4771,11 +4411,6 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -5000,13 +4635,6 @@ madge@^6.1.0: ts-graphviz "^1.5.0" walkdir "^0.4.1" -magic-string@^0.27.0: - version "0.27.0" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3" - integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA== - dependencies: - "@jridgewell/sourcemap-codec" "^1.4.13" - magic-string@^0.29.0: version "0.29.0" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.29.0.tgz#f034f79f8c43dba4ae1730ffb5e8c4e084b16cf3" @@ -5014,15 +4642,6 @@ magic-string@^0.29.0: dependencies: "@jridgewell/sourcemap-codec" "^1.4.13" -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - mdn-data@2.0.14: version "2.0.14" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" @@ -5046,14 +4665,6 @@ micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: braces "^3.0.2" picomatch "^2.3.1" -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - mime-db@1.52.0: version "1.52.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" @@ -5076,16 +4687,6 @@ mimic-fn@^4.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg== - minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -5217,39 +4818,6 @@ node-source-walk@^5.0.0, node-source-walk@^5.0.1: dependencies: "@babel/parser" "^7.21.4" -node-stdlib-browser@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/node-stdlib-browser/-/node-stdlib-browser-1.2.0.tgz#5ddcfdf4063b88fb282979a1aa6ddab9728d5e4c" - integrity sha512-VSjFxUhRhkyed8AtLwSCkMrJRfQ3e2lGtG3sP6FEgaLKBBbxM/dLfjRe1+iLhjvyLFW3tBQ8+c0pcOtXGbAZJg== - dependencies: - assert "^2.0.0" - browser-resolve "^2.0.0" - browserify-zlib "^0.2.0" - buffer "^5.7.1" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - create-require "^1.1.1" - crypto-browserify "^3.11.0" - domain-browser "^4.22.0" - events "^3.0.0" - https-browserify "^1.0.0" - isomorphic-timers-promises "^1.0.1" - os-browserify "^0.3.0" - path-browserify "^1.0.1" - pkg-dir "^5.0.0" - process "^0.11.10" - punycode "^1.4.1" - querystring-es3 "^0.2.1" - readable-stream "^3.6.0" - stream-browserify "^3.0.0" - stream-http "^3.2.0" - string_decoder "^1.0.0" - timers-browserify "^2.0.4" - tty-browserify "0.0.1" - url "^0.11.0" - util "^0.12.4" - vm-browserify "^1.0.1" - normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -5272,14 +4840,6 @@ object-inspect@^1.12.3, object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== -object-is@^1.0.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -5368,7 +4928,7 @@ open@^8.4.0: is-docker "^2.1.1" is-wsl "^2.2.0" -openapi-fetch@^0.4.0: +openapi-fetch@0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/openapi-fetch/-/openapi-fetch-0.4.0.tgz#45c368321ba6c15bc2e168e7dc3fbf322e9cca6d" integrity sha512-4lzZtH5J1ZH9EXfmpcmKi0gOgjy0hc6BAcucAdCmLHY6jZopMeGP51vD3Cd4rE1nTFMfJzmYDc8ar0+364gBVw== @@ -5440,11 +5000,6 @@ ora@^5.4.1: strip-ansi "^6.0.0" wcwidth "^1.0.1" -os-browserify@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A== - os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -5481,11 +5036,6 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" -pako@~1.0.5: - version "1.0.11" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" - integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== - parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -5493,17 +5043,6 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parse-asn1@^5.0.0, parse-asn1@^5.1.5: - version "5.1.6" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.6.tgz#385080a3ec13cb62a62d39409cb3e88844cdaed4" - integrity sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw== - dependencies: - asn1.js "^5.2.0" - browserify-aes "^1.0.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - parse-json@^5.0.0: version "5.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" @@ -5574,17 +5113,6 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pbkdf2@^3.0.3: - version "3.1.2" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" - integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -5600,13 +5128,6 @@ pidtree@^0.6.0: resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c" integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g== -pkg-dir@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-5.0.0.tgz#a02d6aebe6ba133a928f74aec20bafdfe6b8e760" - integrity sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA== - dependencies: - find-up "^5.0.0" - pluralize@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" @@ -5710,11 +5231,6 @@ pretty-ms@^7.0.1: dependencies: parse-ms "^2.1.0" -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== - prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -5729,35 +5245,11 @@ proxy-from-env@^1.1.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== - punycode@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== -qs@^6.11.0: - version "6.11.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.2.tgz#64bea51f12c1f5da1bc01496f48ffcff7c69d7d9" - integrity sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA== - dependencies: - side-channel "^1.0.4" - query-string@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/query-string/-/query-string-8.1.0.tgz#e7f95367737219544cd360a11a4f4ca03836e115" @@ -5767,11 +5259,6 @@ query-string@^8.1.0: filter-obj "^5.1.0" split-on-first "^3.0.0" -querystring-es3@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA== - queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" @@ -5795,21 +5282,6 @@ randexp@0.4.6: discontinuous-range "1.0.0" ret "~0.1.10" -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" @@ -6035,7 +5507,7 @@ reactflow@^11.7.4: "@reactflow/node-resizer" "2.1.1" "@reactflow/node-toolbar" "1.2.3" -readable-stream@^3.4.0, readable-stream@^3.5.0, readable-stream@^3.6.0: +readable-stream@^3.4.0: version "3.6.2" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== @@ -6092,11 +5564,6 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - requirejs-config-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/requirejs-config-file/-/requirejs-config-file-4.0.0.tgz#4244da5dd1f59874038cc1091d078d620abb6ebc" @@ -6130,7 +5597,7 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve@^1.17.0, resolve@^1.19.0, resolve@^1.21.0, resolve@~1.22.1: +resolve@^1.19.0, resolve@^1.21.0, resolve@~1.22.1: version "1.22.2" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== @@ -6193,14 +5660,6 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - roarr@^7.15.0: version "7.15.0" resolved "https://registry.yarnpkg.com/roarr/-/roarr-7.15.0.tgz#09b792f0cd31b4a7f91030bb1c47550ceec98ee4" @@ -6258,7 +5717,7 @@ rxjs@^7.8.0, rxjs@^7.8.1: dependencies: tslib "^2.1.0" -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -6277,11 +5736,6 @@ safe-stable-stringify@^2.4.1: resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== -safer-buffer@^2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - sass-lookup@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/sass-lookup/-/sass-lookup-3.0.0.tgz#3b395fa40569738ce857bc258e04df2617c48cac" @@ -6342,19 +5796,6 @@ set-harmonic-interval@^1.0.1: resolved "https://registry.yarnpkg.com/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz#e1773705539cdfb80ce1c3d99e7f298bb3995249" integrity sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g== -setimmediate@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== - -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -6522,24 +5963,6 @@ stacktrace-js@^2.0.2: stack-generator "^2.0.5" stacktrace-gps "^3.0.4" -stream-browserify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-3.0.0.tgz#22b0a2850cdf6503e73085da1fc7b7d0c2122f2f" - integrity sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA== - dependencies: - inherits "~2.0.4" - readable-stream "^3.5.0" - -stream-http@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.2.0.tgz#1872dfcf24cb15752677e40e5c3f9cc1926028b5" - integrity sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A== - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.4" - readable-stream "^3.6.0" - xtend "^4.0.2" - 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" @@ -6621,7 +6044,7 @@ string.prototype.trimstart@^1.0.6: define-properties "^1.1.4" es-abstract "^1.20.4" -string_decoder@^1.0.0, string_decoder@^1.1.1: +string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== @@ -6750,13 +6173,6 @@ through@^2.3.8: resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== -timers-browserify@^2.0.4: - version "2.0.12" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.12.tgz#44a45c11fbf407f34f97bccd1577c652361b00ee" - integrity sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ== - dependencies: - setimmediate "^1.0.4" - tiny-invariant@^1.0.6: version "1.3.1" resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" @@ -6866,11 +6282,6 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" -tty-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" - integrity sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw== - type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -6968,14 +6379,6 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -url@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.1.tgz#26f90f615427eca1b9f4d6a28288c147e2302a32" - integrity sha512-rWS3H04/+mzzJkv0eZ7vEDGiQbgquI1fGfOad6zKvgYQi1SzMmhl7c/DdRGxhaWrVH6z0qWITo8rpnxK/RfEhA== - dependencies: - punycode "^1.4.1" - qs "^6.11.0" - use-callback-ref@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.0.tgz#772199899b9c9a50526fedc4993fc7fa1f7e32d5" @@ -7023,17 +6426,6 @@ util-deprecate@^1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -util@^0.12.0, util@^0.12.4: - version "0.12.5" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" - integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - which-typed-array "^1.1.2" - uuid@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.0.tgz#592f550650024a38ceb0c562f2f6aa435761efb5" @@ -7074,14 +6466,6 @@ vite-plugin-eslint@^1.8.1: "@types/eslint" "^8.4.5" rollup "^2.77.2" -vite-plugin-node-polyfills@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.9.0.tgz#181d096c43e22cae219c6c2434a204b665044de0" - integrity sha512-+i+WPUuIBhJy+ODfxx6S6FTl28URCxUszbl/IL4GwrZvbqqY/8VDIp+zpjMS8Us/a7GwN4Iaqr/fVIBtkNQojQ== - dependencies: - "@rollup/plugin-inject" "^5.0.3" - node-stdlib-browser "^1.2.0" - vite-tsconfig-paths@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/vite-tsconfig-paths/-/vite-tsconfig-paths-4.2.0.tgz#bd2647d3eadafb65a10fc98a2ca565211f2eaf63" @@ -7102,11 +6486,6 @@ vite@^4.3.9: optionalDependencies: fsevents "~2.3.2" -vm-browserify@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" - integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== - void-elements@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" @@ -7148,7 +6527,7 @@ which-boxed-primitive@^1.0.2: is-string "^1.0.5" is-symbol "^1.0.3" -which-typed-array@^1.1.2, which-typed-array@^1.1.9: +which-typed-array@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== @@ -7210,11 +6589,6 @@ xmlhttprequest-ssl@~2.0.0: resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz#91360c86b914e67f44dce769180027c0da618c67" integrity sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A== -xtend@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"