merge prior to backing out PR #1000
@ -46,7 +46,7 @@ This is a fork of
|
||||
the open source text-to-image generator. It provides a streamlined
|
||||
process with various new features and options to aid the image
|
||||
generation process. It runs on Windows, Mac and Linux machines, with
|
||||
GPU cards with as little as 4 GB or RAM. It provides both a polished
|
||||
GPU cards with as little as 4 GB of RAM. It provides both a polished
|
||||
Web interface, and an easy-to-use command-line interface.
|
||||
|
||||
_Note: This fork is rapidly evolving. Please use the
|
||||
|
BIN
docs/assets/Lincoln-and-Parrot-512-transparent.png
Executable file
After Width: | Height: | Size: 284 KiB |
BIN
docs/assets/Lincoln-and-Parrot-512.png
Normal file
After Width: | Height: | Size: 252 KiB |
BIN
docs/assets/invoke-web-server-1.png
Normal file
After Width: | Height: | Size: 983 KiB |
BIN
docs/assets/invoke-web-server-2.png
Normal file
After Width: | Height: | Size: 101 KiB |
BIN
docs/assets/invoke-web-server-3.png
Normal file
After Width: | Height: | Size: 546 KiB |
BIN
docs/assets/invoke-web-server-4.png
Normal file
After Width: | Height: | Size: 336 KiB |
BIN
docs/assets/invoke-web-server-5.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
docs/assets/invoke-web-server-6.png
Normal file
After Width: | Height: | Size: 148 KiB |
BIN
docs/assets/invoke-web-server-7.png
Normal file
After Width: | Height: | Size: 637 KiB |
BIN
docs/assets/invoke-web-server-8.png
Normal file
After Width: | Height: | Size: 529 KiB |
BIN
docs/assets/invoke_web_server.png
Normal file
After Width: | Height: | Size: 989 KiB |
@ -75,7 +75,6 @@ git clone https://github.com/invoke-ai/InvokeAI.git
|
||||
cd InvokeAI
|
||||
|
||||
### WAIT FOR THE CHECKPOINT FILE TO DOWNLOAD, THEN PROCEED ###
|
||||
>>>>>>> Updates INSTALL_MAC.md
|
||||
|
||||
# We will leave the big checkpoint wherever you stashed it for long-term storage,
|
||||
# and make a link to it from the repo's folder. This allows you to use it for
|
||||
|
483
frontend/dist/assets/index.6cdae835.js
vendored
Normal file
4
frontend/dist/index.html
vendored
@ -6,8 +6,8 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>InvokeAI - A Stable Diffusion Toolkit</title>
|
||||
<link rel="shortcut icon" type="icon" href="/assets/favicon.0d253ced.ico" />
|
||||
<script type="module" crossorigin src="/assets/index.f85957e3.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index.c04b2fd8.css">
|
||||
<script type="module" crossorigin src="/assets/index.6cdae835.js"></script>
|
||||
<link rel="stylesheet" href="/assets/index.4ceb640a.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@ -25,6 +25,7 @@
|
||||
"react-dropzone": "^14.2.2",
|
||||
"react-hotkeys-hook": "^3.4.7",
|
||||
"react-icons": "^4.4.0",
|
||||
"react-masonry-css": "^1.0.16",
|
||||
"react-redux": "^8.0.2",
|
||||
"redux-persist": "^6.0.0",
|
||||
"socket.io": "^4.5.2",
|
||||
|
@ -71,7 +71,7 @@
|
||||
.next-prev-button-trigger-area {
|
||||
width: 7rem;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
width: 15%;
|
||||
display: grid;
|
||||
align-items: center;
|
||||
pointer-events: auto;
|
||||
|
59
frontend/src/features/gallery/HoverableImage.scss
Normal file
@ -0,0 +1,59 @@
|
||||
.hoverable-image {
|
||||
display: grid;
|
||||
grid-template-areas: 'hoverable-image';
|
||||
transition: transform 0.2s ease-out;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
border-radius: 0.5rem;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.hoverable-image-image,
|
||||
.hoverable-image-content,
|
||||
.hoverable-image-icons {
|
||||
grid-area: hoverable-image;
|
||||
}
|
||||
|
||||
.hoverable-image-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.hoverable-image-content {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
|
||||
.hoverable-image-check {
|
||||
fill: var(--status-good-color);
|
||||
}
|
||||
}
|
||||
|
||||
.hoverable-image-icons {
|
||||
grid-area: hoverable-image;
|
||||
position: absolute;
|
||||
bottom: -2rem;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, max-content);
|
||||
border-radius: 0.4rem;
|
||||
background-color: var(--background-color-secondary);
|
||||
padding: 0.2rem;
|
||||
gap: 0.2rem;
|
||||
grid-auto-rows: max-content;
|
||||
place-self: center;
|
||||
|
||||
button {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 0.2rem;
|
||||
padding: 10px 0;
|
||||
svg {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,4 @@
|
||||
import {
|
||||
Box,
|
||||
Flex,
|
||||
Icon,
|
||||
IconButton,
|
||||
Image,
|
||||
Tooltip,
|
||||
useColorModeValue,
|
||||
} from '@chakra-ui/react';
|
||||
import { Box, Icon, IconButton, Image, Tooltip } from '@chakra-ui/react';
|
||||
import { RootState, useAppDispatch, useAppSelector } from '../../app/store';
|
||||
import { setCurrentImage } from './gallerySlice';
|
||||
import { FaCheck, FaImage, FaSeedling, FaTrashAlt } from 'react-icons/fa';
|
||||
@ -42,13 +34,6 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
||||
(state: RootState) => state.options.activeTab
|
||||
);
|
||||
|
||||
const checkColor = useColorModeValue('green.600', 'green.300');
|
||||
const bgColor = useColorModeValue('gray.200', 'gray.700');
|
||||
const bgGradient = useColorModeValue(
|
||||
'radial-gradient(circle, rgba(255,255,255,0.7) 0%, rgba(255,255,255,0.7) 20%, rgba(0,0,0,0) 100%)',
|
||||
'radial-gradient(circle, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.7) 20%, rgba(0,0,0,0) 100%)'
|
||||
);
|
||||
|
||||
const { image, isSelected } = props;
|
||||
const { url, uuid, metadata } = image;
|
||||
|
||||
@ -76,91 +61,80 @@ const HoverableImage = memo((props: HoverableImageProps) => {
|
||||
const handleClickImage = () => dispatch(setCurrentImage(image));
|
||||
|
||||
return (
|
||||
<Box position={'relative'} key={uuid}>
|
||||
<Box
|
||||
position={'relative'}
|
||||
key={uuid}
|
||||
className="hoverable-image"
|
||||
onMouseOver={handleMouseOver}
|
||||
onMouseOut={handleMouseOut}
|
||||
>
|
||||
<Image
|
||||
width={120}
|
||||
height={120}
|
||||
objectFit="cover"
|
||||
rounded={'md'}
|
||||
src={url}
|
||||
loading={'lazy'}
|
||||
backgroundColor={bgColor}
|
||||
className="hoverable-image-image"
|
||||
/>
|
||||
<Flex
|
||||
cursor={'pointer'}
|
||||
position={'absolute'}
|
||||
top={0}
|
||||
left={0}
|
||||
rounded={'md'}
|
||||
width="100%"
|
||||
height="100%"
|
||||
alignItems={'center'}
|
||||
justifyContent={'center'}
|
||||
background={isSelected ? bgGradient : undefined}
|
||||
onClick={handleClickImage}
|
||||
onMouseOver={handleMouseOver}
|
||||
onMouseOut={handleMouseOut}
|
||||
>
|
||||
<div className="hoverable-image-content" onClick={handleClickImage}>
|
||||
{isSelected && (
|
||||
<Icon fill={checkColor} width={'50%'} height={'50%'} as={FaCheck} />
|
||||
<Icon
|
||||
width={'50%'}
|
||||
height={'50%'}
|
||||
as={FaCheck}
|
||||
className="hoverable-image-check"
|
||||
/>
|
||||
)}
|
||||
{isHovered && (
|
||||
<Flex
|
||||
direction={'column'}
|
||||
gap={1}
|
||||
position={'absolute'}
|
||||
top={1}
|
||||
right={1}
|
||||
>
|
||||
<Tooltip label={'Delete image'}>
|
||||
<DeleteImageModal image={image}>
|
||||
<IconButton
|
||||
colorScheme="red"
|
||||
aria-label="Delete image"
|
||||
icon={<FaTrashAlt />}
|
||||
size="xs"
|
||||
variant={'imageHoverIconButton'}
|
||||
fontSize={14}
|
||||
/>
|
||||
</DeleteImageModal>
|
||||
</Tooltip>
|
||||
{['txt2img', 'img2img'].includes(image?.metadata?.image?.type) && (
|
||||
<Tooltip label="Use all parameters">
|
||||
<IconButton
|
||||
aria-label="Use all parameters"
|
||||
icon={<IoArrowUndoCircleOutline />}
|
||||
size="xs"
|
||||
fontSize={18}
|
||||
variant={'imageHoverIconButton'}
|
||||
onClickCapture={handleClickSetAllParameters}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
{image?.metadata?.image?.seed !== undefined && (
|
||||
<Tooltip label="Use seed">
|
||||
<IconButton
|
||||
aria-label="Use seed"
|
||||
icon={<FaSeedling />}
|
||||
size="xs"
|
||||
fontSize={16}
|
||||
variant={'imageHoverIconButton'}
|
||||
onClickCapture={handleClickSetSeed}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip label="Send To Image To Image">
|
||||
</div>
|
||||
{isHovered && (
|
||||
<div className="hoverable-image-icons">
|
||||
<Tooltip label={'Delete image'} hasArrow>
|
||||
<DeleteImageModal image={image}>
|
||||
<IconButton
|
||||
aria-label="Send To Image To Image"
|
||||
icon={<FaImage />}
|
||||
colorScheme="red"
|
||||
aria-label="Delete image"
|
||||
icon={<FaTrashAlt />}
|
||||
size="xs"
|
||||
variant={'imageHoverIconButton'}
|
||||
fontSize={14}
|
||||
/>
|
||||
</DeleteImageModal>
|
||||
</Tooltip>
|
||||
{['txt2img', 'img2img'].includes(image?.metadata?.image?.type) && (
|
||||
<Tooltip label="Use All Parameters" hasArrow>
|
||||
<IconButton
|
||||
aria-label="Use All Parameters"
|
||||
icon={<IoArrowUndoCircleOutline />}
|
||||
size="xs"
|
||||
fontSize={18}
|
||||
variant={'imageHoverIconButton'}
|
||||
onClickCapture={handleClickSetAllParameters}
|
||||
/>
|
||||
</Tooltip>
|
||||
)}
|
||||
{image?.metadata?.image?.seed !== undefined && (
|
||||
<Tooltip label="Use Seed" hasArrow>
|
||||
<IconButton
|
||||
aria-label="Use Seed"
|
||||
icon={<FaSeedling />}
|
||||
size="xs"
|
||||
fontSize={16}
|
||||
variant={'imageHoverIconButton'}
|
||||
onClickCapture={handleSetInitImage}
|
||||
onClickCapture={handleClickSetSeed}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
)}
|
||||
</Flex>
|
||||
)}
|
||||
<Tooltip label="Send To Image To Image" hasArrow>
|
||||
<IconButton
|
||||
aria-label="Send To Image To Image"
|
||||
icon={<FaImage />}
|
||||
size="xs"
|
||||
fontSize={16}
|
||||
variant={'imageHoverIconButton'}
|
||||
onClickCapture={handleSetInitImage}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}, memoEqualityCheck);
|
||||
|
@ -55,12 +55,31 @@
|
||||
@include HideScrollbar;
|
||||
}
|
||||
|
||||
.image-gallery {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(120px, auto));
|
||||
gap: 0.6rem;
|
||||
justify-items: center;
|
||||
.masonry-grid {
|
||||
display: -webkit-box; /* Not needed if autoprefixing */
|
||||
display: -ms-flexbox; /* Not needed if autoprefixing */
|
||||
display: flex;
|
||||
margin-left: 0.5rem; /* gutter size offset */
|
||||
width: auto;
|
||||
}
|
||||
.masonry-grid_column {
|
||||
padding-left: 0.5rem; /* gutter size */
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
/* Style your items */
|
||||
.masonry-grid_column > .hoverable-image {
|
||||
/* change div to reference your elements you put in <Masonry> */
|
||||
background: var(--tab-color);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
// .image-gallery {
|
||||
// display: grid;
|
||||
// grid-template-columns: repeat(auto-fill, minmax(80px, auto));
|
||||
// gap: 0.5rem;
|
||||
// justify-items: center;
|
||||
// }
|
||||
|
||||
.image-gallery-load-more-btn {
|
||||
background-color: var(--btn-load-more) !important;
|
||||
|
@ -1,25 +1,25 @@
|
||||
import { Button, IconButton } from '@chakra-ui/button';
|
||||
import { Resizable } from 're-resizable';
|
||||
import React from 'react';
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
import { MdClear, MdPhotoLibrary } from 'react-icons/md';
|
||||
import Masonry from 'react-masonry-css';
|
||||
import { requestImages } from '../../app/socketio/actions';
|
||||
import { RootState, useAppDispatch, useAppSelector } from '../../app/store';
|
||||
import IAIIconButton from '../../common/components/IAIIconButton';
|
||||
import {
|
||||
selectNextImage,
|
||||
selectPrevImage,
|
||||
setShouldShowGallery,
|
||||
} from './gallerySlice';
|
||||
import { selectNextImage, selectPrevImage } from './gallerySlice';
|
||||
import HoverableImage from './HoverableImage';
|
||||
import { setShouldShowGallery } from '../options/optionsSlice';
|
||||
|
||||
export default function ImageGallery() {
|
||||
const {
|
||||
images,
|
||||
currentImageUuid,
|
||||
areMoreImagesAvailable,
|
||||
shouldShowGallery,
|
||||
} = useAppSelector((state: RootState) => state.gallery);
|
||||
const { images, currentImageUuid, areMoreImagesAvailable } = useAppSelector(
|
||||
(state: RootState) => state.gallery
|
||||
);
|
||||
|
||||
const shouldShowGallery = useAppSelector(
|
||||
(state: RootState) => state.options.shouldShowGallery
|
||||
);
|
||||
|
||||
const activeTab = useAppSelector(
|
||||
(state: RootState) => state.options.activeTab
|
||||
@ -27,6 +27,12 @@ export default function ImageGallery() {
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const [column, setColumn] = useState<number | undefined>();
|
||||
|
||||
const handleResize = (event: MouseEvent | TouchEvent | any) => {
|
||||
setColumn(Math.floor((window.innerWidth - event.x) / 120));
|
||||
};
|
||||
|
||||
const handleShowGalleryToggle = () => {
|
||||
dispatch(setShouldShowGallery(!shouldShowGallery));
|
||||
};
|
||||
@ -83,6 +89,7 @@ export default function ImageGallery() {
|
||||
minWidth={'300'}
|
||||
maxWidth={activeTab == 1 ? '300' : '600'}
|
||||
className="image-gallery-popup"
|
||||
onResize={handleResize}
|
||||
>
|
||||
{/* <div className="image-gallery-popup"></div> */}
|
||||
<div className="image-gallery-header">
|
||||
@ -97,7 +104,12 @@ export default function ImageGallery() {
|
||||
</div>
|
||||
<div className="image-gallery-container">
|
||||
{images.length ? (
|
||||
<div className="image-gallery">
|
||||
<Masonry
|
||||
className="masonry-grid"
|
||||
columnClassName="masonry-grid_column"
|
||||
breakpointCols={column}
|
||||
>
|
||||
{/* <div className="image-gallery"> */}
|
||||
{images.map((image) => {
|
||||
const { uuid } = image;
|
||||
const isSelected = currentImageUuid === uuid;
|
||||
@ -109,7 +121,8 @@ export default function ImageGallery() {
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
{/* </div> */}
|
||||
</Masonry>
|
||||
) : (
|
||||
<div className="image-gallery-container-placeholder">
|
||||
<MdPhotoLibrary />
|
||||
|
@ -11,14 +11,12 @@ export interface GalleryState {
|
||||
areMoreImagesAvailable: boolean;
|
||||
latest_mtime?: number;
|
||||
earliest_mtime?: number;
|
||||
shouldShowGallery: boolean;
|
||||
}
|
||||
|
||||
const initialState: GalleryState = {
|
||||
currentImageUuid: '',
|
||||
images: [],
|
||||
areMoreImagesAvailable: true,
|
||||
shouldShowGallery: false,
|
||||
};
|
||||
|
||||
export const gallerySlice = createSlice({
|
||||
@ -140,9 +138,6 @@ export const gallerySlice = createSlice({
|
||||
state.areMoreImagesAvailable = areMoreImagesAvailable;
|
||||
}
|
||||
},
|
||||
setShouldShowGallery: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldShowGallery = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -155,7 +150,6 @@ export const {
|
||||
setIntermediateImage,
|
||||
selectNextImage,
|
||||
selectPrevImage,
|
||||
setShouldShowGallery,
|
||||
} = gallerySlice.actions;
|
||||
|
||||
export default gallerySlice.reducer;
|
||||
|
@ -35,6 +35,7 @@ export interface OptionsState {
|
||||
showAdvancedOptions: boolean;
|
||||
activeTab: number;
|
||||
shouldShowImageDetails: boolean;
|
||||
shouldShowGallery: boolean;
|
||||
}
|
||||
|
||||
const initialOptionsState: OptionsState = {
|
||||
@ -66,6 +67,7 @@ const initialOptionsState: OptionsState = {
|
||||
showAdvancedOptions: true,
|
||||
activeTab: 0,
|
||||
shouldShowImageDetails: false,
|
||||
shouldShowGallery: false,
|
||||
};
|
||||
|
||||
const initialState: OptionsState = initialOptionsState;
|
||||
@ -281,6 +283,9 @@ export const optionsSlice = createSlice({
|
||||
setShouldShowImageDetails: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldShowImageDetails = action.payload;
|
||||
},
|
||||
setShouldShowGallery: (state, action: PayloadAction<boolean>) => {
|
||||
state.shouldShowGallery = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -317,6 +322,7 @@ export const {
|
||||
setShowAdvancedOptions,
|
||||
setActiveTab,
|
||||
setShouldShowImageDetails,
|
||||
setShouldShowGallery,
|
||||
} = optionsSlice.actions;
|
||||
|
||||
export default optionsSlice.reducer;
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
.site-header-right-side {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, max-content);
|
||||
grid-template-columns: repeat(7, max-content);
|
||||
align-items: center;
|
||||
column-gap: 0.5rem;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { IconButton, Link, Tooltip, useColorMode } from '@chakra-ui/react';
|
||||
import { useHotkeys } from 'react-hotkeys-hook';
|
||||
|
||||
import { FaSun, FaMoon, FaGithub } from 'react-icons/fa';
|
||||
import { FaSun, FaMoon, FaGithub, FaDiscord } from 'react-icons/fa';
|
||||
import { MdHelp, MdKeyboard, MdSettings } from 'react-icons/md';
|
||||
|
||||
import InvokeAILogo from '../../assets/images/logo.png';
|
||||
@ -70,7 +70,7 @@ const SiteHeader = () => {
|
||||
icon={
|
||||
<Link
|
||||
isExternal
|
||||
href="http://github.com/lstein/stable-diffusion/issues"
|
||||
href="http://github.com/invoke-ai/InvokeAI/issues"
|
||||
>
|
||||
<MdHelp />
|
||||
</Link>
|
||||
@ -85,13 +85,27 @@ const SiteHeader = () => {
|
||||
fontSize={20}
|
||||
size={'sm'}
|
||||
icon={
|
||||
<Link isExternal href="http://github.com/lstein/stable-diffusion">
|
||||
<Link isExternal href="http://github.com/invoke-ai/InvokeAI">
|
||||
<FaGithub />
|
||||
</Link>
|
||||
}
|
||||
/>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip hasArrow label="Discord" placement={'bottom'}>
|
||||
<IconButton
|
||||
aria-label="Link to Discord Server"
|
||||
variant="link"
|
||||
fontSize={20}
|
||||
size={'sm'}
|
||||
icon={
|
||||
<Link isExternal href="https://discord.gg/ZmtBAhwWhy">
|
||||
<FaDiscord />
|
||||
</Link>
|
||||
}
|
||||
/>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip hasArrow label="Theme" placement={'bottom'}>
|
||||
<IconButton
|
||||
aria-label="Toggle Dark Mode"
|
||||
|
@ -6,7 +6,7 @@ import { RootState, useAppSelector } from '../../../app/store';
|
||||
|
||||
export default function ImageToImage() {
|
||||
const shouldShowGallery = useAppSelector(
|
||||
(state: RootState) => state.gallery.shouldShowGallery
|
||||
(state: RootState) => state.options.shouldShowGallery
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -6,7 +6,7 @@ import { RootState, useAppSelector } from '../../../app/store';
|
||||
|
||||
export default function TextToImage() {
|
||||
const shouldShowGallery = useAppSelector(
|
||||
(state: RootState) => state.gallery.shouldShowGallery
|
||||
(state: RootState) => state.options.shouldShowGallery
|
||||
);
|
||||
|
||||
return (
|
||||
|
@ -26,6 +26,7 @@
|
||||
// gallery
|
||||
@use '../features/gallery/CurrentImageDisplay.scss';
|
||||
@use '../features/gallery/ImageGallery.scss';
|
||||
@use '../features/gallery/HoverableImage.scss';
|
||||
@use '../features/gallery/InvokePopover.scss';
|
||||
@use '../features/gallery/ImageMetaDataViewer/ImageMetadataViewer.scss';
|
||||
|
||||
|
@ -2850,6 +2850,11 @@ react-is@^18.0.0:
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
|
||||
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
|
||||
|
||||
react-masonry-css@^1.0.16:
|
||||
version "1.0.16"
|
||||
resolved "https://registry.yarnpkg.com/react-masonry-css/-/react-masonry-css-1.0.16.tgz#72b28b4ae3484e250534700860597553a10f1a2c"
|
||||
integrity sha512-KSW0hR2VQmltt/qAa3eXOctQDyOu7+ZBevtKgpNDSzT7k5LA/0XntNa9z9HKCdz3QlxmJHglTZ18e4sX4V8zZQ==
|
||||
|
||||
react-redux@^8.0.2:
|
||||
version "8.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-8.0.2.tgz#bc2a304bb21e79c6808e3e47c50fe1caf62f7aad"
|
||||
|