mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-02-23 19:49:56 +01:00
editor: get rid of framer-motion
This commit is contained in:
committed by
Abdullah Atta
parent
b7aaa382b1
commit
6671a97181
@@ -92,7 +92,6 @@
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@types/react-modal": "^3.16.3 ",
|
||||
"@types/tinycolor2": "^1.4.6",
|
||||
"framer-motion": "^11.5.4",
|
||||
"happy-dom": "^15.7.4",
|
||||
"isomorphic-fetch": "^3.0.0",
|
||||
"nodemon": "^3.1.7",
|
||||
@@ -110,7 +109,6 @@
|
||||
"@mdi/js": ">=7.2.96",
|
||||
"@theme-ui/components": ">=0.16.0",
|
||||
"@theme-ui/core": ">=0.16.0",
|
||||
"framer-motion": ">=11",
|
||||
"react": ">=18",
|
||||
"react-dom": ">=18",
|
||||
"react-modal": ">=3",
|
||||
|
||||
@@ -28,29 +28,13 @@ import { MenuItem, Icon, MenuButton, MenuSeparator } from "@notesnook/ui";
|
||||
import { Box, Button, Flex, Text } from "@theme-ui/components";
|
||||
import { Icons } from "../../toolbar/icons.js";
|
||||
import Modal from "react-modal";
|
||||
import {
|
||||
motion,
|
||||
PanInfo,
|
||||
useMotionValue,
|
||||
useTransform,
|
||||
useAnimation
|
||||
} from "framer-motion";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import { EmotionThemeProvider, Theme } from "@notesnook/theme";
|
||||
|
||||
const AnimatedFlex = motion.create(Flex);
|
||||
|
||||
type ActionSheetHistoryItem = {
|
||||
title?: string;
|
||||
items?: MenuItem[];
|
||||
};
|
||||
const TRANSITION = {
|
||||
type: "spring",
|
||||
stiffness: 300,
|
||||
damping: 30,
|
||||
mass: 0.2,
|
||||
duration: 300
|
||||
};
|
||||
|
||||
function useHistory<T>(initial: T) {
|
||||
const [current, setCurrent] = useState<T | undefined>(initial);
|
||||
@@ -101,25 +85,127 @@ export function ActionSheetPresenter(
|
||||
} = props;
|
||||
const theme = useTheme() as Theme;
|
||||
const contentRef = useRef<HTMLDivElement>();
|
||||
const pressed = useRef(false);
|
||||
const startY = useRef(0);
|
||||
const reverse = false;
|
||||
const threshold = 50;
|
||||
const sheetTransition = "transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1)";
|
||||
const animationRef = useRef(0);
|
||||
const masterOffset = useRef(0);
|
||||
const sheetRef = useRef<HTMLDivElement>(null);
|
||||
const overlayRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const y = useMotionValue(0);
|
||||
const opacity = useTransform(
|
||||
y,
|
||||
[0, contentRef.current?.offsetHeight || window.innerHeight],
|
||||
[1, 0]
|
||||
);
|
||||
const animation = useAnimation();
|
||||
const onSwipeMove = (event: React.TouchEvent<HTMLDivElement>): void => {
|
||||
if (pressed.current) {
|
||||
const offset = event.touches[0].clientY - startY.current;
|
||||
move(offset);
|
||||
}
|
||||
};
|
||||
|
||||
const onMouseMove = (
|
||||
event: React.MouseEvent<HTMLDivElement, MouseEvent>
|
||||
): void => {
|
||||
event.stopPropagation();
|
||||
if (pressed.current) {
|
||||
if (reverse) {
|
||||
const offset = event.clientY - startY.current;
|
||||
move(offset);
|
||||
} else {
|
||||
const offset = event.clientY - startY.current;
|
||||
move(offset);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const move = (offset: number): boolean => {
|
||||
if (!reverse && offset > 0) {
|
||||
masterOffset.current = offset;
|
||||
animationRef.current = requestAnimationFrame(updatePosition);
|
||||
return true;
|
||||
} else if (reverse && offset < 0) {
|
||||
masterOffset.current = offset;
|
||||
animationRef.current = requestAnimationFrame(updatePosition);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const updatePosition = (): boolean => {
|
||||
if (animationRef.current !== undefined) {
|
||||
if (sheetRef.current) {
|
||||
sheetRef.current.style.transform = `translate3d(0, ${masterOffset.current}px, 0)`;
|
||||
if (overlayRef.current)
|
||||
overlayRef.current.style.opacity = `${
|
||||
1 - masterOffset.current / sheetRef.current.offsetHeight
|
||||
}`;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const onSwipeStart = (event: React.TouchEvent<HTMLDivElement>): void => {
|
||||
if (sheetRef?.current) sheetRef.current.style.transition = "none";
|
||||
startY.current = event.touches[0].clientY;
|
||||
changePressed(true);
|
||||
};
|
||||
|
||||
const onMouseStart = (
|
||||
event: React.MouseEvent<HTMLDivElement, MouseEvent>
|
||||
): void => {
|
||||
if (sheetRef?.current) sheetRef.current.style.transition = "none";
|
||||
startY.current = event.clientY;
|
||||
changePressed(true);
|
||||
};
|
||||
|
||||
const changePressed = (x: boolean): void => {
|
||||
pressed.current = x;
|
||||
};
|
||||
|
||||
const requestSheetDown = React.useCallback((): boolean => {
|
||||
if (sheetRef.current) {
|
||||
sheetRef.current.style.transition = sheetTransition;
|
||||
sheetRef.current.style.transform = reverse
|
||||
? "translate3d(0, -101%, 0)"
|
||||
: "translate3d(0, 101%, 0)";
|
||||
if (overlayRef.current) overlayRef.current.style.opacity = `0`;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}, [reverse, sheetTransition]);
|
||||
|
||||
const requestSheetUp = React.useCallback((): boolean => {
|
||||
if (sheetRef.current) {
|
||||
sheetRef.current.style.transform = `translate3d(0, 0%, 0)`;
|
||||
if (overlayRef.current) overlayRef.current.style.opacity = `1`;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}, []);
|
||||
|
||||
const onSwipeEnd = (): void => {
|
||||
cancelAnimationFrame(animationRef.current);
|
||||
changePressed(false);
|
||||
if (Math.abs(masterOffset.current) > threshold) {
|
||||
// setShow(false);
|
||||
requestSheetDown();
|
||||
console.log("CLSOING", masterOffset.current);
|
||||
setTimeout(() => {
|
||||
if (onClose) onClose();
|
||||
}, 300);
|
||||
} else {
|
||||
requestSheetUp();
|
||||
}
|
||||
masterOffset.current = 0;
|
||||
};
|
||||
|
||||
const onBeforeClose = useCallback(() => {
|
||||
const height = contentRef.current?.offsetHeight || window.innerHeight;
|
||||
requestSheetDown();
|
||||
setTimeout(() => {
|
||||
onClose?.();
|
||||
}, TRANSITION.duration - 50);
|
||||
animation.start({
|
||||
transition: TRANSITION,
|
||||
y: height + 100
|
||||
});
|
||||
}, [animation, onClose]);
|
||||
if (onClose) onClose();
|
||||
}, 300);
|
||||
}, [onClose, requestSheetDown]);
|
||||
|
||||
const handleBackPress = useCallback(
|
||||
(event: Event) => {
|
||||
@@ -156,7 +242,7 @@ export function ActionSheetPresenter(
|
||||
onRequestClose={() => onBeforeClose()}
|
||||
portalClassName={"bottom-sheet-presenter-portal"}
|
||||
onAfterOpen={() => {
|
||||
setTimeout(() => animation.start({ transition: TRANSITION, y: 0 }));
|
||||
setTimeout(() => requestSheetUp());
|
||||
}}
|
||||
overlayElement={(overlayElementProps, contentEl) => {
|
||||
return (
|
||||
@@ -172,12 +258,13 @@ export function ActionSheetPresenter(
|
||||
tabIndex={-1}
|
||||
>
|
||||
{blocking && (
|
||||
<motion.div
|
||||
id="action-sheet-overlay"
|
||||
<div
|
||||
ref={overlayRef}
|
||||
style={{
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
opacity,
|
||||
zIndex: 1000,
|
||||
transition: "opacity 0.3s ease-out",
|
||||
position: "absolute",
|
||||
backgroundColor: "var(--backdrop)"
|
||||
}}
|
||||
@@ -212,14 +299,12 @@ export function ActionSheetPresenter(
|
||||
</Box>
|
||||
)}
|
||||
>
|
||||
<AnimatedFlex
|
||||
animate={animation}
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
style={{ y }}
|
||||
initial={{ y: 1000 }}
|
||||
<Flex
|
||||
ref={sheetRef}
|
||||
sx={{
|
||||
bg: "background",
|
||||
transform: "translate3d(0, 101%, 0)",
|
||||
transition: sheetTransition,
|
||||
borderTopLeftRadius: 15,
|
||||
borderTopRightRadius: 15,
|
||||
boxShadow: theme?.shadows.menu || "none",
|
||||
@@ -228,34 +313,13 @@ export function ActionSheetPresenter(
|
||||
}}
|
||||
>
|
||||
{draggable && (
|
||||
<AnimatedFlex
|
||||
drag="y"
|
||||
onDrag={(_, { delta }: PanInfo) => {
|
||||
y.set(Math.max(y.get() + delta.y, 0));
|
||||
}}
|
||||
onDragEnd={(_, { velocity }: PanInfo) => {
|
||||
if (velocity.y >= 500) {
|
||||
onClose?.();
|
||||
return;
|
||||
}
|
||||
const sheetEl = contentRef.current;
|
||||
if (!sheetEl) return;
|
||||
|
||||
const contentHeight = sheetEl.offsetHeight;
|
||||
const threshold = 30;
|
||||
const closingHeight = (contentHeight * threshold) / 100;
|
||||
|
||||
if (y.get() >= closingHeight) {
|
||||
onBeforeClose();
|
||||
} else {
|
||||
setTimeout(() =>
|
||||
animation.start({ transition: TRANSITION, y: 0 })
|
||||
);
|
||||
}
|
||||
}}
|
||||
dragConstraints={{ top: 0, bottom: 0 }}
|
||||
dragMomentum={false}
|
||||
dragElastic={false}
|
||||
<Flex
|
||||
onMouseDown={onMouseStart}
|
||||
onMouseMove={onMouseMove}
|
||||
onMouseUp={onSwipeEnd}
|
||||
onTouchStart={onSwipeStart}
|
||||
onTouchMove={onSwipeMove}
|
||||
onTouchEnd={onSwipeEnd}
|
||||
sx={{
|
||||
bg: "transparent",
|
||||
alignItems: "center",
|
||||
@@ -272,12 +336,12 @@ export function ActionSheetPresenter(
|
||||
borderRadius: 100
|
||||
}}
|
||||
/>
|
||||
</AnimatedFlex>
|
||||
</Flex>
|
||||
)}
|
||||
<ContentContainer items={items} title={title} onClose={onClose}>
|
||||
{children}
|
||||
</ContentContainer>
|
||||
</AnimatedFlex>
|
||||
</Flex>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -38,13 +38,10 @@ import {
|
||||
toBlobURL,
|
||||
toDataURL
|
||||
} from "../../utils/downloader.js";
|
||||
import { motion } from "framer-motion";
|
||||
import { useObserver } from "../../hooks/use-observer.js";
|
||||
import { Attachment, ImageAlignmentOptions } from "../attachment/index.js";
|
||||
import { DataURL } from "@notesnook/common";
|
||||
|
||||
export const AnimatedImage = motion.create(Image);
|
||||
|
||||
export function ImageComponent(
|
||||
props: ReactNodeViewProps<Partial<ImageAttributes>>
|
||||
) {
|
||||
@@ -252,11 +249,8 @@ export function ImageComponent(
|
||||
/>
|
||||
</Flex>
|
||||
)}
|
||||
<AnimatedImage
|
||||
<Image
|
||||
as={isSVG ? "object" : "img"}
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: bloburl || src ? 1 : 0 }}
|
||||
transition={{ duration: 0.2, ease: "easeIn" }}
|
||||
data-drag-image
|
||||
ref={imageRef}
|
||||
alt={alt}
|
||||
@@ -271,6 +265,8 @@ export function ImageComponent(
|
||||
})}
|
||||
title={title}
|
||||
sx={{
|
||||
animation: bloburl || src ? "0.2s ease-in 0s 1 fadeIn" : "none",
|
||||
opacity: 0,
|
||||
objectFit: "contain",
|
||||
width: editor.isEditable ? "100%" : size.width,
|
||||
height: editor.isEditable ? "100%" : size.height,
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
@keyframes fadeIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.ProseMirror p span {
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user