diff --git a/client/package.json b/client/package.json index 2f79c064..779c9b76 100644 --- a/client/package.json +++ b/client/package.json @@ -17,6 +17,7 @@ "react": "^18.3.1", "react-dom": "^18.3.1", "socket.io-client": "^4.8.1", + "vite-plugin-svgr": "^4.3.0", "zustand": "^5.0.1" }, "devDependencies": { diff --git a/client/src/assets/icons/close.svg b/client/src/assets/icons/close.svg new file mode 100644 index 00000000..3098f92d --- /dev/null +++ b/client/src/assets/icons/close.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/src/assets/icons/expand.svg b/client/src/assets/icons/expand.svg new file mode 100644 index 00000000..71f2465c --- /dev/null +++ b/client/src/assets/icons/expand.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/src/assets/icons/minus.svg b/client/src/assets/icons/minus.svg new file mode 100644 index 00000000..6dc66acf --- /dev/null +++ b/client/src/assets/icons/minus.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/src/assets/images/background.png b/client/src/assets/images/background.png index 9b9ee52b..9ee392c5 100644 Binary files a/client/src/assets/images/background.png and b/client/src/assets/images/background.png differ diff --git a/client/src/components/bottomNavigator/BottomNavigator.tsx b/client/src/components/bottomNavigator/BottomNavigator.tsx index fcfc6f50..23a3f6db 100644 --- a/client/src/components/bottomNavigator/BottomNavigator.tsx +++ b/client/src/components/bottomNavigator/BottomNavigator.tsx @@ -1,12 +1,12 @@ -import { Page } from "@src/types/page"; import { motion } from "framer-motion"; import { IconButton } from "@components/button/IconButton"; +import { Page } from "@src/types/page"; import { animation } from "./BottomNavigator.animation"; import { bottomNavigatorContainer } from "./BottomNavigator.style"; interface BottomNavigatorProps { pages: Page[]; - handlePageSelect: (pageId: number) => void; + handlePageSelect: ({ pageId, isSidebar }: { pageId: number; isSidebar?: boolean }) => void; } export const BottomNavigator = ({ pages, handlePageSelect }: BottomNavigatorProps) => { @@ -25,7 +25,9 @@ export const BottomNavigator = ({ pages, handlePageSelect }: BottomNavigatorProp icon={page.icon} size="md" onClick={() => { - handlePageSelect(page.id); + handlePageSelect({ + pageId: page.id, + }); }} /> diff --git a/client/src/components/modal/modal.animation.ts b/client/src/components/modal/modal.animation.ts index f5f1efb1..a0bdef14 100644 --- a/client/src/components/modal/modal.animation.ts +++ b/client/src/components/modal/modal.animation.ts @@ -11,19 +11,7 @@ export const overlayAnimation = { }; export const modalContainerAnimation = { - initial: { - scale: 0.7, - opacity: 0, - top: "50%", - left: "50%", - transform: "translate(-50%, -50%)", - }, - animate: { - scale: 1, - opacity: 1, - }, - exit: { - scale: 0.7, - opacity: 0, - }, + initial: { opacity: 0, y: 50, scale: 0.3 }, + animate: { opacity: 1, y: 0, scale: 1 }, + exit: { opacity: 0, scale: 0.5, transition: { duration: 0.2 } }, }; diff --git a/client/src/components/modal/modal.style.ts b/client/src/components/modal/modal.style.ts index 8ed080bd..f0998fea 100644 --- a/client/src/components/modal/modal.style.ts +++ b/client/src/components/modal/modal.style.ts @@ -27,8 +27,6 @@ export const modalContainer = cx( display: "flex", zIndex: 10001, position: "absolute", - top: "50%", - left: "50%", transform: "translate(-50%, -50%)", flexDirection: "column", width: "400px", diff --git a/client/src/components/sidebar/MenuButton.style.ts b/client/src/components/sidebar/MenuButton.style.ts index 72859892..8a3f95e1 100644 --- a/client/src/components/sidebar/MenuButton.style.ts +++ b/client/src/components/sidebar/MenuButton.style.ts @@ -14,6 +14,7 @@ export const imageBox = css({ borderRadius: "sm", width: "50px", height: "50px", + background: "white", overflow: "hidden", }); diff --git a/client/src/components/sidebar/MenuButton.tsx b/client/src/components/sidebar/MenuButton.tsx index 8402c5a2..19c81ff9 100644 --- a/client/src/components/sidebar/MenuButton.tsx +++ b/client/src/components/sidebar/MenuButton.tsx @@ -3,9 +3,7 @@ import { menuItemWrapper, imageBox, textBox } from "./MenuButton.style"; export const MenuButton = () => { return (
-
- -
+

Noctturn

); diff --git a/client/src/components/sidebar/PageItem.style.ts b/client/src/components/sidebar/PageItem.style.ts index 5ee503aa..fc61c4b2 100644 --- a/client/src/components/sidebar/PageItem.style.ts +++ b/client/src/components/sidebar/PageItem.style.ts @@ -5,6 +5,7 @@ export const pageItemContainer = css({ gap: "sm", alignItems: "center", width: "100%", + height: "56px", paddingInline: "md", "&:hover": { background: "white/50", @@ -14,6 +15,7 @@ export const pageItemContainer = css({ export const iconBox = css({ display: "flex", + flexShrink: 0, justifyContent: "center", alignItems: "center", borderRadius: "xs", @@ -26,4 +28,7 @@ export const iconBox = css({ export const textBox = css({ textStyle: "display-medium20", color: "gray.700", + textOverflow: "ellipsis", + overflow: "hidden", + whiteSpace: "nowrap", }); diff --git a/client/src/components/sidebar/Sidebar.style.ts b/client/src/components/sidebar/Sidebar.style.ts index 6f5c3fad..2cf411d3 100644 --- a/client/src/components/sidebar/Sidebar.style.ts +++ b/client/src/components/sidebar/Sidebar.style.ts @@ -16,11 +16,14 @@ export const navWrapper = css({ gap: "md", flexDirection: "column", width: "100%", + overflowX: "hidden", + overflowY: "scroll", }); export const plusIconBox = css({ display: "flex", justifyContent: "start", + marginBlock: "10px", paddingInline: "md", }); diff --git a/client/src/components/sidebar/Sidebar.tsx b/client/src/components/sidebar/Sidebar.tsx index 596d4e2a..db623778 100644 --- a/client/src/components/sidebar/Sidebar.tsx +++ b/client/src/components/sidebar/Sidebar.tsx @@ -1,7 +1,10 @@ -import { useIsSidebarOpen, useSidebarActions } from "@src/stores/useSidebarStore"; -import { Page } from "@src/types/page"; import { motion } from "framer-motion"; import { IconButton } from "@components/button/IconButton"; +import { Modal } from "@components/modal/modal"; +import { useModal } from "@components/modal/useModal"; +import { MAX_VISIBLE_PAGE } from "@src/constants/page"; +import { useIsSidebarOpen, useSidebarActions } from "@src/stores/useSidebarStore"; +import { Page } from "@src/types/page"; import { MenuButton } from "./MenuButton"; import { PageItem } from "./PageItem"; import { animation, contentVariants, sidebarVariants } from "./Sidebar.animation"; @@ -14,10 +17,30 @@ export const Sidebar = ({ }: { pages: Page[]; handlePageAdd: () => void; - handlePageSelect: (pageId: number, isSidebar: boolean) => void; + handlePageSelect: ({ pageId }: { pageId: number }) => void; }) => { + const visiblePages = pages.filter((page) => page.isVisible); + const isMaxVisiblePage = visiblePages.length >= MAX_VISIBLE_PAGE; + const isSidebarOpen = useIsSidebarOpen(); const { toggleSidebar } = useSidebarActions(); + const { isOpen, openModal, closeModal } = useModal(); + + const handlePageItemClick = (id: number) => { + if (isMaxVisiblePage) { + openModal(); + return; + } + handlePageSelect({ pageId: id }); + }; + + const handleAddPageButtonClick = () => { + if (isMaxVisiblePage) { + openModal(); + return; + } + handlePageAdd(); + }; return ( {isSidebarOpen ? "«" : "»"} - - + + + {pages?.map((item) => ( - handlePageSelect(item.id, true)} /> + handlePageItemClick(item.id)} /> ))} -
- -
+ + + + +

+ 최대 {MAX_VISIBLE_PAGE}개의 페이지만 표시할 수 있습니다 +
+ 사용하지 않는 페이지는 닫아주세요. +

+
); }; diff --git a/client/src/constants/page.ts b/client/src/constants/page.ts new file mode 100644 index 00000000..bc01c68f --- /dev/null +++ b/client/src/constants/page.ts @@ -0,0 +1 @@ +export const MAX_VISIBLE_PAGE = 10; diff --git a/client/src/features/page/Page.animation.ts b/client/src/features/page/Page.animation.ts index 1ab36da8..63e80890 100644 --- a/client/src/features/page/Page.animation.ts +++ b/client/src/features/page/Page.animation.ts @@ -1,6 +1,6 @@ export const pageAnimation = { initial: { - x: -300, + x: 0, y: 0, opacity: 0, scale: 0.8, @@ -12,7 +12,9 @@ export const pageAnimation = { scale: 1, boxShadow: isActive ? "0 8px 30px rgba(0,0,0,0.15)" : "0 2px 10px rgba(0,0,0,0.1)", transition: { - boxShadow: { duration: 0.2 }, + x: { type: "tween", duration: 0.03, ease: "linear" }, + y: { type: "tween", duration: 0.03, ease: "linear" }, + scale: { type: "spring", stiffness: 300, damping: 15 }, }, }), }; diff --git a/client/src/features/page/Page.style.ts b/client/src/features/page/Page.style.ts index a286df1f..563c3748 100644 --- a/client/src/features/page/Page.style.ts +++ b/client/src/features/page/Page.style.ts @@ -4,7 +4,9 @@ import { glassContainer } from "@styled-system/recipes"; export const pageContainer = cx( glassContainer({ border: "lg" }), css({ + display: "flex", position: "absolute", + flexDirection: "column", width: "450px", height: "400px", }), @@ -24,11 +26,6 @@ export const pageHeader = css({ }, }); -export const pageTitle = css({ - textStyle: "display-medium24", - color: "gray.500", -}); - export const resizeHandle = css({ position: "absolute", right: "-10px", diff --git a/client/src/features/page/Page.tsx b/client/src/features/page/Page.tsx index 7c03267a..74272e7b 100644 --- a/client/src/features/page/Page.tsx +++ b/client/src/features/page/Page.tsx @@ -1,7 +1,6 @@ -import { Page as PageType } from "@src/types/page"; import { motion, AnimatePresence } from "framer-motion"; -import { useRef } from "react"; 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"; @@ -10,7 +9,7 @@ import { PageTitle } from "./components/PageTitle/PageTitle"; import { usePage } from "./hooks/usePage"; interface PageProps extends PageType { - handlePageSelect: (pageId: number) => void; + handlePageSelect: ({ pageId, isSidebar }: { pageId: number; isSidebar?: boolean }) => void; handlePageClose: (pageId: number) => void; handleTitleChange: (pageId: number, newTitle: string) => void; } @@ -26,7 +25,6 @@ export const Page = ({ handlePageClose, handleTitleChange, }: PageProps) => { - const pageRef = useRef(null); const { position, size, pageDrag, pageResize, pageMinimize, pageMaximize } = usePage({ x, y }); const onTitleChange = (newTitle: string) => { @@ -36,7 +34,6 @@ export const Page = ({ return ( handlePageSelect(id)} + onPointerDown={() => + handlePageSelect({ + pageId: id, + }) + } >
diff --git a/client/src/features/page/components/PageControlButton/PageControlButton.style.ts b/client/src/features/page/components/PageControlButton/PageControlButton.style.ts index 1aa0c628..417da660 100644 --- a/client/src/features/page/components/PageControlButton/PageControlButton.style.ts +++ b/client/src/features/page/components/PageControlButton/PageControlButton.style.ts @@ -3,6 +3,12 @@ import { css, cva } from "@styled-system/css"; export const pageControlContainer = css({ display: "flex", gap: "sm", + _hover: { + "& svg": { + transform: "scale(1)", // 추가 효과 + opacity: 1, + }, + }, }); export const pageControlButton = cva({ @@ -20,3 +26,11 @@ export const pageControlButton = cva({ }, }, }); + +export const iconBox = css({ + transform: "scale(0.8)", + strokeWidth: "2.5px", + color: "white/90", + opacity: 0, + transition: "all 0.1s ease", +}); diff --git a/client/src/features/page/components/PageControlButton/PageControlButton.tsx b/client/src/features/page/components/PageControlButton/PageControlButton.tsx index 8287b117..1224e29b 100644 --- a/client/src/features/page/components/PageControlButton/PageControlButton.tsx +++ b/client/src/features/page/components/PageControlButton/PageControlButton.tsx @@ -1,4 +1,7 @@ -import { pageControlContainer, pageControlButton } from "./PageControlButton.style"; +import CloseIcon from "@assets/icons/close.svg?react"; +import ExpandIcon from "@assets/icons/expand.svg?react"; +import MinusIcon from "@assets/icons/minus.svg?react"; +import { pageControlContainer, pageControlButton, iconBox } from "./PageControlButton.style"; interface PageControlButtonProps { onPageMinimize?: () => void; @@ -13,11 +16,15 @@ export const PageControlButton = ({ }: PageControlButtonProps) => { return (
- + +
); }; diff --git a/client/src/features/page/components/PageTitle/PageTitle.style.ts b/client/src/features/page/components/PageTitle/PageTitle.style.ts index df1cc901..f0d967cd 100644 --- a/client/src/features/page/components/PageTitle/PageTitle.style.ts +++ b/client/src/features/page/components/PageTitle/PageTitle.style.ts @@ -3,4 +3,7 @@ import { css } from "@styled-system/css"; export const pageTitle = css({ textStyle: "display-medium24", color: "gray.500", + textOverflow: "ellipsis", + overflow: "hidden", + whiteSpace: "nowrap", }); diff --git a/client/src/features/page/hooks/usePage.ts b/client/src/features/page/hooks/usePage.ts index 2ec215b0..618edd2c 100644 --- a/client/src/features/page/hooks/usePage.ts +++ b/client/src/features/page/hooks/usePage.ts @@ -1,8 +1,8 @@ -import { useIsSidebarOpen } from "@src/stores/useSidebarStore"; -import { Position, Size } from "@src/types/page"; import { useEffect, useState } from "react"; import { PAGE, SIDE_BAR } from "@constants/size"; import { SPACING } from "@constants/spacing"; +import { useIsSidebarOpen } from "@src/stores/useSidebarStore"; +import { Position, Size } from "@src/types/page"; const PADDING = SPACING.MEDIUM * 2; diff --git a/client/src/features/workSpace/hooks/usePagesManage.ts b/client/src/features/workSpace/hooks/usePagesManage.ts index 957ce3dc..6229d263 100644 --- a/client/src/features/workSpace/hooks/usePagesManage.ts +++ b/client/src/features/workSpace/hooks/usePagesManage.ts @@ -1,18 +1,10 @@ +import { useEffect, useState } from "react"; import { Page } from "@src/types/page"; -import { useState } from "react"; - -interface usePagesManageProps { - pages: Page[]; - addPage: () => void; - selectPage: (pageId: number, isSidebar?: boolean) => void; - closePage: (pageId: number) => void; - updatePageTitle: (pageId: number, newTitle: string) => void; -} const INIT_ICON = "📄"; const PAGE_OFFSET = 60; -export const usePagesManage = (): usePagesManageProps => { +export const usePagesManage = () => { const [pages, setPages] = useState([]); const getZIndex = () => { @@ -37,14 +29,14 @@ export const usePagesManage = (): usePagesManageProps => { ]); }; - const selectPage = (pageId: number, isSidebar: boolean = false) => { + const selectPage = ({ pageId }: { pageId: number }) => { setPages((prevPages) => prevPages.map((page) => ({ ...page, isActive: page.id === pageId, ...(page.id === pageId && { zIndex: getZIndex(), - isVisible: isSidebar ? true : page.isVisible, + isVisible: true, }), })), ); @@ -62,6 +54,21 @@ export const usePagesManage = (): usePagesManageProps => { ); }; + // 서버에서 처음 불러올때는 좌표를 모르기에, 초기화 과정 필요 + const initPagePosition = () => { + setPages((prevPages) => + prevPages.map((page, index) => ({ + ...page, + x: PAGE_OFFSET * index, + y: PAGE_OFFSET * index, + })), + ); + }; + + useEffect(() => { + initPagePosition(); + }, []); + return { pages, addPage, diff --git a/client/src/styles/global.ts b/client/src/styles/global.ts index 837bd8e5..6ee9c598 100644 --- a/client/src/styles/global.ts +++ b/client/src/styles/global.ts @@ -6,4 +6,21 @@ export const globalStyles = defineGlobalStyles({ backgroundSize: "cover", // TODO 폰트 설정 }, + + // 스크롤바 전체 + "::-webkit-scrollbar": { + width: "8px", + }, + + // 스크롤바 전체 영역 + "::-webkit-scrollbar-track": { + background: "transparent", + marginBottom: "12px", + }, + + // 스크롤바 핸들 + "::-webkit-scrollbar-thumb": { + background: "white/50", + borderRadius: "lg", + }, }); diff --git a/client/tsconfig.json b/client/tsconfig.json index 9af798bf..1ed5bc84 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -16,7 +16,7 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "composite": true, - "types": ["vite/client"], + "types": ["vite/client", "vite-plugin-svgr/client"], "baseUrl": ".", "paths": { "@src/*": ["src/*"], diff --git a/client/vite-env-override.d.ts b/client/vite-env-override.d.ts new file mode 100644 index 00000000..3a982e15 --- /dev/null +++ b/client/vite-env-override.d.ts @@ -0,0 +1,4 @@ +declare module "*.svg" { + const content: React.FC>; + export default content; +} diff --git a/client/vite.config.ts b/client/vite.config.ts index c857bc33..12ba9500 100644 --- a/client/vite.config.ts +++ b/client/vite.config.ts @@ -2,8 +2,11 @@ import { defineConfig } from "vite"; import path from "path"; import react from "@vitejs/plugin-react"; import tsconfigPaths from "vite-tsconfig-paths"; +import svgr from "vite-plugin-svgr"; export default defineConfig({ - plugins: [react(), tsconfigPaths()], - resolve: { alias: { "@noctaCrdt": path.resolve(__dirname, "../@noctaCrdt") } }, + plugins: [react(), tsconfigPaths(), svgr()], + resolve: { + alias: { "@noctaCrdt": path.resolve(__dirname, "../@noctaCrdt") }, + }, }); diff --git a/client/vite.env.d.ts b/client/vite.env.d.ts new file mode 100644 index 00000000..2ca039ea --- /dev/null +++ b/client/vite.env.d.ts @@ -0,0 +1,2 @@ +// / +// / diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 190afeb2..1572c74b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -79,6 +79,9 @@ importers: socket.io-client: specifier: ^4.8.1 version: 4.8.1 + vite-plugin-svgr: + specifier: ^4.3.0 + version: 4.3.0(rollup@4.24.3)(typescript@5.3.3)(vite@5.4.10(@types/node@20.17.6)(lightningcss@1.25.1)(terser@5.36.0)) zustand: specifier: ^5.0.1 version: 5.0.1(@types/react@18.3.12)(react@18.3.1) @@ -1116,6 +1119,15 @@ packages: resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@rollup/pluginutils@5.1.3': + resolution: {integrity: sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + '@rollup/rollup-android-arm-eabi@4.24.3': resolution: {integrity: sha512-ufb2CH2KfBWPJok95frEZZ82LtDl0A6QKTa8MoM+cWwDZvVGl5/jNb79pIhRvAalUu+7LD91VYR0nwRD799HkQ==} cpu: [arm] @@ -1228,6 +1240,74 @@ packages: '@socket.io/component-emitter@3.1.2': resolution: {integrity: sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==} + '@svgr/babel-plugin-add-jsx-attribute@8.0.0': + resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-remove-jsx-attribute@8.0.0': + resolution: {integrity: sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0': + resolution: {integrity: sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0': + resolution: {integrity: sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-svg-dynamic-title@8.0.0': + resolution: {integrity: sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-svg-em-dimensions@8.0.0': + resolution: {integrity: sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-transform-react-native-svg@8.1.0': + resolution: {integrity: sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-transform-svg-component@8.0.0': + resolution: {integrity: sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==} + engines: {node: '>=12'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-preset@8.1.0': + resolution: {integrity: sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/core@8.1.0': + resolution: {integrity: sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==} + engines: {node: '>=14'} + + '@svgr/hast-util-to-babel-ast@8.0.0': + resolution: {integrity: sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==} + engines: {node: '>=14'} + + '@svgr/plugin-jsx@8.1.0': + resolution: {integrity: sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==} + engines: {node: '>=14'} + peerDependencies: + '@svgr/core': '*' + '@ts-morph/common@0.22.0': resolution: {integrity: sha512-HqNBuV/oIlMKdkLshXd1zKBqNQCsuPEsgQOkfFQ/eUKjRlwndXW1AjN9LVkBEIukm00gGXSRmfkl0Wv5VXLnlw==} @@ -2129,6 +2209,9 @@ packages: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} + dot-case@3.0.4: + resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + dotenv-expand@10.0.0: resolution: {integrity: sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==} engines: {node: '>=12'} @@ -3353,6 +3436,9 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true + lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -3596,6 +3682,9 @@ packages: resolution: {integrity: sha512-lDcBsjBSMlj3LXH2v/FW3txlh2pYTjmbOXPYJD93HI5EwuLzI11tdHSIpUMmfq/IOsldj4Ps8M8flhm+pCK4Ew==} engines: {node: '>=12.22.0'} + no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + node-abort-controller@3.1.1: resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} @@ -3785,6 +3874,10 @@ packages: resolution: {integrity: sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==} engines: {node: '>=12'} + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} @@ -4152,6 +4245,9 @@ packages: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + snake-case@3.0.4: + resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} + socket.io-adapter@2.5.5: resolution: {integrity: sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==} @@ -4301,6 +4397,9 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + svg-parser@2.0.4: + resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} + symbol-observable@4.0.0: resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} engines: {node: '>=0.10'} @@ -4580,6 +4679,11 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} + vite-plugin-svgr@4.3.0: + resolution: {integrity: sha512-Jy9qLB2/PyWklpYy0xk0UU3TlU0t2UMpJXZvf+hWII1lAmRHrOUKi11Uw8N3rxoNk7atZNYO3pR3vI1f7oi+6w==} + peerDependencies: + vite: '>=2.6.0' + vite-tsconfig-paths@5.1.0: resolution: {integrity: sha512-Y1PLGHCJfAq1Zf4YIGEsmuU/NCX1epoZx9zwSr32Gjn3aalwQHRKr5aUmbo6r0JHeHkqmWpmDg7WOynhYXw1og==} peerDependencies: @@ -5939,6 +6043,14 @@ snapshots: '@pkgr/core@0.1.1': {} + '@rollup/pluginutils@5.1.3(rollup@4.24.3)': + dependencies: + '@types/estree': 1.0.6 + estree-walker: 2.0.2 + picomatch: 4.0.2 + optionalDependencies: + rollup: 4.24.3 + '@rollup/rollup-android-arm-eabi@4.24.3': optional: true @@ -6021,6 +6133,76 @@ snapshots: '@socket.io/component-emitter@3.1.2': {} + '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + + '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + + '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + + '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + + '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + + '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + + '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + + '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + + '@svgr/babel-preset@8.1.0(@babel/core@7.26.0)': + dependencies: + '@babel/core': 7.26.0 + '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.26.0) + '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.26.0) + '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.26.0) + '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.26.0) + '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.26.0) + '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.26.0) + '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.26.0) + '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.26.0) + + '@svgr/core@8.1.0(typescript@5.3.3)': + dependencies: + '@babel/core': 7.26.0 + '@svgr/babel-preset': 8.1.0(@babel/core@7.26.0) + camelcase: 6.3.0 + cosmiconfig: 8.3.6(typescript@5.3.3) + snake-case: 3.0.4 + transitivePeerDependencies: + - supports-color + - typescript + + '@svgr/hast-util-to-babel-ast@8.0.0': + dependencies: + '@babel/types': 7.26.0 + entities: 4.5.0 + + '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.3.3))': + dependencies: + '@babel/core': 7.26.0 + '@svgr/babel-preset': 8.1.0(@babel/core@7.26.0) + '@svgr/core': 8.1.0(typescript@5.3.3) + '@svgr/hast-util-to-babel-ast': 8.0.0 + svg-parser: 2.0.4 + transitivePeerDependencies: + - supports-color + '@ts-morph/common@0.22.0': dependencies: fast-glob: 3.3.2 @@ -7050,6 +7232,11 @@ snapshots: dependencies: esutils: 2.0.3 + dot-case@3.0.4: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + dotenv-expand@10.0.0: {} dotenv@16.4.5: {} @@ -8650,6 +8837,10 @@ snapshots: dependencies: js-tokens: 4.0.0 + lower-case@2.0.2: + dependencies: + tslib: 2.8.1 + lru-cache@10.4.3: {} lru-cache@5.1.1: @@ -8913,6 +9104,11 @@ snapshots: transitivePeerDependencies: - supports-color + no-case@3.0.4: + dependencies: + lower-case: 2.0.2 + tslib: 2.8.1 + node-abort-controller@3.1.1: {} node-emoji@1.11.0: @@ -9084,6 +9280,8 @@ snapshots: picomatch@4.0.1: {} + picomatch@4.0.2: {} + pify@4.0.1: {} pirates@4.0.6: {} @@ -9500,6 +9698,11 @@ snapshots: smart-buffer@4.2.0: {} + snake-case@3.0.4: + dependencies: + dot-case: 3.0.4 + tslib: 2.8.1 + socket.io-adapter@2.5.5: dependencies: debug: 4.3.7 @@ -9717,6 +9920,8 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + svg-parser@2.0.4: {} + symbol-observable@4.0.0: {} synckit@0.9.2: @@ -9988,6 +10193,17 @@ snapshots: vary@1.1.2: {} + vite-plugin-svgr@4.3.0(rollup@4.24.3)(typescript@5.3.3)(vite@5.4.10(@types/node@20.17.6)(lightningcss@1.25.1)(terser@5.36.0)): + dependencies: + '@rollup/pluginutils': 5.1.3(rollup@4.24.3) + '@svgr/core': 8.1.0(typescript@5.3.3) + '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.3.3)) + vite: 5.4.10(@types/node@20.17.6)(lightningcss@1.25.1)(terser@5.36.0) + transitivePeerDependencies: + - rollup + - supports-color + - typescript + vite-tsconfig-paths@5.1.0(typescript@5.3.3)(vite@5.4.10(@types/node@20.17.6)(lightningcss@1.25.1)(terser@5.36.0)): dependencies: debug: 4.3.7