From 06044280a235e860db5d2e162bf460c029211ddd Mon Sep 17 00:00:00 2001 From: pipisebastian Date: Sun, 24 Nov 2024 07:26:38 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=208=EB=B0=A9=ED=96=A5=EC=97=90=20?= =?UTF-8?q?=EB=8C=80=ED=95=9C=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #178 --- client/src/features/page/Page.style.ts | 98 ++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 6 deletions(-) diff --git a/client/src/features/page/Page.style.ts b/client/src/features/page/Page.style.ts index 563c3748..8483df13 100644 --- a/client/src/features/page/Page.style.ts +++ b/client/src/features/page/Page.style.ts @@ -26,11 +26,97 @@ export const pageHeader = css({ }, }); -export const resizeHandle = css({ +const baseResizeHandle = css({ + zIndex: 1, position: "absolute", - right: "-10px", - bottom: "-10px", - width: "32px", - height: "32px", - cursor: "se-resize", }); + +export const resizeHandles = { + top: cx( + baseResizeHandle, + css({ + top: "-5px", + left: "5px", + right: "5px", + height: "10px", + cursor: "n-resize", + }), + ), + + bottom: cx( + baseResizeHandle, + css({ + left: "5px", + right: "5px", + bottom: "-5px", + height: "10px", + cursor: "s-resize", + }), + ), + + left: cx( + baseResizeHandle, + css({ + top: "5px", + left: "-5px", + bottom: "5px", + width: "10px", + cursor: "w-resize", + }), + ), + + right: cx( + baseResizeHandle, + css({ + top: "5px", + right: "-5px", + bottom: "5px", + width: "10px", + cursor: "e-resize", + }), + ), + + topLeft: cx( + baseResizeHandle, + css({ + top: "-10px", + left: "-10px", + width: "24px", + height: "24px", + cursor: "nw-resize", + }), + ), + + topRight: cx( + baseResizeHandle, + css({ + top: "-10px", + right: "-10px", + width: "24px", + height: "24px", + cursor: "ne-resize", + }), + ), + + bottomLeft: cx( + baseResizeHandle, + css({ + left: "-10px", + bottom: "-10px", + width: "24px", + height: "24px", + cursor: "sw-resize", + }), + ), + + bottomRight: cx( + baseResizeHandle, + css({ + right: "-10px", + bottom: "-10px", + width: "24px", + height: "24px", + cursor: "se-resize", + }), + ), +}; From bd7d1b6beebbc2eb291768ac9df91574533ff277 Mon Sep 17 00:00:00 2001 From: pipisebastian Date: Sun, 24 Nov 2024 07:26:49 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=208=20=EB=B0=A9=ED=96=A5=EC=97=90=20?= =?UTF-8?q?=EB=A6=AC=EC=82=AC=EC=9D=B4=EC=A7=95=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #178 --- client/src/features/page/Page.tsx | 29 +++-- client/src/features/page/hooks/usePage.ts | 122 ++++++++++++++++++++-- 2 files changed, 124 insertions(+), 27 deletions(-) diff --git a/client/src/features/page/Page.tsx b/client/src/features/page/Page.tsx index 23bf3d15..a376a5fd 100644 --- a/client/src/features/page/Page.tsx +++ b/client/src/features/page/Page.tsx @@ -2,12 +2,10 @@ import { serializedEditorDataProps } from "@noctaCrdt/Interfaces"; import { motion, AnimatePresence } from "framer-motion"; import { Editor } from "@features/editor/Editor"; import { Page as PageType } from "@src/types/page"; -import { pageAnimation, resizeHandleAnimation } from "./Page.animation"; -import { pageContainer, pageHeader, resizeHandle } from "./Page.style"; - +import { pageContainer, pageHeader, resizeHandles } from "./Page.style"; import { PageControlButton } from "./components/PageControlButton/PageControlButton"; import { PageTitle } from "./components/PageTitle/PageTitle"; -import { usePage } from "./hooks/usePage"; +import { DIRECTIONS, usePage } from "./hooks/usePage"; interface PageProps extends PageType { handlePageSelect: ({ pageId, isSidebar }: { pageId: string; isSidebar?: boolean }) => void; @@ -45,17 +43,12 @@ export const Page = ({ return ( - - - + {DIRECTIONS.map((direction) => ( + pageResize(e, direction)} + /> + ))} + ); }; diff --git a/client/src/features/page/hooks/usePage.ts b/client/src/features/page/hooks/usePage.ts index 61cbf7b5..f9cb9a40 100644 --- a/client/src/features/page/hooks/usePage.ts +++ b/client/src/features/page/hooks/usePage.ts @@ -5,6 +5,18 @@ import { useIsSidebarOpen } from "@stores/useSidebarStore"; import { Position, Size } from "@src/types/page"; const PADDING = SPACING.MEDIUM * 2; +export const DIRECTIONS = [ + "top", + "bottom", + "left", + "right", + "topLeft", + "topRight", + "bottomLeft", + "bottomRight", +] as const; + +type Direction = (typeof DIRECTIONS)[number]; export const usePage = ({ x, y }: Position) => { const [position, setPosition] = useState({ x, y }); @@ -68,28 +80,118 @@ export const usePage = ({ x, y }: Position) => { document.addEventListener("pointerup", handleDragEnd); }; - const pageResize = (e: React.MouseEvent) => { + const pageResize = (e: React.MouseEvent, direction: Direction) => { e.preventDefault(); const startX = e.clientX; const startY = e.clientY; const startWidth = size.width; const startHeight = size.height; + const startPosition = { x: position.x, y: position.y }; const resize = (e: MouseEvent) => { const deltaX = e.clientX - startX; const deltaY = e.clientY - startY; - const newWidth = Math.max( - PAGE.MIN_WIDTH, - Math.min(startWidth + deltaX, window.innerWidth - position.x - getSidebarWidth() - PADDING), - ); - - const newHeight = Math.max( - PAGE.MIN_HEIGHT, - Math.min(startHeight + deltaY, window.innerHeight - position.y - PADDING), - ); + let newWidth = startWidth; + let newHeight = startHeight; + let newX = startPosition.x; + let newY = startPosition.y; + + switch (direction) { + case "right": { + // startWidth + deltaX 가 계속해서 변하는 값. 사용자가 마우스를 움직이면서 계속해서 변함 + newWidth = Math.min( + window.innerWidth - startPosition.x - getSidebarWidth() - PADDING, // 최대 넓이를 지정하고 싶을때 Math.min + Math.max(PAGE.MIN_WIDTH, startWidth + deltaX), //최소 넓이를 지정하고 싶을때 Math.max + ); + break; + } + + case "left": { + newWidth = Math.min( + startPosition.x + startWidth, + Math.max(PAGE.MIN_WIDTH, startWidth - deltaX), + ); + newX = Math.max(0, startPosition.x + startWidth - newWidth); + break; + } + + case "bottom": { + newHeight = Math.min( + window.innerHeight - startPosition.y - PADDING, + Math.max(PAGE.MIN_HEIGHT, startHeight + deltaY), + ); + break; + } + + case "top": { + newHeight = Math.min( + startPosition.y + startHeight, + Math.max(PAGE.MIN_HEIGHT, startHeight - deltaY), + ); + newY = Math.max(0, startPosition.y + startHeight - newHeight); + break; + } + + case "topLeft": { + newHeight = Math.min( + startPosition.y + startHeight, + Math.max(PAGE.MIN_HEIGHT, startHeight - deltaY), + ); + newY = Math.max(0, startPosition.y + startHeight - newHeight); + + newWidth = Math.min( + startPosition.x + startWidth, + Math.max(PAGE.MIN_WIDTH, startWidth - deltaX), + ); + newX = Math.max(0, startPosition.x + startWidth - newWidth); + break; + } + + case "topRight": { + newHeight = Math.min( + startPosition.y + startHeight, + Math.max(PAGE.MIN_HEIGHT, startHeight - deltaY), + ); + newY = Math.max(0, startPosition.y + startHeight - newHeight); + + newWidth = Math.min( + window.innerWidth - startPosition.x - getSidebarWidth() - PADDING, + Math.max(PAGE.MIN_WIDTH, startWidth + deltaX), + ); + break; + } + + case "bottomLeft": { + newHeight = Math.min( + window.innerHeight - startPosition.y - PADDING, + Math.max(PAGE.MIN_HEIGHT, startHeight + deltaY), + ); + + newWidth = Math.min( + startPosition.x + startWidth, + Math.max(PAGE.MIN_WIDTH, startWidth - deltaX), + ); + newX = Math.max(0, startPosition.x + startWidth - newWidth); + break; + } + + case "bottomRight": { + newHeight = Math.min( + window.innerHeight - startPosition.y - PADDING, + Math.max(PAGE.MIN_HEIGHT, startHeight + deltaY), + ); + + newWidth = Math.min( + window.innerWidth - startPosition.x - getSidebarWidth() - PADDING, + Math.max(PAGE.MIN_WIDTH, startWidth + deltaX), + ); + break; + } + } setSize({ width: newWidth, height: newHeight }); + setPosition({ x: newX, y: newY }); }; const stopResize = () => { From fc2cda977a75d3274d795dc27ddc7dc9c3b0e81e Mon Sep 17 00:00:00 2001 From: pipisebastian Date: Sun, 24 Nov 2024 07:32:56 +0900 Subject: [PATCH 3/3] =?UTF-8?q?refactor:=20=EC=A3=BC=EC=84=9D=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #178 --- client/src/features/page/hooks/usePage.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/src/features/page/hooks/usePage.ts b/client/src/features/page/hooks/usePage.ts index f9cb9a40..088d6831 100644 --- a/client/src/features/page/hooks/usePage.ts +++ b/client/src/features/page/hooks/usePage.ts @@ -99,10 +99,9 @@ export const usePage = ({ x, y }: Position) => { switch (direction) { case "right": { - // startWidth + deltaX 가 계속해서 변하는 값. 사용자가 마우스를 움직이면서 계속해서 변함 newWidth = Math.min( - window.innerWidth - startPosition.x - getSidebarWidth() - PADDING, // 최대 넓이를 지정하고 싶을때 Math.min - Math.max(PAGE.MIN_WIDTH, startWidth + deltaX), //최소 넓이를 지정하고 싶을때 Math.max + window.innerWidth - startPosition.x - getSidebarWidth() - PADDING, + Math.max(PAGE.MIN_WIDTH, startWidth + deltaX), ); break; }