diff --git a/apps/web/package.json b/apps/web/package.json
index cf59cfc..95c48a3 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -14,13 +14,14 @@
"@repo/theme": "workspace:^",
"@repo/ui": "workspace:^",
"next": "14.2.21",
+ "overlay-kit": "^1.4.1",
"react": "^18",
"react-dom": "^18"
},
"devDependencies": {
"@repo/eslint-config": "workspace:*",
- "@repo/typescript-config": "workspace:*",
"@repo/theme": "workspace:*",
+ "@repo/typescript-config": "workspace:*",
"@repo/ui": "workspace:*",
"@types/node": "^20.11.24",
"@types/react": "18.3.0",
diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx
index 488ca85..5acbefe 100644
--- a/apps/web/src/app/layout.tsx
+++ b/apps/web/src/app/layout.tsx
@@ -3,7 +3,7 @@ import localFont from 'next/font/local';
import './globals.css';
import '@repo/theme/styles';
import '@repo/ui/styles';
-import { ThemeProvider } from '@repo/theme';
+import { Providers } from '../components/Providers/Providers';
const geistSans = localFont({
src: './fonts/GeistVF.woff',
@@ -29,8 +29,7 @@ export default function RootLayout({
return (
-
웹 1팀 파이팅!
+
+
hihi
diff --git a/apps/web/src/components/Providers/Providers.tsx b/apps/web/src/components/Providers/Providers.tsx
new file mode 100644
index 0000000..7bf654f
--- /dev/null
+++ b/apps/web/src/components/Providers/Providers.tsx
@@ -0,0 +1,17 @@
+'use client';
+
+import { ThemeProvider } from '@repo/theme';
+import { OverlayProvider } from 'overlay-kit';
+import { ReactNode } from 'react';
+
+type ProvidersProps = {
+ children: ReactNode;
+};
+
+export function Providers({ children }: ProvidersProps) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/packages/theme/src/themes/contract.ts b/packages/theme/src/themes/contract.ts
index c8167e1..15132ea 100644
--- a/packages/theme/src/themes/contract.ts
+++ b/packages/theme/src/themes/contract.ts
@@ -51,6 +51,12 @@ export type ThemeContract = {
blue200: string;
blue400: string;
blue800: string;
+
+ violet0: string;
+ violet100: string;
+ violet200: string;
+ violet400: string;
+ violet800: string;
};
space: {
[K in keyof typeof tokens.spacing]: string;
diff --git a/packages/theme/src/themes/dark.ts b/packages/theme/src/themes/dark.ts
index c95393e..9dcf642 100644
--- a/packages/theme/src/themes/dark.ts
+++ b/packages/theme/src/themes/dark.ts
@@ -55,6 +55,12 @@ export const darkTheme: ThemeContract = {
blue200: tokens.colors.blue200,
blue400: tokens.colors.blue400,
blue800: tokens.colors.blue800,
+
+ violet0: tokens.colors.violet0,
+ violet100: tokens.colors.violet100,
+ violet200: tokens.colors.violet200,
+ violet400: tokens.colors.violet400,
+ violet800: tokens.colors.violet800,
},
space: tokens.spacing,
borderRadius: tokens.radius,
diff --git a/packages/theme/src/themes/light.ts b/packages/theme/src/themes/light.ts
index ed4537d..7337ae3 100644
--- a/packages/theme/src/themes/light.ts
+++ b/packages/theme/src/themes/light.ts
@@ -55,6 +55,12 @@ export const lightTheme: ThemeContract = {
blue200: tokens.colors.blue200,
blue400: tokens.colors.blue400,
blue800: tokens.colors.blue800,
+
+ violet0: tokens.colors.violet0,
+ violet100: tokens.colors.violet100,
+ violet200: tokens.colors.violet200,
+ violet400: tokens.colors.violet400,
+ violet800: tokens.colors.violet800,
},
space: tokens.spacing,
borderRadius: tokens.radius,
diff --git a/packages/theme/src/tokens/colors.ts b/packages/theme/src/tokens/colors.ts
index a9e6ebe..280fe26 100644
--- a/packages/theme/src/tokens/colors.ts
+++ b/packages/theme/src/tokens/colors.ts
@@ -26,6 +26,12 @@ export const colors = {
blue400: '#7698E2',
blue800: '#153C66',
+ violet0: '#F2F3FF',
+ violet100: '#DFE1FE',
+ violet200: '#B7B4FF',
+ violet400: '#817ED5',
+ violet800: '#4A46A3',
+
grey0: '#FFFFFF',
grey25: '#F7F9FB',
grey50: '#EAEFF4',
diff --git a/packages/ui/esbuild.config.mjs b/packages/ui/esbuild.config.mjs
index 31e5e03..508cc3d 100644
--- a/packages/ui/esbuild.config.mjs
+++ b/packages/ui/esbuild.config.mjs
@@ -20,6 +20,7 @@ const buildOptions = {
}),
],
loader: { '.css': 'file' },
+ allowOverwrite: true,
outdir,
external: ['react'],
};
diff --git a/packages/ui/package.json b/packages/ui/package.json
index 492b468..ad8353c 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -21,8 +21,10 @@
},
"dependencies": {
"@repo/theme": "workspace:^",
+ "@types/react-dom": "18.3.1",
"@vanilla-extract/css": "^1.17.0",
"@vanilla-extract/recipes": "^0.5.5",
+ "motion": "^11.17.0",
"react": "^18"
},
"devDependencies": {
diff --git a/packages/ui/src/components/Toast/Toast.css.ts b/packages/ui/src/components/Toast/Toast.css.ts
new file mode 100644
index 0000000..aff1ee4
--- /dev/null
+++ b/packages/ui/src/components/Toast/Toast.css.ts
@@ -0,0 +1,24 @@
+import { style } from '@vanilla-extract/css';
+import { tokens } from '@repo/theme';
+
+export const container = style({
+ position: 'fixed',
+ bottom: 40,
+ right: 40,
+ padding: `${tokens.spacing[20]} ${tokens.spacing[32]}`,
+ borderRadius: 100,
+ backgroundColor: tokens.colors.grey700,
+ color: tokens.colors.grey0,
+});
+
+export const content = style({
+ display: 'flex',
+ alignItems: 'center',
+ gap: tokens.spacing[8],
+});
+
+export const message = style({
+ fontSize: tokens.typography.fontSize[20],
+ fontWeight: tokens.typography.fontWeight.semibold,
+ lineHeight: '24px',
+});
diff --git a/packages/ui/src/components/Toast/Toast.tsx b/packages/ui/src/components/Toast/Toast.tsx
new file mode 100644
index 0000000..ab5d776
--- /dev/null
+++ b/packages/ui/src/components/Toast/Toast.tsx
@@ -0,0 +1,141 @@
+import { motion, AnimatePresence, HTMLMotionProps } from 'motion/react';
+import {
+ ForwardRefExoticComponent,
+ ReactNode,
+ forwardRef,
+ useEffect,
+ KeyboardEvent,
+ useRef,
+} from 'react';
+import { ToastIcon } from './compounds/Icon/Icon';
+import * as styles from './Toast.css';
+import { useTimer } from './hooks/useTimer';
+import { mergeRefs } from '@/utils';
+
+export type ToastType = 'default' | 'success' | 'error';
+
+export type ToastProps = {
+ /**
+ * 토스트 타입
+ * @default 'default'
+ */
+ toastType?: ToastType;
+ /**
+ * 왼쪽 추가 요소 (아이콘 등)
+ */
+ leftAddon?: ReactNode;
+ /**
+ * 토스트 지속 시간
+ * @default 2000
+ */
+ duration?: number;
+ /**
+ * 자식 요소
+ */
+ children?: ReactNode;
+ /**
+ * 토스트 열기 여부
+ */
+ open: boolean;
+ /**
+ * 토스트가 열릴 때 호출되는 함수
+ */
+ onOpen?: VoidFunction;
+ /**
+ * 토스트가 닫힐 때 호출되는 함수
+ */
+ onClose?: VoidFunction;
+ /**
+ * 토스트가 완전히 닫힌 후 호출되는 함수
+ */
+ onExited?: VoidFunction;
+} & Omit
, 'children'>;
+
+const ToastComponent = forwardRef(
+ (
+ {
+ toastType = 'default',
+ leftAddon,
+ duration = 2000,
+ children,
+ open,
+ onOpen,
+ onClose,
+ onExited,
+ style: toastStyle,
+ ...restProps
+ },
+ ref
+ ) => {
+ const { startCurrentTimer, clearCurrentTimeout } = useTimer({
+ onTimerEnd: onClose,
+ timeoutSecond: duration,
+ });
+ const toastRef = useRef(null);
+
+ useEffect(() => {
+ if (open) {
+ onOpen?.();
+ startCurrentTimer();
+ toastRef.current?.focus();
+ }
+ }, [open, onOpen, startCurrentTimer]);
+
+ const handleKeyDown = (event: KeyboardEvent) => {
+ if (event.key === 'Escape') {
+ onClose?.();
+ }
+ };
+
+ return (
+
+ {open && (
+
+
+ {leftAddon ?? (
+
+ )}
+ {children}
+
+
+ )}
+
+ );
+ }
+);
+
+type ToastComposition = {
+ Icon: typeof ToastIcon;
+};
+
+export const Toast: ForwardRefExoticComponent & ToastComposition =
+ Object.assign(ToastComponent, {
+ Icon: ToastIcon,
+ });
+
+Toast.displayName = 'Toast';
diff --git a/packages/ui/src/components/Toast/compounds/Icon/Icon.tsx b/packages/ui/src/components/Toast/compounds/Icon/Icon.tsx
new file mode 100644
index 0000000..0d074b4
--- /dev/null
+++ b/packages/ui/src/components/Toast/compounds/Icon/Icon.tsx
@@ -0,0 +1,38 @@
+import { Icon } from '@repo/ui';
+import type { IconProps } from '@repo/ui';
+import { ToastType } from '../../Toast';
+
+export type ToastIconProps = Omit & {
+ toastType?: ToastType;
+};
+
+export function ToastIcon({
+ toastType = 'default',
+ ...restProps
+}: ToastIconProps) {
+ const iconName = (() => {
+ switch (toastType) {
+ case 'success':
+ return 'check';
+ case 'error':
+ return 'notice';
+ default:
+ return null;
+ }
+ })();
+
+ if (!iconName) {
+ return null;
+ }
+
+ const iconColor = (() => {
+ switch (toastType) {
+ case 'success':
+ return 'violet200';
+ case 'error':
+ return 'warning300';
+ }
+ })();
+
+ return ;
+}
diff --git a/packages/ui/src/components/Toast/hooks/useTimer.ts b/packages/ui/src/components/Toast/hooks/useTimer.ts
new file mode 100644
index 0000000..0499995
--- /dev/null
+++ b/packages/ui/src/components/Toast/hooks/useTimer.ts
@@ -0,0 +1,42 @@
+import { useRef, useCallback, useEffect } from 'react';
+
+type UseTimerParameters = {
+ onTimerEnd?: () => void;
+ timeoutSecond?: number;
+};
+
+export function useTimer({
+ onTimerEnd,
+ timeoutSecond = 3000,
+}: UseTimerParameters) {
+ const timerRef = useRef>();
+
+ const startCurrentTimer = useCallback(() => {
+ if (!onTimerEnd) {
+ return;
+ }
+
+ timerRef.current = setTimeout(() => {
+ onTimerEnd();
+ }, timeoutSecond);
+ }, [timeoutSecond, onTimerEnd]);
+
+ const clearCurrentTimeout = useCallback(() => {
+ if (timerRef.current) {
+ clearTimeout(timerRef.current);
+ }
+ }, []);
+
+ useEffect(() => {
+ return () => {
+ if (timerRef.current) {
+ clearTimeout(timerRef.current);
+ }
+ };
+ }, [timerRef]);
+
+ return {
+ startCurrentTimer,
+ clearCurrentTimeout,
+ };
+}
diff --git a/packages/ui/src/components/Toast/index.ts b/packages/ui/src/components/Toast/index.ts
new file mode 100644
index 0000000..7b412d7
--- /dev/null
+++ b/packages/ui/src/components/Toast/index.ts
@@ -0,0 +1,4 @@
+export { Toast } from './Toast';
+export type { ToastProps, ToastType } from './Toast';
+export { ToastIcon } from './compounds/Icon/Icon';
+export type { ToastIconProps } from './compounds/Icon/Icon';
diff --git a/packages/ui/src/components/index.ts b/packages/ui/src/components/index.ts
index dc4ef55..00bc8ba 100644
--- a/packages/ui/src/components/index.ts
+++ b/packages/ui/src/components/index.ts
@@ -2,5 +2,7 @@ export { Spacing } from './Spacing/Spacing';
export type { SpacingDirection, SpacingProps } from './Spacing/Spacing';
export { Icon } from './Icon/Icon';
export type { IconName, IconProps } from './Icon/Icon';
+export { Toast } from './Toast';
+export type { ToastProps, ToastType, ToastIconProps } from './Toast';
export { Text } from './Text/Text.subComponents';
export type { AllowedTags, TextProps } from './Text/Text';
diff --git a/packages/ui/src/utils/index.ts b/packages/ui/src/utils/index.ts
new file mode 100644
index 0000000..7d5fa86
--- /dev/null
+++ b/packages/ui/src/utils/index.ts
@@ -0,0 +1 @@
+export { mergeRefs } from '@/utils/mergeRefs';
diff --git a/packages/ui/src/utils/mergeRefs.ts b/packages/ui/src/utils/mergeRefs.ts
new file mode 100644
index 0000000..ffd63cc
--- /dev/null
+++ b/packages/ui/src/utils/mergeRefs.ts
@@ -0,0 +1,22 @@
+import type { MutableRefObject, LegacyRef, ForwardedRef, Ref } from 'react';
+
+export function mergeRefs(
+ ...refs: Array<
+ | MutableRefObject
+ | LegacyRef
+ | ForwardedRef
+ | Ref
+ | undefined
+ | null
+ >
+): Ref {
+ return (value) => {
+ refs.forEach((ref) => {
+ if (typeof ref === 'function') {
+ ref(value);
+ } else if (ref != null) {
+ (ref as MutableRefObject).current = value;
+ }
+ });
+ };
+}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 4020780..47ac5d0 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -63,6 +63,9 @@ importers:
next:
specifier: 14.2.21
version: 14.2.21(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ overlay-kit:
+ specifier: ^1.4.1
+ version: 1.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react:
specifier: ^18
version: 18.3.1
@@ -87,7 +90,7 @@ importers:
version: 18.3.1
'@vanilla-extract/next-plugin':
specifier: ^2.4.8
- version: 2.4.8(@types/node@20.17.6)(next@14.2.21(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.37.0)(webpack@5.97.1)
+ version: 2.4.8(@types/node@20.17.6)(next@14.2.21(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(webpack@5.97.1)
eslint-config-next:
specifier: 14.2.21
version: 14.2.21(eslint@9.17.0)(typescript@5.5.4)
@@ -169,12 +172,18 @@ importers:
'@repo/theme':
specifier: workspace:^
version: link:../theme
+ '@types/react-dom':
+ specifier: 18.3.1
+ version: 18.3.1
'@vanilla-extract/css':
specifier: ^1.17.0
version: 1.17.0
'@vanilla-extract/recipes':
specifier: ^0.5.5
version: 0.5.5(@vanilla-extract/css@1.17.0)
+ motion:
+ specifier: ^11.17.0
+ version: 11.17.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react:
specifier: ^18
version: 18.3.1
@@ -982,6 +991,7 @@ packages:
acorn@8.14.0:
resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==}
engines: {node: '>=0.4.0'}
+ hasBin: true
ajv-formats@2.1.1:
resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
@@ -1594,6 +1604,20 @@ packages:
resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==}
engines: {node: '>=14'}
+ framer-motion@11.17.0:
+ resolution: {integrity: sha512-uTNLH9JPMD3ad14WBt3KYRTR+If4tGPLgKTKTIIPaEBMkvazs6EkWNcmCh65qA/tyinOqIbQiuCorXX0qQsNoQ==}
+ peerDependencies:
+ '@emotion/is-prop-valid': '*'
+ react: ^18.0.0 || ^19.0.0
+ react-dom: ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@emotion/is-prop-valid':
+ optional: true
+ react:
+ optional: true
+ react-dom:
+ optional: true
+
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@@ -1869,6 +1893,7 @@ packages:
js-yaml@4.1.0:
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
+ hasBin: true
jsesc@3.1.0:
resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==}
@@ -1954,6 +1979,7 @@ packages:
loose-envify@1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
lower-case@2.0.2:
resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
@@ -2017,6 +2043,26 @@ packages:
modern-ahocorasick@1.1.0:
resolution: {integrity: sha512-sEKPVl2rM+MNVkGQt3ChdmD8YsigmXdn5NifZn6jiwn9LRJpWm8F3guhaqrJT/JOat6pwpbXEk6kv+b9DMIjsQ==}
+ motion-dom@11.16.4:
+ resolution: {integrity: sha512-2wuCie206pCiP2K23uvwJeci4pMFfyQKpWI0Vy6HrCTDzDCer4TsYtT7IVnuGbDeoIV37UuZiUr6SZMHEc1Vww==}
+
+ motion-utils@11.16.0:
+ resolution: {integrity: sha512-ngdWPjg31rD4WGXFi0eZ00DQQqKKu04QExyv/ymlC+3k+WIgYVFbt6gS5JsFPbJODTF/r8XiE/X+SsoT9c0ocw==}
+
+ motion@11.17.0:
+ resolution: {integrity: sha512-mWZhIOWH2slNXPUWhr6cEu98bl9NMX7u9r7vdNI+Bm3/jrOEa3e44GmyUuwXr9hWR+rWII27YTnKb6CDD1vU2g==}
+ peerDependencies:
+ '@emotion/is-prop-valid': '*'
+ react: ^18.0.0 || ^19.0.0
+ react-dom: ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@emotion/is-prop-valid':
+ optional: true
+ react:
+ optional: true
+ react-dom:
+ optional: true
+
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
@@ -2103,6 +2149,12 @@ packages:
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
engines: {node: '>= 0.8.0'}
+ overlay-kit@1.4.1:
+ resolution: {integrity: sha512-BSzpilw1pM1j6/r04Qwc/FHnWe0Hio0qbhdepJuihx352q+n/FPUAr297MqjKanniH722VDPxFdq7JFjErIXdQ==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0
+ react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
+
p-limit@3.1.0:
resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
engines: {node: '>=10'}
@@ -2179,6 +2231,7 @@ packages:
prettier@3.3.3:
resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==}
engines: {node: '>=14'}
+ hasBin: true
prop-types@15.8.1:
resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==}
@@ -2232,9 +2285,11 @@ packages:
resolve@1.22.8:
resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
+ hasBin: true
resolve@2.0.0-next.5:
resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==}
+ hasBin: true
restore-cursor@5.1.0:
resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==}
@@ -2279,10 +2334,12 @@ packages:
semver@6.3.1:
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+ hasBin: true
semver@7.6.3:
resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==}
engines: {node: '>=10'}
+ hasBin: true
serialize-javascript@6.0.2:
resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==}
@@ -2568,6 +2625,11 @@ packages:
uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+ use-sync-external-store@1.4.0:
+ resolution: {integrity: sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
v8-compile-cache-lib@3.0.1:
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
@@ -2643,6 +2705,7 @@ packages:
which@2.0.2:
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
engines: {node: '>= 8'}
+ hasBin: true
word-wrap@1.2.5:
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
@@ -3359,6 +3422,32 @@ snapshots:
- supports-color
- terser
+ '@vanilla-extract/integration@7.1.12(@types/node@20.17.6)':
+ dependencies:
+ '@babel/core': 7.26.0
+ '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.0)
+ '@vanilla-extract/babel-plugin-debug-ids': 1.2.0
+ '@vanilla-extract/css': 1.17.0
+ dedent: 1.5.3
+ esbuild: 0.21.5
+ eval: 0.1.8
+ find-up: 5.0.0
+ javascript-stringify: 2.1.0
+ mlly: 1.7.3
+ vite: 5.4.11(@types/node@20.17.6)(terser@5.37.0)
+ vite-node: 1.6.0(@types/node@20.17.6)(terser@5.37.0)
+ transitivePeerDependencies:
+ - '@types/node'
+ - babel-plugin-macros
+ - less
+ - lightningcss
+ - sass
+ - sass-embedded
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+
'@vanilla-extract/integration@7.1.12(@types/node@20.17.6)(terser@5.37.0)':
dependencies:
'@babel/core': 7.26.0
@@ -3402,9 +3491,9 @@ snapshots:
- terser
- webpack
- '@vanilla-extract/next-plugin@2.4.8(@types/node@20.17.6)(next@14.2.21(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(terser@5.37.0)(webpack@5.97.1)':
+ '@vanilla-extract/next-plugin@2.4.8(@types/node@20.17.6)(next@14.2.21(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(webpack@5.97.1)':
dependencies:
- '@vanilla-extract/webpack-plugin': 2.3.16(@types/node@20.17.6)(terser@5.37.0)(webpack@5.97.1)
+ '@vanilla-extract/webpack-plugin': 2.3.16(@types/node@20.17.6)(webpack@5.97.1)
next: 14.2.21(@babel/core@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
transitivePeerDependencies:
- '@types/node'
@@ -3448,9 +3537,9 @@ snapshots:
- supports-color
- terser
- '@vanilla-extract/webpack-plugin@2.3.16(@types/node@20.17.6)(terser@5.37.0)(webpack@5.97.1)':
+ '@vanilla-extract/webpack-plugin@2.3.16(@types/node@20.17.6)(webpack@5.97.1)':
dependencies:
- '@vanilla-extract/integration': 7.1.12(@types/node@20.17.6)(terser@5.37.0)
+ '@vanilla-extract/integration': 7.1.12(@types/node@20.17.6)
debug: 4.4.0
loader-utils: 2.0.4
picocolors: 1.1.1
@@ -4064,7 +4153,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.12.0(@typescript-eslint/parser@8.15.0(eslint@9.17.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@9.17.0))(eslint@9.17.0):
+ eslint-module-utils@2.12.0(@typescript-eslint/parser@8.15.0(eslint@9.17.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@9.17.0):
dependencies:
debug: 3.2.7
optionalDependencies:
@@ -4086,7 +4175,7 @@ snapshots:
doctrine: 2.1.0
eslint: 9.17.0
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.15.0(eslint@9.17.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0(eslint-plugin-import@2.31.0)(eslint@9.17.0))(eslint@9.17.0)
+ eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.15.0(eslint@9.17.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.7.0)(eslint@9.17.0)
hasown: 2.0.2
is-core-module: 2.15.1
is-glob: 4.0.3
@@ -4311,6 +4400,15 @@ snapshots:
cross-spawn: 7.0.6
signal-exit: 4.1.0
+ framer-motion@11.17.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ motion-dom: 11.16.4
+ motion-utils: 11.16.0
+ tslib: 2.8.1
+ optionalDependencies:
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+
fsevents@2.3.3:
optional: true
@@ -4713,6 +4811,20 @@ snapshots:
modern-ahocorasick@1.1.0: {}
+ motion-dom@11.16.4:
+ dependencies:
+ motion-utils: 11.16.0
+
+ motion-utils@11.16.0: {}
+
+ motion@11.17.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ framer-motion: 11.17.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ tslib: 2.8.1
+ optionalDependencies:
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+
ms@2.1.3: {}
nanoid@3.3.7: {}
@@ -4812,6 +4924,12 @@ snapshots:
type-check: 0.4.0
word-wrap: 1.2.5
+ overlay-kit@1.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ use-sync-external-store: 1.4.0(react@18.3.1)
+
p-limit@3.1.0:
dependencies:
yocto-queue: 0.1.0
@@ -5340,6 +5458,10 @@ snapshots:
dependencies:
punycode: 2.3.1
+ use-sync-external-store@1.4.0(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+
v8-compile-cache-lib@3.0.1: {}
vite-node@1.6.0(@types/node@20.17.12)(terser@5.37.0):