mirror of
https://github.com/invoke-ai/InvokeAI
synced 2024-08-30 20:32:17 +00:00
multi-select actions include: - drag to board to move all to that board - right click to add all to board or delete all backend changes: - add routes for changing board for list of image names, deleting list of images - change image-specific routes to `images/i/{image_name}` to not clobber other routes (like `images/upload`, `images/delete`) - subclass pydantic `BaseModel` as `BaseModelExcludeNull`, which excludes null values when calling `dict()` on the model. this fixes inconsistent types related to JSON parsing null values into `null` instead of `undefined` - remove `board_id` from `remove_image_from_board` frontend changes: - multi-selection stuff uses `ImageDTO[]` as payloads, for dnd and other mutations. this gives us access to image `board_id`s when hitting routes, and enables efficient cache updates. - consolidate change board and delete image modals to handle single and multiples - board totals are now re-fetched on mutation and not kept in sync manually - was way too tedious to do this - fixed warning about nested `<p>` elements - closes #4088 , need to handle case when `autoAddBoardId` is `"none"` - add option to show gallery image delete button on every gallery image frontend refactors/organisation: - make typegen script js instead of ts - enable `noUncheckedIndexedAccess` to help avoid bugs when indexing into arrays, many small changes needed to satisfy TS after this - move all image-related endpoints into `endpoints/images.ts`, its a big file now, but this fixes a number of circular dependency issues that were otherwise felt impossible to resolve
98 lines
2.5 KiB
TypeScript
98 lines
2.5 KiB
TypeScript
import { Box, Flex, useColorMode } from '@chakra-ui/react';
|
|
import { motion } from 'framer-motion';
|
|
import { ReactNode, memo, useRef } from 'react';
|
|
import { mode } from 'theme/util/mode';
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
|
|
type Props = {
|
|
isOver: boolean;
|
|
label?: ReactNode;
|
|
};
|
|
|
|
export const IAIDropOverlay = (props: Props) => {
|
|
const { isOver, label = 'Drop' } = props;
|
|
const motionId = useRef(uuidv4());
|
|
const { colorMode } = useColorMode();
|
|
return (
|
|
<motion.div
|
|
key={motionId.current}
|
|
initial={{
|
|
opacity: 0,
|
|
}}
|
|
animate={{
|
|
opacity: 1,
|
|
transition: { duration: 0.1 },
|
|
}}
|
|
exit={{
|
|
opacity: 0,
|
|
transition: { duration: 0.1 },
|
|
}}
|
|
>
|
|
<Flex
|
|
sx={{
|
|
position: 'absolute',
|
|
top: 0,
|
|
insetInlineStart: 0,
|
|
w: 'full',
|
|
h: 'full',
|
|
}}
|
|
>
|
|
<Flex
|
|
sx={{
|
|
position: 'absolute',
|
|
top: 0,
|
|
insetInlineStart: 0,
|
|
w: 'full',
|
|
h: 'full',
|
|
bg: mode('base.700', 'base.900')(colorMode),
|
|
opacity: 0.7,
|
|
borderRadius: 'base',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
transitionProperty: 'common',
|
|
transitionDuration: '0.1s',
|
|
}}
|
|
/>
|
|
|
|
<Flex
|
|
sx={{
|
|
position: 'absolute',
|
|
top: 0.5,
|
|
insetInlineStart: 0.5,
|
|
insetInlineEnd: 0.5,
|
|
bottom: 0.5,
|
|
opacity: 1,
|
|
borderWidth: 2,
|
|
borderColor: isOver
|
|
? mode('base.50', 'base.50')(colorMode)
|
|
: mode('base.200', 'base.300')(colorMode),
|
|
borderRadius: 'lg',
|
|
borderStyle: 'dashed',
|
|
transitionProperty: 'common',
|
|
transitionDuration: '0.1s',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
}}
|
|
>
|
|
<Box
|
|
sx={{
|
|
fontSize: '2xl',
|
|
fontWeight: 600,
|
|
transform: isOver ? 'scale(1.1)' : 'scale(1)',
|
|
color: isOver
|
|
? mode('base.50', 'base.50')(colorMode)
|
|
: mode('base.200', 'base.300')(colorMode),
|
|
transitionProperty: 'common',
|
|
transitionDuration: '0.1s',
|
|
}}
|
|
>
|
|
{label}
|
|
</Box>
|
|
</Flex>
|
|
</Flex>
|
|
</motion.div>
|
|
);
|
|
};
|
|
|
|
export default memo(IAIDropOverlay);
|