diff --git a/.eslintrc.json b/.eslintrc.json
deleted file mode 100644
index bffb357a7..000000000
--- a/.eslintrc.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "extends": "next/core-web-vitals"
-}
diff --git a/.gitignore b/.gitignore
index 8f322f0d8..5ef6a5207 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,7 +3,12 @@
# dependencies
/node_modules
/.pnp
-.pnp.js
+.pnp.*
+.yarn/*
+!.yarn/patches
+!.yarn/plugins
+!.yarn/releases
+!.yarn/versions
# testing
/coverage
@@ -23,9 +28,10 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*
+.pnpm-debug.log*
-# local env files
-.env*.local
+# env files (can opt-in for committing if needed)
+.env*
# vercel
.vercel
diff --git a/README.md b/README.md
index a75ac5248..38a37188f 100644
--- a/README.md
+++ b/README.md
@@ -1,40 +1,80 @@
-This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
+# Sprint Mission
-## Getting Started
+코드잇 스프린트 미션
-First, run the development server:
+## 배포 URL
-```bash
-npm run dev
-# or
-yarn dev
-# or
-pnpm dev
-# or
-bun dev
-```
+[판다마켓 : sprint-mission-chanki-next.vercel.app/](https://sprint-mission-chanki-next.vercel.app/)
-Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+### 과제 진행중 메모
-You can start editing the page by modifying `pages/index.tsx`. The page auto-updates as you edit the file.
+#### fetch abort option 사용 케이스
-[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.ts`.
+state 관리하고 있는 params과 usePageSize로 관리하는 pageSize의 변화가 일어날때마다, 데이터를 가져오기 위해서 통신을 하는데, 최대 페이지를 넘긴 케이스에 페이지 번호를 최대 페이지로 다시 보정하는 과정중에 이전 요청건의 응답 결과로 한번씩 데이터가 바뀌는 현상이 있었습니다.
-The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages.
+위 현상을 해결하기 위해서 다음 두 가지 방법을 생각했습니다.
-This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
+1. 페이지 번호를 보정하고 나서 통신을 하도록 코드수정
+2. abortController를 이용하여 다음 통신을 할때는 이전 통신을 취소하고 하도록 코드 수정
-## Learn More
+1번을 위해서는 useList(데이터 통신 훅), usePageSize(반응형 사이즈) 두 훅 안에서 보정 처리를 하면 되긴 하는데, 서로 각자의 할 일 만 할 수 있도록 만들어 주고 싶었습니다.
-To learn more about Next.js, take a look at the following resources:
+- useList에서 데이터를 불러오는 콜백함수는 params state (page번호, 검색키워드, orderBy를 관리) 또는 pageSize가 변경될시 재요청하도록 useEffect에 해당 값들을 의존성으로 관리하고 있습니다.
+- useList에서 보정을 하려면, pagination 훅에서 관리하는 값을 가져와야했고,
+- usePageSize에서 보정을 하려면 List컴포넌트에서 관리하고 있는 params state의 정보와 관리하는 함수들을 가져와야했습니다.
+- 최종적으로 내린 결론은, 통신쪽을 수정하여 이전 요청을 취소하고 통신을 하는 방향으로 수정을 했습니다.
-- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
-- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
+#### useList vs useFetch vs useAsync
-You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
+데이터를 받는 훅을 만들때, 처음에는 리스트에 특화된 훅을 만드려고 했는데 다른곳에서는 재사용하기 힘들어서
+범용적인 데이터를 받는 훅을 만드는게 좋을것 같아서 고민을 했습니다.
-## Deploy on Vercel
+1. 첫번째 시도(기존코드) (리스트형 데이터 패칭에 특화된 useList)
-The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
+- 장점
-Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
+ - useList를 호출할때 넣어야되는 필요로하는 인자가 정해져 있어서 편리(눈에 잘보임)
+ - params 객체를 넘겨받아도 인자가 정해져있으니 구조분해하여 useEffect의 의존성배열에 넣기 수월
+
+- 단점
+ - 하지만 모든 요청에 동일한 인자를 보내는건 아니므로 범용성이 떨어져보임
+ - 좀더 일반적인 함수로 바꿔보려고 두번째 시도인 useFetch를 생각
+
+2. 두번째 시도 (데이터요청함수를 실행만 하고 그 함수에 보낼 인자들을 넘겨주기만 하는 useFetch)
+
+- 장점
+ - 훅 자체는 요청함수, 인자들에대해 모르고 있어도 되어서 범용성이 좋은것 같음
+- 단점
+ - 그대신 넘어가는 인자들을 객체로 보내는데 useMemo로 참조를 보정해줘야함(어떤게 올지 몰라서, 구조분해로 분리못함)
+ - 그리고 무슨 인자로 요청하는지는 파악이 안됨 (사용하는 입장에서)
+
+3. 세번째 시도 (둘다 이용해볼까?)
+
+- useList가 useFetch를 이용하면 안될까? 필요한곳에서 useFetch를 재사용도 가능짐
+- useList가 받은 객체를 메모지이에션해서 useFetch로 넘겨주는 방식으로 작업했습니다.
+- 효과 : useList에서 받아야하는 인자값을 나타낼수 있고, useFetch를 useList 뿐만 아니라 다른곳에서도 사용 가능
+
+4. 네번째 마지막 시도 ㅜㅜ(useFetch와 useAsync를 쓰는 방법, 차이점)
+
+- 생각해보니 useFetch는 '주소'를 받아서 fetch처리하는 훅으로 사용되어야할 것 같음 (구글링의 예제 코드들을 분석해봄)
+- url주소 기반으로 처리하는 useFetch를 쓰게되면, 만약에 api url이 변경되거나 요청전 작업이 수정되면 수정하러 이곳저곳을 돌아다녀야 할 것 같음.
+- 비동기 요청함수를 받아서 처리하는 훅으로 만들어둔 useAsync를 쓰는게 더 적합해보임
+- 주소를 기반으로 fetch만을 처리하는 훅으로 useFetch를 수정하고 남겨두기로 결정
+
+#### axios와 abortcontroller 사용기
+
+- fetch와 axios는 abort될시에 error name이 다르다.
+- 기존 fetch에서는 'AbortError'로 예외처리를 했는데, axios에서는 'CanceledError'로 예외처리를 해야했음.
+
+#### react router의 loader를 사용할시 추가로 설정해줘야했던 설정들
+
+- React의 Suspense와 fallback, React router의 loader, hydrateFallback을 조사해보고 정리해보았습니다.
+- https://heavy-bear.tistory.com/13
+
+#### react hook form을 적용하면서 알게된 점
+
+- Controlled 필드를 사용할때는 defaultValue 설정을 꼭 해주어야한다. (초기값이 제대로 안잡히면 벨리데이션이 안됨)
+- useForm의 모드를 'onBlur'로 설정할때에는 필드에 전달된 props중 onBlur가 실행이 되어야 벨리데이션이 된다.
+- 직접 값을 업데이트해줄때는 (특수한 필드의 경우), useForm의 반환값중 setValue를 이용하면 값 업데이트와 벨리데이션이 작동한다.
+- react hook form에 컴포넌트를 연결할때에는 한겹의 어뎁터 레이어를 설정하여 컴포넌트 내부에서 react hook form의 의존성이 없도록 작성하는 방법을 사용하자.
+- watch를 통해 각 필드에 value값을 전달하면 하나의 필드가 업데이트 될때마다 전체가 리랜더링이 되어버린다. (Controller, useController 등을 통해서 전달해야함)
diff --git a/eslint.config.mjs b/eslint.config.mjs
new file mode 100644
index 000000000..6b1f95044
--- /dev/null
+++ b/eslint.config.mjs
@@ -0,0 +1,28 @@
+import { dirname } from "path";
+import { fileURLToPath } from "url";
+import { FlatCompat } from "@eslint/eslintrc";
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = dirname(__filename);
+
+const compat = new FlatCompat({
+ baseDirectory: __dirname,
+});
+
+const eslintConfig = [
+ ...compat.extends("next/core-web-vitals", "next/typescript"),
+ {
+ rules: {
+ "@typescript-eslint/no-unused-vars": [
+ "error",
+ {
+ varsIgnorePattern: "^_",
+ argsIgnorePattern: "^_",
+ destructuredArrayIgnorePattern: "^_",
+ },
+ ],
+ },
+ },
+];
+
+export default eslintConfig;
diff --git a/next.config.js b/next.config.js
deleted file mode 100644
index a843cbee0..000000000
--- a/next.config.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/** @type {import('next').NextConfig} */
-const nextConfig = {
- reactStrictMode: true,
-}
-
-module.exports = nextConfig
diff --git a/next.config.ts b/next.config.ts
new file mode 100644
index 000000000..671d2d67d
--- /dev/null
+++ b/next.config.ts
@@ -0,0 +1,19 @@
+import type { NextConfig } from "next";
+
+const nextConfig: NextConfig = {
+ /* config options here */
+ images: {
+ remotePatterns: [
+ {
+ protocol: "http",
+ hostname: "**",
+ },
+ {
+ protocol: "https",
+ hostname: "**",
+ },
+ ],
+ },
+};
+
+export default nextConfig;
diff --git a/package-lock.json b/package-lock.json
index baa2b6655..71f303537 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,81 +1,159 @@
{
- "name": "fe-weekly-mission",
+ "name": "next",
"version": "0.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
- "name": "fe-weekly-mission",
+ "name": "next",
"version": "0.1.0",
"dependencies": {
- "next": "13.5.6",
- "react": "^18",
- "react-dom": "^18"
+ "@hookform/resolvers": "^3.9.1",
+ "axios": "^1.7.8",
+ "clsx": "^2.1.1",
+ "dayjs": "^1.11.13",
+ "jwt-decode": "^4.0.0",
+ "lodash": "^4.17.21",
+ "next": "15.1.3",
+ "next-auth": "^5.0.0-beta.25",
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0",
+ "react-hook-form": "^7.54.2",
+ "zod": "^3.24.1"
},
"devDependencies": {
+ "@eslint/eslintrc": "^3",
"@types/node": "^20",
- "@types/react": "^18",
- "@types/react-dom": "^18",
- "eslint": "^8",
- "eslint-config-next": "13.5.6",
+ "@types/react": "^19",
+ "@types/react-dom": "^19",
+ "eslint": "^9",
+ "eslint-config-next": "15.1.3",
+ "sass": "^1.83.1",
"typescript": "^5"
}
},
- "node_modules/@aashutoshrathi/word-wrap": {
- "version": "1.2.6",
- "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
- "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
+ "node_modules/@auth/core": {
+ "version": "0.37.2",
+ "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.37.2.tgz",
+ "integrity": "sha512-kUvzyvkcd6h1vpeMAojK2y7+PAV5H+0Cc9+ZlKYDFhDY31AlvsB+GW5vNO4qE3Y07KeQgvNO9U0QUx/fN62kBw==",
+ "license": "ISC",
+ "dependencies": {
+ "@panva/hkdf": "^1.2.1",
+ "@types/cookie": "0.6.0",
+ "cookie": "0.7.1",
+ "jose": "^5.9.3",
+ "oauth4webapi": "^3.0.0",
+ "preact": "10.11.3",
+ "preact-render-to-string": "5.2.3"
+ },
+ "peerDependencies": {
+ "@simplewebauthn/browser": "^9.0.1",
+ "@simplewebauthn/server": "^9.0.2",
+ "nodemailer": "^6.8.0"
+ },
+ "peerDependenciesMeta": {
+ "@simplewebauthn/browser": {
+ "optional": true
+ },
+ "@simplewebauthn/server": {
+ "optional": true
+ },
+ "nodemailer": {
+ "optional": true
+ }
}
},
- "node_modules/@babel/runtime": {
- "version": "7.23.4",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.4.tgz",
- "integrity": "sha512-2Yv65nlWnWlSpe3fXEyX5i7fx5kIKo4Qbcj+hMO0odwaneFjfXw5fdum+4yL20O0QiaHpia0cYQ9xpNMqrBwHg==",
- "dev": true,
+ "node_modules/@emnapi/runtime": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz",
+ "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==",
+ "license": "MIT",
+ "optional": true,
"dependencies": {
- "regenerator-runtime": "^0.14.0"
- },
- "engines": {
- "node": ">=6.9.0"
+ "tslib": "^2.4.0"
}
},
"node_modules/@eslint-community/eslint-utils": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
- "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz",
+ "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "eslint-visitor-keys": "^3.3.0"
+ "eslint-visitor-keys": "^3.4.3"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
"peerDependencies": {
"eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
}
},
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
"node_modules/@eslint-community/regexpp": {
- "version": "4.10.0",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
- "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
+ "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
}
},
+ "node_modules/@eslint/config-array": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz",
+ "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.5",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.2"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.1.tgz",
+ "integrity": "sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
"node_modules/@eslint/eslintrc": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz",
- "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.2.0.tgz",
+ "integrity": "sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ajv": "^6.12.4",
"debug": "^4.3.2",
- "espree": "^9.6.0",
- "globals": "^13.19.0",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
"ignore": "^5.2.0",
"import-fresh": "^3.2.1",
"js-yaml": "^4.1.0",
@@ -83,33 +161,90 @@
"strip-json-comments": "^3.1.1"
},
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/@eslint/js": {
- "version": "8.54.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz",
- "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==",
+ "version": "9.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.17.0.tgz",
+ "integrity": "sha512-Sxc4hqcs1kTu0iID3kcZDW3JHq2a77HO9P8CP6YEA/FpH3Ll8UXE2r/86Rz9YJLKme39S9vU5OWNjC6Xl0Cr3w==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz",
+ "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.2.4",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz",
+ "integrity": "sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@hookform/resolvers": {
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.9.1.tgz",
+ "integrity": "sha512-ud2HqmGBM0P0IABqoskKWI6PEf6ZDDBZkFqe2Vnl+mTHCEHzr3ISjjZyCwTjC/qpL25JC9aIDkloQejvMeq0ug==",
+ "license": "MIT",
+ "peerDependencies": {
+ "react-hook-form": "^7.0.0"
+ }
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
}
},
- "node_modules/@humanwhocodes/config-array": {
- "version": "0.11.13",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
- "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==",
+ "node_modules/@humanfs/node": {
+ "version": "0.16.6",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz",
+ "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "@humanwhocodes/object-schema": "^2.0.1",
- "debug": "^4.1.1",
- "minimatch": "^3.0.5"
+ "@humanfs/core": "^0.19.1",
+ "@humanwhocodes/retry": "^0.3.0"
},
"engines": {
- "node": ">=10.10.0"
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
+ "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
}
},
"node_modules/@humanwhocodes/module-importer": {
@@ -117,6 +252,7 @@
"resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
"integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
"dev": true,
+ "license": "Apache-2.0",
"engines": {
"node": ">=12.22"
},
@@ -125,309 +261,1097 @@
"url": "https://github.com/sponsors/nzakas"
}
},
- "node_modules/@humanwhocodes/object-schema": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz",
- "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
- "dev": true
- },
- "node_modules/@next/env": {
- "version": "13.5.6",
- "resolved": "https://registry.npmjs.org/@next/env/-/env-13.5.6.tgz",
- "integrity": "sha512-Yac/bV5sBGkkEXmAX5FWPS9Mmo2rthrOPRQQNfycJPkjUAUclomCPH7QFVCDQ4Mp2k2K1SSM6m0zrxYrOwtFQw=="
- },
- "node_modules/@next/eslint-plugin-next": {
- "version": "13.5.6",
- "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.5.6.tgz",
- "integrity": "sha512-ng7pU/DDsxPgT6ZPvuprxrkeew3XaRf4LAT4FabaEO/hAbvVx4P7wqnqdbTdDn1kgTvsI4tpIgT4Awn/m0bGbg==",
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz",
+ "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==",
"dev": true,
- "dependencies": {
- "glob": "7.1.7"
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
}
},
- "node_modules/@next/swc-darwin-arm64": {
- "version": "13.5.6",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.5.6.tgz",
- "integrity": "sha512-5nvXMzKtZfvcu4BhtV0KH1oGv4XEW+B+jOfmBdpFI3C7FrB/MfujRpWYSBBO64+qbW8pkZiSyQv9eiwnn5VIQA==",
+ "node_modules/@img/sharp-darwin-arm64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz",
+ "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==",
"cpu": [
"arm64"
],
+ "license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
- "node": ">= 10"
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-arm64": "1.0.4"
}
},
- "node_modules/@next/swc-darwin-x64": {
- "version": "13.5.6",
- "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-13.5.6.tgz",
- "integrity": "sha512-6cgBfxg98oOCSr4BckWjLLgiVwlL3vlLj8hXg2b+nDgm4bC/qVXXLfpLB9FHdoDu4057hzywbxKvmYGmi7yUzA==",
+ "node_modules/@img/sharp-darwin-x64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz",
+ "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==",
"cpu": [
"x64"
],
+ "license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
- "node": ">= 10"
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-x64": "1.0.4"
}
},
- "node_modules/@next/swc-linux-arm64-gnu": {
- "version": "13.5.6",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.5.6.tgz",
- "integrity": "sha512-txagBbj1e1w47YQjcKgSU4rRVQ7uF29YpnlHV5xuVUsgCUf2FmyfJ3CPjZUvpIeXCJAoMCFAoGnbtX86BK7+sg==",
+ "node_modules/@img/sharp-libvips-darwin-arm64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz",
+ "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-x64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz",
+ "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz",
+ "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz",
+ "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-s390x": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz",
+ "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-x64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz",
+ "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz",
+ "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==",
"cpu": [
"arm64"
],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-x64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz",
+ "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz",
+ "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==",
+ "cpu": [
+ "arm"
+ ],
+ "license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
- "node": ">= 10"
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm": "1.0.5"
}
},
- "node_modules/@next/swc-linux-arm64-musl": {
- "version": "13.5.6",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.5.6.tgz",
- "integrity": "sha512-cGd+H8amifT86ZldVJtAKDxUqeFyLWW+v2NlBULnLAdWsiuuN8TuhVBt8ZNpCqcAuoruoSWynvMWixTFcroq+Q==",
+ "node_modules/@img/sharp-linux-arm64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz",
+ "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==",
"cpu": [
"arm64"
],
+ "license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
- "node": ">= 10"
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-s390x": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz",
+ "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==",
+ "cpu": [
+ "s390x"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-s390x": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-x64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz",
+ "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-x64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-arm64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz",
+ "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-arm64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-x64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz",
+ "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-x64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-wasm32": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz",
+ "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==",
+ "cpu": [
+ "wasm32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT",
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.2.0"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-ia32": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz",
+ "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-x64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz",
+ "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "Apache-2.0 AND LGPL-3.0-or-later",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@next/env": {
+ "version": "15.1.3",
+ "resolved": "https://registry.npmjs.org/@next/env/-/env-15.1.3.tgz",
+ "integrity": "sha512-Q1tXwQCGWyA3ehMph3VO+E6xFPHDKdHFYosadt0F78EObYxPio0S09H9UGYznDe6Wc8eLKLG89GqcFJJDiK5xw==",
+ "license": "MIT"
+ },
+ "node_modules/@next/eslint-plugin-next": {
+ "version": "15.1.3",
+ "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.1.3.tgz",
+ "integrity": "sha512-oeP1vnc5Cq9UoOb8SYHAEPbCXMzOgG70l+Zfd+Ie00R25FOm+CCVNrcIubJvB1tvBgakXE37MmqSycksXVPRqg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-glob": "3.3.1"
+ }
+ },
+ "node_modules/@next/swc-darwin-arm64": {
+ "version": "15.1.3",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.1.3.tgz",
+ "integrity": "sha512-aZtmIh8jU89DZahXQt1La0f2EMPt/i7W+rG1sLtYJERsP7GRnNFghsciFpQcKHcGh4dUiyTB5C1X3Dde/Gw8gg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-darwin-x64": {
+ "version": "15.1.3",
+ "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.1.3.tgz",
+ "integrity": "sha512-aw8901rjkVBK5mbq5oV32IqkJg+CQa6aULNlN8zyCWSsePzEG3kpDkAFkkTOh3eJ0p95KbkLyWBzslQKamXsLA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-gnu": {
+ "version": "15.1.3",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.1.3.tgz",
+ "integrity": "sha512-YbdaYjyHa4fPK4GR4k2XgXV0p8vbU1SZh7vv6El4bl9N+ZSiMfbmqCuCuNU1Z4ebJMumafaz6UCC2zaJCsdzjw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-arm64-musl": {
+ "version": "15.1.3",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.1.3.tgz",
+ "integrity": "sha512-qgH/aRj2xcr4BouwKG3XdqNu33SDadqbkqB6KaZZkozar857upxKakbRllpqZgWl/NDeSCBYPmUAZPBHZpbA0w==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-gnu": {
+ "version": "15.1.3",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.1.3.tgz",
+ "integrity": "sha512-uzafnTFwZCPN499fNVnS2xFME8WLC9y7PLRs/yqz5lz1X/ySoxfaK2Hbz74zYUdEg+iDZPd8KlsWaw9HKkLEVw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-linux-x64-musl": {
+ "version": "15.1.3",
+ "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.1.3.tgz",
+ "integrity": "sha512-el6GUFi4SiDYnMTTlJJFMU+GHvw0UIFnffP1qhurrN1qJV3BqaSRUjkDUgVV44T6zpw1Lc6u+yn0puDKHs+Sbw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-arm64-msvc": {
+ "version": "15.1.3",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.1.3.tgz",
+ "integrity": "sha512-6RxKjvnvVMM89giYGI1qye9ODsBQpHSHVo8vqA8xGhmRPZHDQUE4jcDbhBwK0GnFMqBnu+XMg3nYukNkmLOLWw==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@next/swc-win32-x64-msvc": {
+ "version": "15.1.3",
+ "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.1.3.tgz",
+ "integrity": "sha512-VId/f5blObG7IodwC5Grf+aYP0O8Saz1/aeU3YcWqNdIUAmFQY3VEPKPaIzfv32F/clvanOb2K2BR5DtDs6XyQ==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nolyfill/is-core-module": {
+ "version": "1.0.39",
+ "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz",
+ "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.4.0"
+ }
+ },
+ "node_modules/@panva/hkdf": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz",
+ "integrity": "sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
+ }
+ },
+ "node_modules/@parcel/watcher": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.0.tgz",
+ "integrity": "sha512-i0GV1yJnm2n3Yq1qw6QrUrd/LI9bE8WEBOTtOkpCXHHdyN3TAGgqAK/DAT05z4fq2x04cARXt2pDmjWjL92iTQ==",
+ "dev": true,
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "detect-libc": "^1.0.3",
+ "is-glob": "^4.0.3",
+ "micromatch": "^4.0.5",
+ "node-addon-api": "^7.0.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "@parcel/watcher-android-arm64": "2.5.0",
+ "@parcel/watcher-darwin-arm64": "2.5.0",
+ "@parcel/watcher-darwin-x64": "2.5.0",
+ "@parcel/watcher-freebsd-x64": "2.5.0",
+ "@parcel/watcher-linux-arm-glibc": "2.5.0",
+ "@parcel/watcher-linux-arm-musl": "2.5.0",
+ "@parcel/watcher-linux-arm64-glibc": "2.5.0",
+ "@parcel/watcher-linux-arm64-musl": "2.5.0",
+ "@parcel/watcher-linux-x64-glibc": "2.5.0",
+ "@parcel/watcher-linux-x64-musl": "2.5.0",
+ "@parcel/watcher-win32-arm64": "2.5.0",
+ "@parcel/watcher-win32-ia32": "2.5.0",
+ "@parcel/watcher-win32-x64": "2.5.0"
+ }
+ },
+ "node_modules/@parcel/watcher-android-arm64": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.0.tgz",
+ "integrity": "sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-darwin-arm64": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.0.tgz",
+ "integrity": "sha512-hyZ3TANnzGfLpRA2s/4U1kbw2ZI4qGxaRJbBH2DCSREFfubMswheh8TeiC1sGZ3z2jUf3s37P0BBlrD3sjVTUw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-darwin-x64": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.0.tgz",
+ "integrity": "sha512-9rhlwd78saKf18fT869/poydQK8YqlU26TMiNg7AIu7eBp9adqbJZqmdFOsbZ5cnLp5XvRo9wcFmNHgHdWaGYA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-freebsd-x64": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.0.tgz",
+ "integrity": "sha512-syvfhZzyM8kErg3VF0xpV8dixJ+RzbUaaGaeb7uDuz0D3FK97/mZ5AJQ3XNnDsXX7KkFNtyQyFrXZzQIcN49Tw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm-glibc": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.0.tgz",
+ "integrity": "sha512-0VQY1K35DQET3dVYWpOaPFecqOT9dbuCfzjxoQyif1Wc574t3kOSkKevULddcR9znz1TcklCE7Ht6NIxjvTqLA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm-musl": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.0.tgz",
+ "integrity": "sha512-6uHywSIzz8+vi2lAzFeltnYbdHsDm3iIB57d4g5oaB9vKwjb6N6dRIgZMujw4nm5r6v9/BQH0noq6DzHrqr2pA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm64-glibc": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.0.tgz",
+ "integrity": "sha512-BfNjXwZKxBy4WibDb/LDCriWSKLz+jJRL3cM/DllnHH5QUyoiUNEp3GmL80ZqxeumoADfCCP19+qiYiC8gUBjA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm64-musl": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.0.tgz",
+ "integrity": "sha512-S1qARKOphxfiBEkwLUbHjCY9BWPdWnW9j7f7Hb2jPplu8UZ3nes7zpPOW9bkLbHRvWM0WDTsjdOTUgW0xLBN1Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/@next/swc-linux-x64-gnu": {
- "version": "13.5.6",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.5.6.tgz",
- "integrity": "sha512-Mc2b4xiIWKXIhBy2NBTwOxGD3nHLmq4keFk+d4/WL5fMsB8XdJRdtUlL87SqVCTSaf1BRuQQf1HvXZcy+rq3Nw==",
+ "node_modules/@parcel/watcher-linux-x64-glibc": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.0.tgz",
+ "integrity": "sha512-d9AOkusyXARkFD66S6zlGXyzx5RvY+chTP9Jp0ypSTC9d4lzyRs9ovGf/80VCxjKddcUvnsGwCHWuF2EoPgWjw==",
"cpu": [
"x64"
],
+ "dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
- "node": ">= 10"
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/@next/swc-linux-x64-musl": {
- "version": "13.5.6",
- "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.5.6.tgz",
- "integrity": "sha512-CFHvP9Qz98NruJiUnCe61O6GveKKHpJLloXbDSWRhqhkJdZD2zU5hG+gtVJR//tyW897izuHpM6Gtf6+sNgJPQ==",
+ "node_modules/@parcel/watcher-linux-x64-musl": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.0.tgz",
+ "integrity": "sha512-iqOC+GoTDoFyk/VYSFHwjHhYrk8bljW6zOhPuhi5t9ulqiYq1togGJB5e3PwYVFFfeVgc6pbz3JdQyDoBszVaA==",
"cpu": [
"x64"
],
+ "dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"linux"
],
"engines": {
- "node": ">= 10"
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/@next/swc-win32-arm64-msvc": {
- "version": "13.5.6",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.5.6.tgz",
- "integrity": "sha512-aFv1ejfkbS7PUa1qVPwzDHjQWQtknzAZWGTKYIAaS4NMtBlk3VyA6AYn593pqNanlicewqyl2jUhQAaFV/qXsg==",
+ "node_modules/@parcel/watcher-win32-arm64": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.0.tgz",
+ "integrity": "sha512-twtft1d+JRNkM5YbmexfcH/N4znDtjgysFaV9zvZmmJezQsKpkfLYJ+JFV3uygugK6AtIM2oADPkB2AdhBrNig==",
"cpu": [
"arm64"
],
+ "dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
- "node": ">= 10"
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/@next/swc-win32-ia32-msvc": {
- "version": "13.5.6",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.5.6.tgz",
- "integrity": "sha512-XqqpHgEIlBHvzwG8sp/JXMFkLAfGLqkbVsyN+/Ih1mR8INb6YCc2x/Mbwi6hsAgUnqQztz8cvEbHJUbSl7RHDg==",
+ "node_modules/@parcel/watcher-win32-ia32": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.0.tgz",
+ "integrity": "sha512-+rgpsNRKwo8A53elqbbHXdOMtY/tAtTzManTWShB5Kk54N8Q9mzNWV7tV+IbGueCbcj826MfWGU3mprWtuf1TA==",
"cpu": [
"ia32"
],
+ "dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
- "node": ">= 10"
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/@next/swc-win32-x64-msvc": {
- "version": "13.5.6",
- "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.5.6.tgz",
- "integrity": "sha512-Cqfe1YmOS7k+5mGu92nl5ULkzpKuxJrP3+4AEuPmrpFZ3BHxTY3TnHmU1On3bFmFFs6FbTcdF58CCUProGpIGQ==",
+ "node_modules/@parcel/watcher-win32-x64": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.0.tgz",
+ "integrity": "sha512-lPrxve92zEHdgeff3aiu4gDOIt4u7sJYha6wbdEZDCDUhtjTsOMiaJzG5lMY4GkWH8p0fMmO2Ppq5G5XXG+DQw==",
"cpu": [
"x64"
],
+ "dev": true,
+ "license": "MIT",
"optional": true,
"os": [
"win32"
],
"engines": {
- "node": ">= 10"
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
}
},
- "node_modules/@nodelib/fs.scandir": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
- "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "node_modules/@parcel/watcher/node_modules/detect-libc": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
+ "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
"dev": true,
- "dependencies": {
- "@nodelib/fs.stat": "2.0.5",
- "run-parallel": "^1.1.9"
+ "license": "Apache-2.0",
+ "optional": true,
+ "bin": {
+ "detect-libc": "bin/detect-libc.js"
},
"engines": {
- "node": ">= 8"
+ "node": ">=0.10"
}
},
- "node_modules/@nodelib/fs.stat": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
- "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "node_modules/@rtsao/scc": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
+ "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==",
"dev": true,
- "engines": {
- "node": ">= 8"
- }
+ "license": "MIT"
},
- "node_modules/@nodelib/fs.walk": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
- "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "node_modules/@rushstack/eslint-patch": {
+ "version": "1.10.4",
+ "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz",
+ "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==",
"dev": true,
- "dependencies": {
- "@nodelib/fs.scandir": "2.1.5",
- "fastq": "^1.6.0"
- },
- "engines": {
- "node": ">= 8"
- }
+ "license": "MIT"
},
- "node_modules/@rushstack/eslint-patch": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.6.0.tgz",
- "integrity": "sha512-2/U3GXA6YiPYQDLGwtGlnNgKYBSwCFIHf8Y9LUY5VATHdtbLlU0Y1R3QoBnT0aB4qv/BEiVVsj7LJXoQCgJ2vA==",
- "dev": true
+ "node_modules/@swc/counter": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz",
+ "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==",
+ "license": "Apache-2.0"
},
"node_modules/@swc/helpers": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz",
- "integrity": "sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==",
+ "version": "0.5.15",
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz",
+ "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==",
+ "license": "Apache-2.0",
"dependencies": {
- "tslib": "^2.4.0"
+ "tslib": "^2.8.0"
}
},
+ "node_modules/@types/cookie": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
+ "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==",
+ "license": "MIT"
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
+ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/json5": {
"version": "0.0.29",
"resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@types/node": {
- "version": "20.9.4",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.4.tgz",
- "integrity": "sha512-wmyg8HUhcn6ACjsn8oKYjkN/zUzQeNtMy44weTJSM6p4MMzEOuKbA3OjJ267uPCOW7Xex9dyrNTful8XTQYoDA==",
+ "version": "20.17.11",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.11.tgz",
+ "integrity": "sha512-Ept5glCK35R8yeyIeYlRIZtX6SLRyqMhOFTgj5SOkMpLTdw3SEHI9fHx60xaUZ+V1aJxQJODE+7/j5ocZydYTg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "undici-types": "~5.26.4"
+ "undici-types": "~6.19.2"
}
},
- "node_modules/@types/prop-types": {
- "version": "15.7.11",
- "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.11.tgz",
- "integrity": "sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==",
- "dev": true
- },
"node_modules/@types/react": {
- "version": "18.2.38",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.38.tgz",
- "integrity": "sha512-cBBXHzuPtQK6wNthuVMV6IjHAFkdl/FOPFIlkd81/Cd1+IqkHu/A+w4g43kaQQoYHik/ruaQBDL72HyCy1vuMw==",
+ "version": "19.0.2",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.2.tgz",
+ "integrity": "sha512-USU8ZI/xyKJwFTpjSVIrSeHBVAGagkHQKPNbxeWwql/vDmnTIBgx+TJnhFnj1NXgz8XfprU0egV2dROLGpsBEg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@types/prop-types": "*",
- "@types/scheduler": "*",
"csstype": "^3.0.2"
}
},
"node_modules/@types/react-dom": {
- "version": "18.2.17",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.17.tgz",
- "integrity": "sha512-rvrT/M7Df5eykWFxn6MYt5Pem/Dbyc1N8Y0S9Mrkw2WFCRiqUgw9P7ul2NpwsXCSM1DVdENzdG9J5SreqfAIWg==",
+ "version": "19.0.2",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.2.tgz",
+ "integrity": "sha512-c1s+7TKFaDRRxr1TxccIX2u7sfCnc3RxkVyBIUA2lCpyqCF+QoAwQ/CBg7bsMdVwP120HEH143VQezKtef5nCg==",
"dev": true,
- "dependencies": {
- "@types/react": "*"
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/react": "^19.0.0"
}
},
- "node_modules/@types/scheduler": {
- "version": "0.16.8",
- "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz",
- "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==",
- "dev": true
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.19.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.0.tgz",
+ "integrity": "sha512-NggSaEZCdSrFddbctrVjkVZvFC6KGfKfNK0CU7mNK/iKHGKbzT4Wmgm08dKpcZECBu9f5FypndoMyRHkdqfT1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.10.0",
+ "@typescript-eslint/scope-manager": "8.19.0",
+ "@typescript-eslint/type-utils": "8.19.0",
+ "@typescript-eslint/utils": "8.19.0",
+ "@typescript-eslint/visitor-keys": "8.19.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.3.1",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <5.8.0"
+ }
},
"node_modules/@typescript-eslint/parser": {
- "version": "6.12.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.12.0.tgz",
- "integrity": "sha512-s8/jNFPKPNRmXEnNXfuo1gemBdVmpQsK1pcu+QIvuNJuhFzGrpD7WjOcvDc/+uEdfzSYpNu7U/+MmbScjoQ6vg==",
+ "version": "8.19.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.19.0.tgz",
+ "integrity": "sha512-6M8taKyOETY1TKHp0x8ndycipTVgmp4xtg5QpEZzXxDhNvvHOJi5rLRkLr8SK3jTgD5l4fTlvBiRdfsuWydxBw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@typescript-eslint/scope-manager": "6.12.0",
- "@typescript-eslint/types": "6.12.0",
- "@typescript-eslint/typescript-estree": "6.12.0",
- "@typescript-eslint/visitor-keys": "6.12.0",
+ "@typescript-eslint/scope-manager": "8.19.0",
+ "@typescript-eslint/types": "8.19.0",
+ "@typescript-eslint/typescript-estree": "8.19.0",
+ "@typescript-eslint/visitor-keys": "8.19.0",
"debug": "^4.3.4"
},
"engines": {
- "node": "^16.0.0 || >=18.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "eslint": "^7.0.0 || ^8.0.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <5.8.0"
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "6.12.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.12.0.tgz",
- "integrity": "sha512-5gUvjg+XdSj8pcetdL9eXJzQNTl3RD7LgUiYTl8Aabdi8hFkaGSYnaS6BLc0BGNaDH+tVzVwmKtWvu0jLgWVbw==",
+ "version": "8.19.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.19.0.tgz",
+ "integrity": "sha512-hkoJiKQS3GQ13TSMEiuNmSCvhz7ujyqD1x3ShbaETATHrck+9RaDdUbt+osXaUuns9OFwrDTTrjtwsU8gJyyRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.19.0",
+ "@typescript-eslint/visitor-keys": "8.19.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "8.19.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.19.0.tgz",
+ "integrity": "sha512-TZs0I0OSbd5Aza4qAMpp1cdCYVnER94IziudE3JU328YUHgWu9gwiwhag+fuLeJ2LkWLXI+F/182TbG+JaBdTg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "6.12.0",
- "@typescript-eslint/visitor-keys": "6.12.0"
+ "@typescript-eslint/typescript-estree": "8.19.0",
+ "@typescript-eslint/utils": "8.19.0",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^1.3.0"
},
"engines": {
- "node": "^16.0.0 || >=18.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <5.8.0"
}
},
"node_modules/@typescript-eslint/types": {
- "version": "6.12.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.12.0.tgz",
- "integrity": "sha512-MA16p/+WxM5JG/F3RTpRIcuOghWO30//VEOvzubM8zuOOBYXsP+IfjoCXXiIfy2Ta8FRh9+IO9QLlaFQUU+10Q==",
+ "version": "8.19.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.0.tgz",
+ "integrity": "sha512-8XQ4Ss7G9WX8oaYvD4OOLCjIQYgRQxO+qCiR2V2s2GxI9AUpo7riNwo6jDhKtTcaJjT8PY54j2Yb33kWtSJsmA==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": "^16.0.0 || >=18.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
@@ -435,60 +1359,136 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "6.12.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.12.0.tgz",
- "integrity": "sha512-vw9E2P9+3UUWzhgjyyVczLWxZ3GuQNT7QpnIY3o5OMeLO/c8oHljGc8ZpryBMIyympiAAaKgw9e5Hl9dCWFOYw==",
+ "version": "8.19.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.19.0.tgz",
+ "integrity": "sha512-WW9PpDaLIFW9LCbucMSdYUuGeFUz1OkWYS/5fwZwTA+l2RwlWFdJvReQqMUMBw4yJWJOfqd7An9uwut2Oj8sLw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "6.12.0",
- "@typescript-eslint/visitor-keys": "6.12.0",
+ "@typescript-eslint/types": "8.19.0",
+ "@typescript-eslint/visitor-keys": "8.19.0",
"debug": "^4.3.4",
- "globby": "^11.1.0",
+ "fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
- "semver": "^7.5.4",
- "ts-api-utils": "^1.0.1"
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^1.3.0"
},
"engines": {
- "node": "^16.0.0 || >=18.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <5.8.0"
}
},
- "node_modules/@typescript-eslint/visitor-keys": {
- "version": "6.12.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.12.0.tgz",
- "integrity": "sha512-rg3BizTZHF1k3ipn8gfrzDXXSFKyOEB5zxYXInQ6z0hUvmQlhaZQzK+YmHmNViMA9HzW5Q9+bPPt90bU6GQwyw==",
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/fast-glob": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.8"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "8.19.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.19.0.tgz",
+ "integrity": "sha512-PTBG+0oEMPH9jCZlfg07LCB2nYI0I317yyvXGfxnvGvw4SHIOuRnQ3kadyyXY6tGdChusIHIbM5zfIbp4M6tCg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "6.12.0",
- "eslint-visitor-keys": "^3.4.1"
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@typescript-eslint/scope-manager": "8.19.0",
+ "@typescript-eslint/types": "8.19.0",
+ "@typescript-eslint/typescript-estree": "8.19.0"
},
"engines": {
- "node": "^16.0.0 || >=18.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <5.8.0"
}
},
- "node_modules/@ungap/structured-clone": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
- "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
- "dev": true
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.19.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.0.tgz",
+ "integrity": "sha512-mCFtBbFBJDCNCWUl5y6sZSCHXw1DEFEk3c/M3nRK2a4XUB8StGFtmcEMizdjKuBzB6e/smJAAWYug3VrdLMr1w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.19.0",
+ "eslint-visitor-keys": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
},
"node_modules/acorn": {
- "version": "8.11.2",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz",
- "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==",
+ "version": "8.14.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
+ "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
"dev": true,
+ "license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
@@ -501,6 +1501,7 @@
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
"dev": true,
+ "license": "MIT",
"peerDependencies": {
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
@@ -510,6 +1511,7 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -521,20 +1523,12 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
- "node_modules/ansi-regex": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
- "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -549,40 +1543,48 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true
+ "dev": true,
+ "license": "Python-2.0"
},
"node_modules/aria-query": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
- "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz",
+ "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==",
"dev": true,
- "dependencies": {
- "dequal": "^2.0.3"
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
}
},
"node_modules/array-buffer-byte-length": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz",
- "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
+ "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "is-array-buffer": "^3.0.1"
+ "call-bound": "^1.0.3",
+ "is-array-buffer": "^3.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/array-includes": {
- "version": "3.1.7",
- "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz",
- "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==",
+ "version": "3.1.8",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz",
+ "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "get-intrinsic": "^1.2.1",
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.4",
"is-string": "^1.0.7"
},
"engines": {
@@ -592,26 +1594,40 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/array-union": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
- "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "node_modules/array.prototype.findlast": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
+ "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
"engines": {
- "node": ">=8"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/array.prototype.findlastindex": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz",
- "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==",
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz",
+ "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "es-shim-unscopables": "^1.0.0",
- "get-intrinsic": "^1.2.1"
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "es-shim-unscopables": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -621,15 +1637,16 @@
}
},
"node_modules/array.prototype.flat": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz",
- "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==",
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz",
+ "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "es-shim-unscopables": "^1.0.0"
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -639,15 +1656,16 @@
}
},
"node_modules/array.prototype.flatmap": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz",
- "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==",
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz",
+ "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "es-shim-unscopables": "^1.0.0"
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -657,31 +1675,36 @@
}
},
"node_modules/array.prototype.tosorted": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz",
- "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz",
+ "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "es-shim-unscopables": "^1.0.0",
- "get-intrinsic": "^1.2.1"
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.3",
+ "es-errors": "^1.3.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
}
},
"node_modules/arraybuffer.prototype.slice": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz",
- "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==",
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
+ "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "array-buffer-byte-length": "^1.0.0",
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "get-intrinsic": "^1.2.1",
- "is-array-buffer": "^3.0.2",
- "is-shared-array-buffer": "^1.0.2"
+ "array-buffer-byte-length": "^1.0.1",
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "is-array-buffer": "^3.0.4"
},
"engines": {
"node": ">= 0.4"
@@ -694,22 +1717,24 @@
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz",
"integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==",
- "dev": true
- },
- "node_modules/asynciterator.prototype": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz",
- "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==",
"dev": true,
- "dependencies": {
- "has-symbols": "^1.0.3"
- }
+ "license": "MIT"
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
},
"node_modules/available-typed-arrays": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
- "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
"engines": {
"node": ">= 0.4"
},
@@ -718,46 +1743,62 @@
}
},
"node_modules/axe-core": {
- "version": "4.7.0",
- "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz",
- "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==",
+ "version": "4.10.2",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz",
+ "integrity": "sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==",
"dev": true,
+ "license": "MPL-2.0",
"engines": {
"node": ">=4"
}
},
+ "node_modules/axios": {
+ "version": "1.7.9",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz",
+ "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==",
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
"node_modules/axobject-query": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz",
- "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz",
+ "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==",
"dev": true,
- "dependencies": {
- "dequal": "^2.0.3"
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">= 0.4"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "fill-range": "^7.0.1"
+ "fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
@@ -775,14 +1816,50 @@
}
},
"node_modules/call-bind": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz",
- "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==",
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
+ "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "function-bind": "^1.1.2",
- "get-intrinsic": "^1.2.1",
- "set-function-length": "^1.1.1"
+ "call-bind-apply-helpers": "^1.0.0",
+ "es-define-property": "^1.0.0",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz",
+ "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz",
+ "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -793,14 +1870,15 @@
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001564",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001564.tgz",
- "integrity": "sha512-DqAOf+rhof+6GVx1y+xzbFPeOumfQnhYzVnZD6LAXijR77yPtm9mfOcqOnT3mpnJiZVT+kwLAFnRlZcIz+c6bg==",
+ "version": "1.0.30001690",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz",
+ "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==",
"funding": [
{
"type": "opencollective",
@@ -814,34 +1892,77 @@
"type": "github",
"url": "https://github.com/sponsors/ai"
}
- ]
+ ],
+ "license": "CC-BY-4.0"
},
"node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
- "node": ">=10"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz",
+ "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "readdirp": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14.16.0"
},
"funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
+ "url": "https://paulmillr.com/funding/"
}
},
"node_modules/client-only": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
- "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
+ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==",
+ "license": "MIT"
+ },
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/color": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
+ "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "color-convert": "^2.0.1",
+ "color-string": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=12.5.0"
+ }
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
+ "devOptional": true,
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -853,19 +1974,54 @@
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/color-string": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
+ "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cookie": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz",
+ "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
},
"node_modules/cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
@@ -876,24 +2032,87 @@
}
},
"node_modules/csstype": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz",
- "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==",
- "dev": true
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/damerau-levenshtein": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz",
"integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==",
- "dev": true
+ "dev": true,
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/data-view-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
+ "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
+ "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/inspect-js"
+ }
+ },
+ "node_modules/data-view-byte-offset": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
+ "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/dayjs": {
+ "version": "1.11.13",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
+ "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==",
+ "license": "MIT"
},
"node_modules/debug": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
- "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
+ "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ms": "2.1.2"
+ "ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
@@ -908,20 +2127,25 @@
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/define-data-property": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz",
- "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "get-intrinsic": "^1.2.1",
- "gopd": "^1.0.1",
- "has-property-descriptors": "^1.0.0"
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/define-properties": {
@@ -929,6 +2153,7 @@
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
"integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"define-data-property": "^1.0.1",
"has-property-descriptors": "^1.0.0",
@@ -941,50 +2166,66 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/dequal": {
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/detect-libc": {
"version": "2.0.3",
- "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
- "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
- "dev": true,
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
+ "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
+ "license": "Apache-2.0",
+ "optional": true,
"engines": {
- "node": ">=6"
+ "node": ">=8"
}
},
- "node_modules/dir-glob": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
- "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "path-type": "^4.0.0"
+ "esutils": "^2.0.2"
},
"engines": {
- "node": ">=8"
+ "node": ">=0.10.0"
}
},
- "node_modules/doctrine": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
- "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "esutils": "^2.0.2"
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
},
"engines": {
- "node": ">=6.0.0"
+ "node": ">= 0.4"
}
},
"node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/enhanced-resolve": {
- "version": "5.15.0",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz",
- "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==",
+ "version": "5.18.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz",
+ "integrity": "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"graceful-fs": "^4.2.4",
"tapable": "^2.2.0"
@@ -994,50 +2235,63 @@
}
},
"node_modules/es-abstract": {
- "version": "1.22.3",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz",
- "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==",
- "dev": true,
- "dependencies": {
- "array-buffer-byte-length": "^1.0.0",
- "arraybuffer.prototype.slice": "^1.0.2",
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.5",
- "es-set-tostringtag": "^2.0.1",
- "es-to-primitive": "^1.2.1",
- "function.prototype.name": "^1.1.6",
- "get-intrinsic": "^1.2.2",
- "get-symbol-description": "^1.0.0",
- "globalthis": "^1.0.3",
- "gopd": "^1.0.1",
- "has-property-descriptors": "^1.0.0",
- "has-proto": "^1.0.1",
- "has-symbols": "^1.0.3",
- "hasown": "^2.0.0",
- "internal-slot": "^1.0.5",
- "is-array-buffer": "^3.0.2",
+ "version": "1.23.9",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz",
+ "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.2",
+ "arraybuffer.prototype.slice": "^1.0.4",
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "data-view-buffer": "^1.0.2",
+ "data-view-byte-length": "^1.0.2",
+ "data-view-byte-offset": "^1.0.1",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "es-set-tostringtag": "^2.1.0",
+ "es-to-primitive": "^1.3.0",
+ "function.prototype.name": "^1.1.8",
+ "get-intrinsic": "^1.2.7",
+ "get-proto": "^1.0.0",
+ "get-symbol-description": "^1.1.0",
+ "globalthis": "^1.0.4",
+ "gopd": "^1.2.0",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "internal-slot": "^1.1.0",
+ "is-array-buffer": "^3.0.5",
"is-callable": "^1.2.7",
- "is-negative-zero": "^2.0.2",
- "is-regex": "^1.1.4",
- "is-shared-array-buffer": "^1.0.2",
- "is-string": "^1.0.7",
- "is-typed-array": "^1.1.12",
- "is-weakref": "^1.0.2",
- "object-inspect": "^1.13.1",
+ "is-data-view": "^1.0.2",
+ "is-regex": "^1.2.1",
+ "is-shared-array-buffer": "^1.0.4",
+ "is-string": "^1.1.1",
+ "is-typed-array": "^1.1.15",
+ "is-weakref": "^1.1.0",
+ "math-intrinsics": "^1.1.0",
+ "object-inspect": "^1.13.3",
"object-keys": "^1.1.1",
- "object.assign": "^4.1.4",
- "regexp.prototype.flags": "^1.5.1",
- "safe-array-concat": "^1.0.1",
- "safe-regex-test": "^1.0.0",
- "string.prototype.trim": "^1.2.8",
- "string.prototype.trimend": "^1.0.7",
- "string.prototype.trimstart": "^1.0.7",
- "typed-array-buffer": "^1.0.0",
- "typed-array-byte-length": "^1.0.0",
- "typed-array-byte-offset": "^1.0.0",
- "typed-array-length": "^1.0.4",
- "unbox-primitive": "^1.0.2",
- "which-typed-array": "^1.1.13"
+ "object.assign": "^4.1.7",
+ "own-keys": "^1.0.1",
+ "regexp.prototype.flags": "^1.5.3",
+ "safe-array-concat": "^1.1.3",
+ "safe-push-apply": "^1.0.0",
+ "safe-regex-test": "^1.1.0",
+ "set-proto": "^1.0.0",
+ "string.prototype.trim": "^1.2.10",
+ "string.prototype.trimend": "^1.0.9",
+ "string.prototype.trimstart": "^1.0.8",
+ "typed-array-buffer": "^1.0.3",
+ "typed-array-byte-length": "^1.0.3",
+ "typed-array-byte-offset": "^1.0.4",
+ "typed-array-length": "^1.0.7",
+ "unbox-primitive": "^1.1.0",
+ "which-typed-array": "^1.1.18"
},
"engines": {
"node": ">= 0.4"
@@ -1046,37 +2300,78 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/es-iterator-helpers": {
- "version": "1.0.15",
- "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz",
- "integrity": "sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz",
+ "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "asynciterator.prototype": "^1.0.0",
- "call-bind": "^1.0.2",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
"define-properties": "^1.2.1",
- "es-abstract": "^1.22.1",
- "es-set-tostringtag": "^2.0.1",
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.2.1",
- "globalthis": "^1.0.3",
- "has-property-descriptors": "^1.0.0",
- "has-proto": "^1.0.1",
- "has-symbols": "^1.0.3",
- "internal-slot": "^1.0.5",
- "iterator.prototype": "^1.1.2",
- "safe-array-concat": "^1.0.1"
+ "es-abstract": "^1.23.6",
+ "es-errors": "^1.3.0",
+ "es-set-tostringtag": "^2.0.3",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.6",
+ "globalthis": "^1.0.4",
+ "gopd": "^1.2.0",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "internal-slot": "^1.1.0",
+ "iterator.prototype": "^1.1.4",
+ "safe-array-concat": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz",
+ "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
}
},
"node_modules/es-set-tostringtag": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz",
- "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "get-intrinsic": "^1.2.2",
- "has-tostringtag": "^1.0.0",
- "hasown": "^2.0.0"
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -1087,19 +2382,21 @@
"resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz",
"integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"hasown": "^2.0.0"
}
},
"node_modules/es-to-primitive": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
- "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
+ "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-callable": "^1.1.4",
- "is-date-object": "^1.0.1",
- "is-symbol": "^1.0.2"
+ "is-callable": "^1.2.7",
+ "is-date-object": "^1.0.5",
+ "is-symbol": "^1.0.4"
},
"engines": {
"node": ">= 0.4"
@@ -1113,6 +2410,7 @@
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=10"
},
@@ -1121,78 +2419,85 @@
}
},
"node_modules/eslint": {
- "version": "8.54.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz",
- "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==",
+ "version": "9.17.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.17.0.tgz",
+ "integrity": "sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
- "@eslint-community/regexpp": "^4.6.1",
- "@eslint/eslintrc": "^2.1.3",
- "@eslint/js": "8.54.0",
- "@humanwhocodes/config-array": "^0.11.13",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.19.0",
+ "@eslint/core": "^0.9.0",
+ "@eslint/eslintrc": "^3.2.0",
+ "@eslint/js": "9.17.0",
+ "@eslint/plugin-kit": "^0.2.3",
+ "@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1",
- "@nodelib/fs.walk": "^1.2.8",
- "@ungap/structured-clone": "^1.2.0",
+ "@humanwhocodes/retry": "^0.4.1",
+ "@types/estree": "^1.0.6",
+ "@types/json-schema": "^7.0.15",
"ajv": "^6.12.4",
"chalk": "^4.0.0",
- "cross-spawn": "^7.0.2",
+ "cross-spawn": "^7.0.6",
"debug": "^4.3.2",
- "doctrine": "^3.0.0",
"escape-string-regexp": "^4.0.0",
- "eslint-scope": "^7.2.2",
- "eslint-visitor-keys": "^3.4.3",
- "espree": "^9.6.1",
- "esquery": "^1.4.2",
+ "eslint-scope": "^8.2.0",
+ "eslint-visitor-keys": "^4.2.0",
+ "espree": "^10.3.0",
+ "esquery": "^1.5.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^6.0.1",
+ "file-entry-cache": "^8.0.0",
"find-up": "^5.0.0",
"glob-parent": "^6.0.2",
- "globals": "^13.19.0",
- "graphemer": "^1.4.0",
"ignore": "^5.2.0",
"imurmurhash": "^0.1.4",
"is-glob": "^4.0.0",
- "is-path-inside": "^3.0.3",
- "js-yaml": "^4.1.0",
"json-stable-stringify-without-jsonify": "^1.0.1",
- "levn": "^0.4.1",
"lodash.merge": "^4.6.2",
"minimatch": "^3.1.2",
"natural-compare": "^1.4.0",
- "optionator": "^0.9.3",
- "strip-ansi": "^6.0.1",
- "text-table": "^0.2.0"
+ "optionator": "^0.9.3"
},
"bin": {
"eslint": "bin/eslint.js"
},
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
- "url": "https://opencollective.com/eslint"
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
}
},
"node_modules/eslint-config-next": {
- "version": "13.5.6",
- "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.5.6.tgz",
- "integrity": "sha512-o8pQsUHTo9aHqJ2YiZDym5gQAMRf7O2HndHo/JZeY7TDD+W4hk6Ma8Vw54RHiBeb7OWWO5dPirQB+Is/aVQ7Kg==",
+ "version": "15.1.3",
+ "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.1.3.tgz",
+ "integrity": "sha512-wGYlNuWnh4ujuKtZvH+7B2Z2vy9nONZE6ztd+DKF7hAsIabkrxmD4TzYHzASHENo42lmz2tnT2B+zN2sOHvpJg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@next/eslint-plugin-next": "13.5.6",
- "@rushstack/eslint-patch": "^1.3.3",
- "@typescript-eslint/parser": "^5.4.2 || ^6.0.0",
+ "@next/eslint-plugin-next": "15.1.3",
+ "@rushstack/eslint-patch": "^1.10.3",
+ "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0",
+ "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0",
"eslint-import-resolver-node": "^0.3.6",
"eslint-import-resolver-typescript": "^3.5.2",
- "eslint-plugin-import": "^2.28.1",
- "eslint-plugin-jsx-a11y": "^6.7.1",
- "eslint-plugin-react": "^7.33.2",
- "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705"
+ "eslint-plugin-import": "^2.31.0",
+ "eslint-plugin-jsx-a11y": "^6.10.0",
+ "eslint-plugin-react": "^7.37.0",
+ "eslint-plugin-react-hooks": "^5.0.0"
},
"peerDependencies": {
- "eslint": "^7.23.0 || ^8.0.0",
+ "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0",
"typescript": ">=3.3.1"
},
"peerDependenciesMeta": {
@@ -1206,6 +2511,7 @@
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
"integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"debug": "^3.2.7",
"is-core-module": "^2.13.0",
@@ -1217,23 +2523,26 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ms": "^2.1.1"
}
},
"node_modules/eslint-import-resolver-typescript": {
- "version": "3.6.1",
- "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz",
- "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==",
- "dev": true,
- "dependencies": {
- "debug": "^4.3.4",
- "enhanced-resolve": "^5.12.0",
- "eslint-module-utils": "^2.7.4",
- "fast-glob": "^3.3.1",
- "get-tsconfig": "^4.5.0",
- "is-core-module": "^2.11.0",
- "is-glob": "^4.0.3"
+ "version": "3.7.0",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.7.0.tgz",
+ "integrity": "sha512-Vrwyi8HHxY97K5ebydMtffsWAn1SCR9eol49eCd5fJS4O1WV7PaAjbcjmbfJJSMz/t4Mal212Uz/fQZrOB8mow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "@nolyfill/is-core-module": "1.0.39",
+ "debug": "^4.3.7",
+ "enhanced-resolve": "^5.15.0",
+ "fast-glob": "^3.3.2",
+ "get-tsconfig": "^4.7.5",
+ "is-bun-module": "^1.0.2",
+ "is-glob": "^4.0.3",
+ "stable-hash": "^0.0.4"
},
"engines": {
"node": "^14.18.0 || >=16.0.0"
@@ -1243,14 +2552,54 @@
},
"peerDependencies": {
"eslint": "*",
- "eslint-plugin-import": "*"
+ "eslint-plugin-import": "*",
+ "eslint-plugin-import-x": "*"
+ },
+ "peerDependenciesMeta": {
+ "eslint-plugin-import": {
+ "optional": true
+ },
+ "eslint-plugin-import-x": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-import-resolver-typescript/node_modules/fast-glob": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.8"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/eslint-import-resolver-typescript/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
}
},
"node_modules/eslint-module-utils": {
- "version": "2.8.0",
- "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz",
- "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==",
+ "version": "2.12.0",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz",
+ "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"debug": "^3.2.7"
},
@@ -1268,39 +2617,43 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ms": "^2.1.1"
}
},
"node_modules/eslint-plugin-import": {
- "version": "2.29.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz",
- "integrity": "sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==",
+ "version": "2.31.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz",
+ "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "array-includes": "^3.1.7",
- "array.prototype.findlastindex": "^1.2.3",
+ "@rtsao/scc": "^1.1.0",
+ "array-includes": "^3.1.8",
+ "array.prototype.findlastindex": "^1.2.5",
"array.prototype.flat": "^1.3.2",
"array.prototype.flatmap": "^1.3.2",
"debug": "^3.2.7",
"doctrine": "^2.1.0",
"eslint-import-resolver-node": "^0.3.9",
- "eslint-module-utils": "^2.8.0",
- "hasown": "^2.0.0",
- "is-core-module": "^2.13.1",
+ "eslint-module-utils": "^2.12.0",
+ "hasown": "^2.0.2",
+ "is-core-module": "^2.15.1",
"is-glob": "^4.0.3",
"minimatch": "^3.1.2",
- "object.fromentries": "^2.0.7",
- "object.groupby": "^1.0.1",
- "object.values": "^1.1.7",
+ "object.fromentries": "^2.0.8",
+ "object.groupby": "^1.0.3",
+ "object.values": "^1.2.0",
"semver": "^6.3.1",
- "tsconfig-paths": "^3.14.2"
+ "string.prototype.trimend": "^1.0.8",
+ "tsconfig-paths": "^3.15.0"
},
"engines": {
"node": ">=4"
},
"peerDependencies": {
- "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9"
}
},
"node_modules/eslint-plugin-import/node_modules/debug": {
@@ -1308,113 +2661,95 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ms": "^2.1.1"
}
},
- "node_modules/eslint-plugin-import/node_modules/doctrine": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
- "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
- "dev": true,
- "dependencies": {
- "esutils": "^2.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/eslint-plugin-import/node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
+ "license": "ISC",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/eslint-plugin-jsx-a11y": {
- "version": "6.8.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz",
- "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==",
+ "version": "6.10.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz",
+ "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/runtime": "^7.23.2",
- "aria-query": "^5.3.0",
- "array-includes": "^3.1.7",
+ "aria-query": "^5.3.2",
+ "array-includes": "^3.1.8",
"array.prototype.flatmap": "^1.3.2",
"ast-types-flow": "^0.0.8",
- "axe-core": "=4.7.0",
- "axobject-query": "^3.2.1",
+ "axe-core": "^4.10.0",
+ "axobject-query": "^4.1.0",
"damerau-levenshtein": "^1.0.8",
"emoji-regex": "^9.2.2",
- "es-iterator-helpers": "^1.0.15",
- "hasown": "^2.0.0",
+ "hasown": "^2.0.2",
"jsx-ast-utils": "^3.3.5",
"language-tags": "^1.0.9",
"minimatch": "^3.1.2",
- "object.entries": "^1.1.7",
- "object.fromentries": "^2.0.7"
+ "object.fromentries": "^2.0.8",
+ "safe-regex-test": "^1.0.3",
+ "string.prototype.includes": "^2.0.1"
},
"engines": {
"node": ">=4.0"
},
"peerDependencies": {
- "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9"
}
},
"node_modules/eslint-plugin-react": {
- "version": "7.33.2",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz",
- "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==",
+ "version": "7.37.3",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.3.tgz",
+ "integrity": "sha512-DomWuTQPFYZwF/7c9W2fkKkStqZmBd3uugfqBYLdkZ3Hii23WzZuOLUskGxB8qkSKqftxEeGL1TB2kMhrce0jA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "array-includes": "^3.1.6",
- "array.prototype.flatmap": "^1.3.1",
- "array.prototype.tosorted": "^1.1.1",
+ "array-includes": "^3.1.8",
+ "array.prototype.findlast": "^1.2.5",
+ "array.prototype.flatmap": "^1.3.3",
+ "array.prototype.tosorted": "^1.1.4",
"doctrine": "^2.1.0",
- "es-iterator-helpers": "^1.0.12",
+ "es-iterator-helpers": "^1.2.1",
"estraverse": "^5.3.0",
+ "hasown": "^2.0.2",
"jsx-ast-utils": "^2.4.1 || ^3.0.0",
"minimatch": "^3.1.2",
- "object.entries": "^1.1.6",
- "object.fromentries": "^2.0.6",
- "object.hasown": "^1.1.2",
- "object.values": "^1.1.6",
+ "object.entries": "^1.1.8",
+ "object.fromentries": "^2.0.8",
+ "object.values": "^1.2.1",
"prop-types": "^15.8.1",
- "resolve": "^2.0.0-next.4",
+ "resolve": "^2.0.0-next.5",
"semver": "^6.3.1",
- "string.prototype.matchall": "^4.0.8"
+ "string.prototype.matchall": "^4.0.12",
+ "string.prototype.repeat": "^1.0.0"
},
"engines": {
"node": ">=4"
},
"peerDependencies": {
- "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
}
},
"node_modules/eslint-plugin-react-hooks": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
- "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.1.0.tgz",
+ "integrity": "sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=10"
},
"peerDependencies": {
- "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0"
- }
- },
- "node_modules/eslint-plugin-react/node_modules/doctrine": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
- "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
- "dev": true,
- "dependencies": {
- "esutils": "^2.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
}
},
"node_modules/eslint-plugin-react/node_modules/resolve": {
@@ -1422,6 +2757,7 @@
"resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
"integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"is-core-module": "^2.13.0",
"path-parse": "^1.0.7",
@@ -1439,60 +2775,65 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
+ "license": "ISC",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/eslint-scope": {
- "version": "7.2.2",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
- "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz",
+ "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"esrecurse": "^4.3.0",
"estraverse": "^5.2.0"
},
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/eslint-visitor-keys": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
- "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
+ "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
"dev": true,
+ "license": "Apache-2.0",
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/espree": {
- "version": "9.6.1",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
- "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz",
+ "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
- "acorn": "^8.9.0",
+ "acorn": "^8.14.0",
"acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^3.4.1"
+ "eslint-visitor-keys": "^4.2.0"
},
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/esquery": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
- "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
"dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
"estraverse": "^5.1.0"
},
@@ -1505,6 +2846,7 @@
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"estraverse": "^5.2.0"
},
@@ -1517,6 +2859,7 @@
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"dev": true,
+ "license": "BSD-2-Clause",
"engines": {
"node": ">=4.0"
}
@@ -1526,6 +2869,7 @@
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"dev": true,
+ "license": "BSD-2-Clause",
"engines": {
"node": ">=0.10.0"
}
@@ -1534,13 +2878,15 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/fast-glob": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
- "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
+ "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3",
@@ -1557,6 +2903,7 @@
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
},
@@ -1568,40 +2915,45 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/fast-levenshtein": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/fastq": {
- "version": "1.15.0",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
- "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
+ "version": "1.18.0",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz",
+ "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"reusify": "^1.0.4"
}
},
"node_modules/file-entry-cache": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
- "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "flat-cache": "^3.0.4"
+ "flat-cache": "^4.0.0"
},
"engines": {
- "node": "^10.12.0 || >=12.0.0"
+ "node": ">=16.0.0"
}
},
"node_modules/fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
},
@@ -1614,6 +2966,7 @@
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"locate-path": "^6.0.0",
"path-exists": "^4.0.0"
@@ -1626,59 +2979,93 @@
}
},
"node_modules/flat-cache": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
- "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"flatted": "^3.2.9",
- "keyv": "^4.5.3",
- "rimraf": "^3.0.2"
+ "keyv": "^4.5.4"
},
"engines": {
- "node": "^10.12.0 || >=12.0.0"
+ "node": ">=16"
}
},
"node_modules/flatted": {
- "version": "3.2.9",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
- "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
- "dev": true
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz",
+ "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.9",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
+ "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
},
"node_modules/for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
"integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"is-callable": "^1.1.3"
}
},
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "dev": true
+ "node_modules/form-data": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
+ "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true,
+ "license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/function.prototype.name": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
- "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
+ "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "functions-have-names": "^1.2.3"
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "functions-have-names": "^1.2.3",
+ "hasown": "^2.0.2",
+ "is-callable": "^1.2.7"
},
"engines": {
"node": ">= 0.4"
@@ -1692,71 +3079,79 @@
"resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
"dev": true,
+ "license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-intrinsic": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
- "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==",
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz",
+ "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
"function-bind": "^1.1.2",
- "has-proto": "^1.0.1",
- "has-symbols": "^1.0.3",
- "hasown": "^2.0.0"
+ "get-proto": "^1.0.0",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/get-symbol-description": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
- "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.1"
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/get-tsconfig": {
- "version": "4.7.2",
- "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz",
- "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==",
+ "node_modules/get-symbol-description": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
+ "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "resolve-pkg-maps": "^1.0.0"
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
- "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/glob": {
- "version": "7.1.7",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
- "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+ "node_modules/get-tsconfig": {
+ "version": "4.8.1",
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz",
+ "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.0.4",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
+ "resolve-pkg-maps": "^1.0.0"
},
"funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
}
},
"node_modules/glob-parent": {
@@ -1764,6 +3159,7 @@
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"is-glob": "^4.0.3"
},
@@ -1771,33 +3167,28 @@
"node": ">=10.13.0"
}
},
- "node_modules/glob-to-regexp": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
- "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
- },
"node_modules/globals": {
- "version": "13.23.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
- "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
"dev": true,
- "dependencies": {
- "type-fest": "^0.20.2"
- },
+ "license": "MIT",
"engines": {
- "node": ">=8"
+ "node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/globalthis": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz",
- "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==",
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
+ "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "define-properties": "^1.1.3"
+ "define-properties": "^1.2.1",
+ "gopd": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
@@ -1806,33 +3197,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/globby": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
- "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
- "dev": true,
- "dependencies": {
- "array-union": "^2.1.0",
- "dir-glob": "^3.0.1",
- "fast-glob": "^3.2.9",
- "ignore": "^5.2.0",
- "merge2": "^1.4.1",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/gopd": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
- "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"dev": true,
- "dependencies": {
- "get-intrinsic": "^1.1.3"
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -1841,19 +3213,26 @@
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
- "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+ "dev": true,
+ "license": "ISC"
},
"node_modules/graphemer": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/has-bigints": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
- "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
+ "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
"dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -1863,27 +3242,33 @@
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/has-property-descriptors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz",
- "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "get-intrinsic": "^1.2.2"
+ "es-define-property": "^1.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
- "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
+ "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.0"
+ },
"engines": {
"node": ">= 0.4"
},
@@ -1892,10 +3277,11 @@
}
},
"node_modules/has-symbols": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
- "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -1904,12 +3290,13 @@
}
},
"node_modules/has-tostringtag": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
- "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "has-symbols": "^1.0.2"
+ "has-symbols": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
@@ -1919,10 +3306,11 @@
}
},
"node_modules/hasown": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
- "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
},
@@ -1931,19 +3319,28 @@
}
},
"node_modules/ignore": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
- "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 4"
}
},
+ "node_modules/immutable": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz",
+ "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==",
+ "devOptional": true,
+ "license": "MIT"
+ },
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
"integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"parent-module": "^1.0.0",
"resolve-from": "^4.0.0"
@@ -1960,61 +3357,62 @@
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.8.19"
}
},
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "dev": true,
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "dev": true
- },
"node_modules/internal-slot": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz",
- "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
+ "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "get-intrinsic": "^1.2.2",
- "hasown": "^2.0.0",
- "side-channel": "^1.0.4"
+ "es-errors": "^1.3.0",
+ "hasown": "^2.0.2",
+ "side-channel": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/is-array-buffer": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz",
- "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==",
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
+ "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.0",
- "is-typed-array": "^1.1.10"
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-arrayish": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
+ "license": "MIT",
+ "optional": true
+ },
"node_modules/is-async-function": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz",
- "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.0.tgz",
+ "integrity": "sha512-GExz9MtyhlZyXYLxzlJRj5WUCE661zhDa1Yna52CN57AJsymh+DvXXjyveSioqSRdxvUrdKdvqB1b5cVKsNpWQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "has-tostringtag": "^1.0.0"
+ "call-bound": "^1.0.3",
+ "get-proto": "^1.0.1",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
@@ -2024,25 +3422,30 @@
}
},
"node_modules/is-bigint": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
- "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
+ "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "has-bigints": "^1.0.1"
+ "has-bigints": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-boolean-object": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
- "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz",
+ "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
+ "call-bound": "^1.0.2",
+ "has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -2051,11 +3454,22 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-bun-module": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.3.0.tgz",
+ "integrity": "sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.6.3"
+ }
+ },
"node_modules/is-callable": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -2064,24 +3478,48 @@
}
},
"node_modules/is-core-module": {
- "version": "2.13.1",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
- "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+ "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "hasown": "^2.0.0"
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-data-view": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
+ "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "get-intrinsic": "^1.2.6",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-date-object": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
- "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
+ "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "has-tostringtag": "^1.0.0"
+ "call-bound": "^1.0.2",
+ "has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -2095,29 +3533,38 @@
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-finalizationregistry": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz",
- "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
+ "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2"
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-generator-function": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
- "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz",
+ "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "has-tostringtag": "^1.0.0"
+ "call-bound": "^1.0.3",
+ "get-proto": "^1.0.0",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
@@ -2131,6 +3578,7 @@
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"is-extglob": "^2.1.1"
},
@@ -2139,19 +3587,11 @@
}
},
"node_modules/is-map": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
- "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-negative-zero": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
- "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
+ "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -2164,17 +3604,20 @@
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/is-number-object": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
- "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
+ "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "has-tostringtag": "^1.0.0"
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -2183,23 +3626,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-path-inside": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
- "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/is-regex": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
- "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
+ "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
+ "call-bound": "^1.0.2",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -2209,33 +3646,43 @@
}
},
"node_modules/is-set": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz",
- "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==",
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
+ "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
"dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-shared-array-buffer": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
- "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==",
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
+ "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2"
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-string": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
- "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
+ "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "has-tostringtag": "^1.0.0"
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -2245,12 +3692,15 @@
}
},
"node_modules/is-symbol": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
- "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
+ "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "has-symbols": "^1.0.2"
+ "call-bound": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "safe-regex-test": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
@@ -2260,12 +3710,13 @@
}
},
"node_modules/is-typed-array": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
- "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==",
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
+ "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "which-typed-array": "^1.1.11"
+ "which-typed-array": "^1.1.16"
},
"engines": {
"node": ">= 0.4"
@@ -2275,34 +3726,46 @@
}
},
"node_modules/is-weakmap": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
- "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
+ "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
"dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-weakref": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
- "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz",
+ "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2"
+ "call-bound": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-weakset": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
- "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
+ "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.1"
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -2312,37 +3775,56 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true
+ "dev": true,
+ "license": "ISC"
},
"node_modules/iterator.prototype": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz",
- "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==",
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz",
+ "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "define-properties": "^1.2.1",
- "get-intrinsic": "^1.2.1",
- "has-symbols": "^1.0.3",
- "reflect.getprototypeof": "^1.0.4",
- "set-function-name": "^2.0.1"
+ "define-data-property": "^1.1.4",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.6",
+ "get-proto": "^1.0.0",
+ "has-symbols": "^1.1.0",
+ "set-function-name": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/jose": {
+ "version": "5.9.6",
+ "resolved": "https://registry.npmjs.org/jose/-/jose-5.9.6.tgz",
+ "integrity": "sha512-AMlnetc9+CV9asI19zHmrgS/WYsWUwCn2R7RzlbJWD7F9eWYUTGyBmU9o6PxngtLGOiDGPRu+Uc4fhKzbpteZQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
- "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"argparse": "^2.0.1"
},
@@ -2354,25 +3836,29 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/json5": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
"integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"minimist": "^1.2.0"
},
@@ -2385,6 +3871,7 @@
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
"integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"array-includes": "^3.1.6",
"array.prototype.flat": "^1.3.1",
@@ -2395,26 +3882,38 @@
"node": ">=4.0"
}
},
+ "node_modules/jwt-decode": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz",
+ "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"json-buffer": "3.0.1"
}
},
"node_modules/language-subtag-registry": {
- "version": "0.3.22",
- "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
- "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==",
- "dev": true
+ "version": "0.3.23",
+ "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz",
+ "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==",
+ "dev": true,
+ "license": "CC0-1.0"
},
"node_modules/language-tags": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz",
"integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"language-subtag-registry": "^0.3.20"
},
@@ -2427,6 +3926,7 @@
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"prelude-ls": "^1.2.1",
"type-check": "~0.4.0"
@@ -2440,6 +3940,7 @@
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"p-locate": "^5.0.0"
},
@@ -2450,16 +3951,25 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "license": "MIT"
+ },
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/loose-envify": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
"integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
@@ -2467,16 +3977,14 @@
"loose-envify": "cli.js"
}
},
- "node_modules/lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"dev": true,
- "dependencies": {
- "yallist": "^4.0.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=10"
+ "node": ">= 0.4"
}
},
"node_modules/merge2": {
@@ -2484,28 +3992,52 @@
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 8"
}
},
"node_modules/micromatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
- "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "braces": "^3.0.2",
+ "braces": "^3.0.3",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=8.6"
}
},
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -2518,26 +4050,29 @@
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
"dev": true,
+ "license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
- "dev": true
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/nanoid": {
- "version": "3.3.7",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
- "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "version": "3.3.8",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz",
+ "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
+ "license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
@@ -2549,67 +4084,126 @@
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/next": {
- "version": "13.5.6",
- "resolved": "https://registry.npmjs.org/next/-/next-13.5.6.tgz",
- "integrity": "sha512-Y2wTcTbO4WwEsVb4A8VSnOsG1I9ok+h74q0ZdxkwM3EODqrs4pasq7O0iUxbcS9VtWMicG7f3+HAj0r1+NtKSw==",
- "dependencies": {
- "@next/env": "13.5.6",
- "@swc/helpers": "0.5.2",
+ "version": "15.1.3",
+ "resolved": "https://registry.npmjs.org/next/-/next-15.1.3.tgz",
+ "integrity": "sha512-5igmb8N8AEhWDYzogcJvtcRDU6n4cMGtBklxKD4biYv4LXN8+awc/bbQ2IM2NQHdVPgJ6XumYXfo3hBtErg1DA==",
+ "license": "MIT",
+ "dependencies": {
+ "@next/env": "15.1.3",
+ "@swc/counter": "0.1.3",
+ "@swc/helpers": "0.5.15",
"busboy": "1.6.0",
- "caniuse-lite": "^1.0.30001406",
+ "caniuse-lite": "^1.0.30001579",
"postcss": "8.4.31",
- "styled-jsx": "5.1.1",
- "watchpack": "2.4.0"
+ "styled-jsx": "5.1.6"
},
"bin": {
"next": "dist/bin/next"
},
"engines": {
- "node": ">=16.14.0"
+ "node": "^18.18.0 || ^19.8.0 || >= 20.0.0"
},
"optionalDependencies": {
- "@next/swc-darwin-arm64": "13.5.6",
- "@next/swc-darwin-x64": "13.5.6",
- "@next/swc-linux-arm64-gnu": "13.5.6",
- "@next/swc-linux-arm64-musl": "13.5.6",
- "@next/swc-linux-x64-gnu": "13.5.6",
- "@next/swc-linux-x64-musl": "13.5.6",
- "@next/swc-win32-arm64-msvc": "13.5.6",
- "@next/swc-win32-ia32-msvc": "13.5.6",
- "@next/swc-win32-x64-msvc": "13.5.6"
+ "@next/swc-darwin-arm64": "15.1.3",
+ "@next/swc-darwin-x64": "15.1.3",
+ "@next/swc-linux-arm64-gnu": "15.1.3",
+ "@next/swc-linux-arm64-musl": "15.1.3",
+ "@next/swc-linux-x64-gnu": "15.1.3",
+ "@next/swc-linux-x64-musl": "15.1.3",
+ "@next/swc-win32-arm64-msvc": "15.1.3",
+ "@next/swc-win32-x64-msvc": "15.1.3",
+ "sharp": "^0.33.5"
},
"peerDependencies": {
"@opentelemetry/api": "^1.1.0",
- "react": "^18.2.0",
- "react-dom": "^18.2.0",
+ "@playwright/test": "^1.41.2",
+ "babel-plugin-react-compiler": "*",
+ "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
+ "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0",
"sass": "^1.3.0"
},
"peerDependenciesMeta": {
"@opentelemetry/api": {
"optional": true
},
+ "@playwright/test": {
+ "optional": true
+ },
+ "babel-plugin-react-compiler": {
+ "optional": true
+ },
"sass": {
"optional": true
}
}
},
+ "node_modules/next-auth": {
+ "version": "5.0.0-beta.25",
+ "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-5.0.0-beta.25.tgz",
+ "integrity": "sha512-2dJJw1sHQl2qxCrRk+KTQbeH+izFbGFPuJj5eGgBZFYyiYYtvlrBeUw1E/OJJxTRjuxbSYGnCTkUIRsIIW0bog==",
+ "license": "ISC",
+ "dependencies": {
+ "@auth/core": "0.37.2"
+ },
+ "peerDependencies": {
+ "@simplewebauthn/browser": "^9.0.1",
+ "@simplewebauthn/server": "^9.0.2",
+ "next": "^14.0.0-0 || ^15.0.0-0",
+ "nodemailer": "^6.6.5",
+ "react": "^18.2.0 || ^19.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "@simplewebauthn/browser": {
+ "optional": true
+ },
+ "@simplewebauthn/server": {
+ "optional": true
+ },
+ "nodemailer": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-addon-api": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
+ "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/oauth4webapi": {
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.1.4.tgz",
+ "integrity": "sha512-eVfN3nZNbok2s/ROifO0UAc5G8nRoLSbrcKJ09OqmucgnhXEfdIQOR4gq1eJH1rN3gV7rNw62bDEgftsgFtBEg==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
+ }
+ },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-inspect": {
- "version": "1.13.1",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
- "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
+ "version": "1.13.3",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz",
+ "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==",
"dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -2619,19 +4213,23 @@
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/object.assign": {
- "version": "4.1.4",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
- "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
+ "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.4",
- "has-symbols": "^1.0.3",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0",
+ "has-symbols": "^1.1.0",
"object-keys": "^1.1.1"
},
"engines": {
@@ -2642,28 +4240,31 @@
}
},
"node_modules/object.entries": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz",
- "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==",
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz",
+ "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/object.fromentries": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz",
- "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==",
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz",
+ "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
@@ -2673,39 +4274,31 @@
}
},
"node_modules/object.groupby": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz",
- "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "get-intrinsic": "^1.2.1"
- }
- },
- "node_modules/object.hasown": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz",
- "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz",
+ "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "engines": {
+ "node": ">= 0.4"
}
},
"node_modules/object.values": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz",
- "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz",
+ "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
@@ -2714,37 +4307,48 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "dev": true,
- "dependencies": {
- "wrappy": "1"
- }
- },
"node_modules/optionator": {
- "version": "0.9.3",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
- "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@aashutoshrathi/word-wrap": "^1.2.3",
"deep-is": "^0.1.3",
"fast-levenshtein": "^2.0.6",
"levn": "^0.4.1",
"prelude-ls": "^1.2.1",
- "type-check": "^0.4.0"
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
},
"engines": {
"node": ">= 0.8.0"
}
},
+ "node_modules/own-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
+ "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.2.6",
+ "object-keys": "^1.1.1",
+ "safe-push-apply": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"yocto-queue": "^0.1.0"
},
@@ -2760,6 +4364,7 @@
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"p-limit": "^3.0.2"
},
@@ -2775,6 +4380,7 @@
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"callsites": "^3.0.0"
},
@@ -2787,24 +4393,17 @@
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
},
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -2813,27 +4412,21 @@
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true
- },
- "node_modules/path-type": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
- "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"dev": true,
- "engines": {
- "node": ">=8"
- }
+ "license": "MIT"
},
"node_modules/picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8.6"
},
@@ -2841,6 +4434,16 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/possible-typed-array-names": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
+ "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
"node_modules/postcss": {
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
@@ -2859,6 +4462,7 @@
"url": "https://github.com/sponsors/ai"
}
],
+ "license": "MIT",
"dependencies": {
"nanoid": "^3.3.6",
"picocolors": "^1.0.0",
@@ -2868,31 +4472,68 @@
"node": "^10 || ^12 || >=14"
}
},
+ "node_modules/preact": {
+ "version": "10.11.3",
+ "resolved": "https://registry.npmjs.org/preact/-/preact-10.11.3.tgz",
+ "integrity": "sha512-eY93IVpod/zG3uMF22Unl8h9KkrcKIRs2EGar8hwLZZDU1lkjph303V9HZBwufh2s736U6VXuhD109LYqPoffg==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/preact"
+ }
+ },
+ "node_modules/preact-render-to-string": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-5.2.3.tgz",
+ "integrity": "sha512-aPDxUn5o3GhWdtJtW0svRC2SS/l8D9MAgo2+AWml+BhDImb27ALf04Q2d+AHqUUOc6RdSXFIBVa2gxzgMKgtZA==",
+ "license": "MIT",
+ "dependencies": {
+ "pretty-format": "^3.8.0"
+ },
+ "peerDependencies": {
+ "preact": ">=10"
+ }
+ },
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.8.0"
}
},
+ "node_modules/pretty-format": {
+ "version": "3.8.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz",
+ "integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==",
+ "license": "MIT"
+ },
"node_modules/prop-types": {
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
"react-is": "^16.13.1"
}
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT"
+ },
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6"
}
@@ -2915,49 +4556,82 @@
"type": "consulting",
"url": "https://feross.org/support"
}
- ]
+ ],
+ "license": "MIT"
},
"node_modules/react": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
- "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
- "dependencies": {
- "loose-envify": "^1.1.0"
- },
+ "version": "19.0.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz",
+ "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==",
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-dom": {
- "version": "18.2.0",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
- "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
+ "version": "19.0.0",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz",
+ "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==",
+ "license": "MIT",
"dependencies": {
- "loose-envify": "^1.1.0",
- "scheduler": "^0.23.0"
+ "scheduler": "^0.25.0"
+ },
+ "peerDependencies": {
+ "react": "^19.0.0"
+ }
+ },
+ "node_modules/react-hook-form": {
+ "version": "7.54.2",
+ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.54.2.tgz",
+ "integrity": "sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/react-hook-form"
},
"peerDependencies": {
- "react": "^18.2.0"
+ "react": "^16.8.0 || ^17 || ^18 || ^19"
}
},
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/readdirp": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz",
+ "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14.16.0"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
},
"node_modules/reflect.getprototypeof": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz",
- "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==",
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
+ "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "get-intrinsic": "^1.2.1",
- "globalthis": "^1.0.3",
- "which-builtin-type": "^1.1.3"
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.9",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.7",
+ "get-proto": "^1.0.1",
+ "which-builtin-type": "^1.2.1"
},
"engines": {
"node": ">= 0.4"
@@ -2966,21 +4640,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/regenerator-runtime": {
- "version": "0.14.0",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz",
- "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==",
- "dev": true
- },
"node_modules/regexp.prototype.flags": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz",
- "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==",
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
+ "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "set-function-name": "^2.0.0"
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-errors": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "set-function-name": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -2990,18 +4662,22 @@
}
},
"node_modules/resolve": {
- "version": "1.22.8",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
- "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "version": "1.22.10",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
+ "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-core-module": "^2.13.0",
+ "is-core-module": "^2.16.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
"bin": {
"resolve": "bin/resolve"
},
+ "engines": {
+ "node": ">= 0.4"
+ },
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -3011,6 +4687,7 @@
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=4"
}
@@ -3020,6 +4697,7 @@
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
"dev": true,
+ "license": "MIT",
"funding": {
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
}
@@ -3029,26 +4707,12 @@
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
"dev": true,
+ "license": "MIT",
"engines": {
"iojs": ">=1.0.0",
"node": ">=0.10.0"
}
},
- "node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "dev": true,
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -3068,19 +4732,22 @@
"url": "https://feross.org/support"
}
],
+ "license": "MIT",
"dependencies": {
"queue-microtask": "^1.2.2"
}
},
"node_modules/safe-array-concat": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz",
- "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==",
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz",
+ "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.1",
- "has-symbols": "^1.0.3",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "get-intrinsic": "^1.2.6",
+ "has-symbols": "^1.1.0",
"isarray": "^2.0.5"
},
"engines": {
@@ -3090,36 +4757,74 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/safe-regex-test": {
+ "node_modules/safe-push-apply": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz",
- "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==",
+ "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
+ "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.3",
- "is-regex": "^1.1.4"
+ "es-errors": "^1.3.0",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/scheduler": {
- "version": "0.23.0",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
- "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
+ "node_modules/safe-regex-test": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
+ "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "loose-envify": "^1.1.0"
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-regex": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/semver": {
- "version": "7.5.4",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
- "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
- "dev": true,
+ "node_modules/sass": {
+ "version": "1.83.1",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.83.1.tgz",
+ "integrity": "sha512-EVJbDaEs4Rr3F0glJzFSOvtg2/oy2V/YrGFPqPY24UqcLDWcI9ZY5sN+qyO3c/QCZwzgfirvhXvINiJCE/OLcA==",
+ "devOptional": true,
+ "license": "MIT",
"dependencies": {
- "lru-cache": "^6.0.0"
+ "chokidar": "^4.0.0",
+ "immutable": "^5.0.2",
+ "source-map-js": ">=0.6.2 <2.0.0"
+ },
+ "bin": {
+ "sass": "sass.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
},
+ "optionalDependencies": {
+ "@parcel/watcher": "^2.4.1"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.25.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz",
+ "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==",
+ "license": "MIT"
+ },
+ "node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "devOptional": true,
+ "license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
@@ -3128,39 +4833,100 @@
}
},
"node_modules/set-function-length": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz",
- "integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==",
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "define-data-property": "^1.1.1",
- "get-intrinsic": "^1.2.1",
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
"gopd": "^1.0.1",
- "has-property-descriptors": "^1.0.0"
+ "has-property-descriptors": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/set-function-name": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz",
- "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
+ "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "define-data-property": "^1.0.1",
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
"functions-have-names": "^1.2.3",
- "has-property-descriptors": "^1.0.0"
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-proto": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
+ "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
+ "node_modules/sharp": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz",
+ "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "color": "^4.2.3",
+ "detect-libc": "^2.0.3",
+ "semver": "^7.6.3"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-darwin-arm64": "0.33.5",
+ "@img/sharp-darwin-x64": "0.33.5",
+ "@img/sharp-libvips-darwin-arm64": "1.0.4",
+ "@img/sharp-libvips-darwin-x64": "1.0.4",
+ "@img/sharp-libvips-linux-arm": "1.0.5",
+ "@img/sharp-libvips-linux-arm64": "1.0.4",
+ "@img/sharp-libvips-linux-s390x": "1.0.4",
+ "@img/sharp-libvips-linux-x64": "1.0.4",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.0.4",
+ "@img/sharp-libvips-linuxmusl-x64": "1.0.4",
+ "@img/sharp-linux-arm": "0.33.5",
+ "@img/sharp-linux-arm64": "0.33.5",
+ "@img/sharp-linux-s390x": "0.33.5",
+ "@img/sharp-linux-x64": "0.33.5",
+ "@img/sharp-linuxmusl-arm64": "0.33.5",
+ "@img/sharp-linuxmusl-x64": "0.33.5",
+ "@img/sharp-wasm32": "0.33.5",
+ "@img/sharp-win32-ia32": "0.33.5",
+ "@img/sharp-win32-x64": "0.33.5"
+ }
+ },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"shebang-regex": "^3.0.0"
},
@@ -3173,41 +4939,113 @@
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/side-channel": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
- "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.0",
- "get-intrinsic": "^1.0.2",
- "object-inspect": "^1.9.0"
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3",
+ "side-channel-list": "^1.0.0",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/slash": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
- "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "node_modules/side-channel-list": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
+ "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3"
+ },
"engines": {
- "node": ">=8"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/source-map-js": {
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-weakmap": {
"version": "1.0.2",
- "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
- "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/simple-swizzle": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+ "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "is-arrayish": "^0.3.1"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
+ "node_modules/stable-hash": {
+ "version": "0.0.4",
+ "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz",
+ "integrity": "sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/streamsearch": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
@@ -3216,35 +5054,41 @@
"node": ">=10.0.0"
}
},
- "node_modules/string.prototype.matchall": {
- "version": "4.0.10",
- "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz",
- "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==",
+ "node_modules/string.prototype.includes": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz",
+ "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "get-intrinsic": "^1.2.1",
- "has-symbols": "^1.0.3",
- "internal-slot": "^1.0.5",
- "regexp.prototype.flags": "^1.5.0",
- "set-function-name": "^2.0.0",
- "side-channel": "^1.0.4"
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.3"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "engines": {
+ "node": ">= 0.4"
}
},
- "node_modules/string.prototype.trim": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz",
- "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==",
+ "node_modules/string.prototype.matchall": {
+ "version": "4.0.12",
+ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz",
+ "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.6",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.6",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "internal-slot": "^1.1.0",
+ "regexp.prototype.flags": "^1.5.3",
+ "set-function-name": "^2.0.2",
+ "side-channel": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
@@ -3253,44 +5097,74 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/string.prototype.trimend": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz",
- "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==",
+ "node_modules/string.prototype.repeat": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz",
+ "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.10",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
+ "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "define-data-property": "^1.1.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-object-atoms": "^1.0.0",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/string.prototype.trimstart": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz",
- "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==",
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz",
+ "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1"
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
+ "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ansi-regex": "^5.0.1"
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
},
"engines": {
- "node": ">=8"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/strip-bom": {
@@ -3298,6 +5172,7 @@
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
"integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=4"
}
@@ -3307,6 +5182,7 @@
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
},
@@ -3315,9 +5191,10 @@
}
},
"node_modules/styled-jsx": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz",
- "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==",
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz",
+ "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==",
+ "license": "MIT",
"dependencies": {
"client-only": "0.0.1"
},
@@ -3325,7 +5202,7 @@
"node": ">= 12.0.0"
},
"peerDependencies": {
- "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0"
+ "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0"
},
"peerDependenciesMeta": {
"@babel/core": {
@@ -3341,6 +5218,7 @@
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -3353,6 +5231,7 @@
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -3365,21 +5244,17 @@
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
"integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6"
}
},
- "node_modules/text-table": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
- "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
- "dev": true
- },
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
},
@@ -3388,22 +5263,24 @@
}
},
"node_modules/ts-api-utils": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz",
- "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==",
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz",
+ "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=16.13.0"
+ "node": ">=16"
},
"peerDependencies": {
"typescript": ">=4.2.0"
}
},
"node_modules/tsconfig-paths": {
- "version": "3.14.2",
- "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz",
- "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==",
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
+ "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@types/json5": "^0.0.29",
"json5": "^1.0.2",
@@ -3412,15 +5289,17 @@
}
},
"node_modules/tslib": {
- "version": "2.6.2",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
- "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
},
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"prelude-ls": "^1.2.1"
},
@@ -3428,42 +5307,33 @@
"node": ">= 0.8.0"
}
},
- "node_modules/type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/typed-array-buffer": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz",
- "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
+ "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.2.1",
- "is-typed-array": "^1.1.10"
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-typed-array": "^1.1.14"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/typed-array-byte-length": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz",
- "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==",
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz",
+ "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
+ "call-bind": "^1.0.8",
"for-each": "^0.3.3",
- "has-proto": "^1.0.1",
- "is-typed-array": "^1.1.10"
+ "gopd": "^1.2.0",
+ "has-proto": "^1.2.0",
+ "is-typed-array": "^1.1.14"
},
"engines": {
"node": ">= 0.4"
@@ -3473,16 +5343,19 @@
}
},
"node_modules/typed-array-byte-offset": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz",
- "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==",
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz",
+ "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.2",
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
"for-each": "^0.3.3",
- "has-proto": "^1.0.1",
- "is-typed-array": "^1.1.10"
+ "gopd": "^1.2.0",
+ "has-proto": "^1.2.0",
+ "is-typed-array": "^1.1.15",
+ "reflect.getprototypeof": "^1.0.9"
},
"engines": {
"node": ">= 0.4"
@@ -3492,24 +5365,32 @@
}
},
"node_modules/typed-array-length": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz",
- "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz",
+ "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
+ "call-bind": "^1.0.7",
"for-each": "^0.3.3",
- "is-typed-array": "^1.1.9"
+ "gopd": "^1.0.1",
+ "is-typed-array": "^1.1.13",
+ "possible-typed-array-names": "^1.0.0",
+ "reflect.getprototypeof": "^1.0.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/typescript": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.2.tgz",
- "integrity": "sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ==",
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz",
+ "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==",
"dev": true,
+ "license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -3519,52 +5400,47 @@
}
},
"node_modules/unbox-primitive": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
- "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
+ "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
+ "call-bound": "^1.0.3",
"has-bigints": "^1.0.2",
- "has-symbols": "^1.0.3",
- "which-boxed-primitive": "^1.0.2"
+ "has-symbols": "^1.1.0",
+ "which-boxed-primitive": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/undici-types": {
- "version": "5.26.5",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
- "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
- "dev": true
+ "version": "6.19.8",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
+ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"punycode": "^2.1.0"
}
},
- "node_modules/watchpack": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
- "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==",
- "dependencies": {
- "glob-to-regexp": "^0.4.1",
- "graceful-fs": "^4.1.2"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"isexe": "^2.0.0"
},
@@ -3576,39 +5452,45 @@
}
},
"node_modules/which-boxed-primitive": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
- "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
+ "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-bigint": "^1.0.1",
- "is-boolean-object": "^1.1.0",
- "is-number-object": "^1.0.4",
- "is-string": "^1.0.5",
- "is-symbol": "^1.0.3"
+ "is-bigint": "^1.1.0",
+ "is-boolean-object": "^1.2.1",
+ "is-number-object": "^1.1.1",
+ "is-string": "^1.1.1",
+ "is-symbol": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/which-builtin-type": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz",
- "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz",
+ "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "function.prototype.name": "^1.1.5",
- "has-tostringtag": "^1.0.0",
+ "call-bound": "^1.0.2",
+ "function.prototype.name": "^1.1.6",
+ "has-tostringtag": "^1.0.2",
"is-async-function": "^2.0.0",
- "is-date-object": "^1.0.5",
- "is-finalizationregistry": "^1.0.2",
+ "is-date-object": "^1.1.0",
+ "is-finalizationregistry": "^1.1.0",
"is-generator-function": "^1.0.10",
- "is-regex": "^1.1.4",
+ "is-regex": "^1.2.1",
"is-weakref": "^1.0.2",
"isarray": "^2.0.5",
- "which-boxed-primitive": "^1.0.2",
- "which-collection": "^1.0.1",
- "which-typed-array": "^1.1.9"
+ "which-boxed-primitive": "^1.1.0",
+ "which-collection": "^1.0.2",
+ "which-typed-array": "^1.1.16"
},
"engines": {
"node": ">= 0.4"
@@ -3618,31 +5500,37 @@
}
},
"node_modules/which-collection": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
- "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
+ "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-map": "^2.0.1",
- "is-set": "^2.0.1",
- "is-weakmap": "^2.0.1",
- "is-weakset": "^2.0.1"
+ "is-map": "^2.0.3",
+ "is-set": "^2.0.3",
+ "is-weakmap": "^2.0.2",
+ "is-weakset": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/which-typed-array": {
- "version": "1.1.13",
- "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz",
- "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==",
+ "version": "1.1.18",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz",
+ "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "available-typed-arrays": "^1.0.5",
- "call-bind": "^1.0.4",
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
"for-each": "^0.3.3",
- "gopd": "^1.0.1",
- "has-tostringtag": "^1.0.0"
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
@@ -3651,29 +5539,37 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "dev": true
- },
- "node_modules/yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
},
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
+ },
+ "node_modules/zod": {
+ "version": "3.24.1",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz",
+ "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
}
}
}
diff --git a/package.json b/package.json
index 1ce24924f..0320aea9a 100644
--- a/package.json
+++ b/package.json
@@ -1,5 +1,5 @@
{
- "name": "fe-weekly-mission",
+ "name": "next",
"version": "0.1.0",
"private": true,
"scripts": {
@@ -9,16 +9,27 @@
"lint": "next lint"
},
"dependencies": {
- "react": "^18",
- "react-dom": "^18",
- "next": "13.5.6"
+ "@hookform/resolvers": "^3.9.1",
+ "axios": "^1.7.8",
+ "clsx": "^2.1.1",
+ "dayjs": "^1.11.13",
+ "jwt-decode": "^4.0.0",
+ "lodash": "^4.17.21",
+ "next": "15.1.3",
+ "next-auth": "^5.0.0-beta.25",
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0",
+ "react-hook-form": "^7.54.2",
+ "zod": "^3.24.1"
},
"devDependencies": {
- "typescript": "^5",
+ "@eslint/eslintrc": "^3",
"@types/node": "^20",
- "@types/react": "^18",
- "@types/react-dom": "^18",
- "eslint": "^8",
- "eslint-config-next": "13.5.6"
+ "@types/react": "^19",
+ "@types/react-dom": "^19",
+ "eslint": "^9",
+ "eslint-config-next": "15.1.3",
+ "sass": "^1.83.1",
+ "typescript": "^5"
}
}
diff --git a/pages/_app.tsx b/pages/_app.tsx
deleted file mode 100644
index 021681f4d..000000000
--- a/pages/_app.tsx
+++ /dev/null
@@ -1,6 +0,0 @@
-import '@/styles/globals.css'
-import type { AppProps } from 'next/app'
-
-export default function App({ Component, pageProps }: AppProps) {
- return
-}
diff --git a/pages/_document.tsx b/pages/_document.tsx
deleted file mode 100644
index 54e8bf3e2..000000000
--- a/pages/_document.tsx
+++ /dev/null
@@ -1,13 +0,0 @@
-import { Html, Head, Main, NextScript } from 'next/document'
-
-export default function Document() {
- return (
-
-
-
-
-
-
- )
-}
diff --git a/pages/api/hello.ts b/pages/api/hello.ts
deleted file mode 100644
index f8bcc7e5c..000000000
--- a/pages/api/hello.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
-import type { NextApiRequest, NextApiResponse } from 'next'
-
-type Data = {
- name: string
-}
-
-export default function handler(
- req: NextApiRequest,
- res: NextApiResponse
-) {
- res.status(200).json({ name: 'John Doe' })
-}
diff --git a/pages/index.tsx b/pages/index.tsx
deleted file mode 100644
index 02c4dee04..000000000
--- a/pages/index.tsx
+++ /dev/null
@@ -1,114 +0,0 @@
-import Head from 'next/head'
-import Image from 'next/image'
-import { Inter } from 'next/font/google'
-import styles from '@/styles/Home.module.css'
-
-const inter = Inter({ subsets: ['latin'] })
-
-export default function Home() {
- return (
- <>
-
- Create Next App
-
-
-
-
-
-
-
- Get started by editing
- pages/index.tsx
-
-
-
-
-
-
-
-
-
-
- >
- )
-}
diff --git a/public/favicon.ico b/public/favicon.ico
deleted file mode 100644
index 718d6fea4..000000000
Binary files a/public/favicon.ico and /dev/null differ
diff --git a/public/next.svg b/public/next.svg
deleted file mode 100644
index 5174b28c5..000000000
--- a/public/next.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/robots.txt b/public/robots.txt
new file mode 100644
index 000000000..c2a49f4fb
--- /dev/null
+++ b/public/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+Allow: /
diff --git a/public/vercel.svg b/public/vercel.svg
deleted file mode 100644
index d2f842227..000000000
--- a/public/vercel.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/src/app/(auth)/_components/AuthContainer.module.scss b/src/app/(auth)/_components/AuthContainer.module.scss
new file mode 100644
index 000000000..669f5da65
--- /dev/null
+++ b/src/app/(auth)/_components/AuthContainer.module.scss
@@ -0,0 +1,57 @@
+@use "@assets/scss/base/mixins";
+
+.auth-container {
+ max-width: calc(64rem + var(--gutter) * 2);
+ margin: 0 auto;
+ padding: 12rem var(--gutter);
+
+ @include mixins.mobile {
+ max-width: calc(40rem + var(--gutter) * 2);
+ padding: 8rem var(--gutter);
+ }
+
+ .auth-header {
+ margin-bottom: 4rem;
+ text-align: center;
+
+ @include mixins.mobile {
+ margin-bottom: 2.4rem;
+ }
+
+ .auth-logo {
+ a {
+ display: inline-block;
+ height: 13.2rem;
+
+ @include mixins.mobile {
+ height: 6.6rem;
+ }
+ }
+
+ img {
+ width: auto;
+ height: 100%;
+ }
+ }
+ }
+
+ .auth-body {
+ margin-bottom: 2.4rem;
+ }
+
+ .error {
+ padding: 2rem 0 1rem;
+ color: var(--color-error-100);
+ text-align: center;
+ }
+}
+
+.auth-options {
+ text-align: center;
+ font-size: 1.4rem;
+
+ a {
+ color: var(--color-primary-100);
+ text-decoration: underline;
+ }
+}
diff --git a/src/app/(auth)/_components/AuthContainer.tsx b/src/app/(auth)/_components/AuthContainer.tsx
new file mode 100644
index 000000000..16a1d4302
--- /dev/null
+++ b/src/app/(auth)/_components/AuthContainer.tsx
@@ -0,0 +1,45 @@
+import { ReactNode } from "react";
+import Link from "next/link";
+import Image from "next/image";
+import logo from "@assets/img/common/logo_full.svg";
+import Oauth from "./Oauth";
+import styles from "./AuthContainer.module.scss";
+
+interface AuthContainerProps {
+ children: ReactNode;
+ mode?: "login" | "signup";
+}
+
+export default function AuthContainer({
+ children,
+ mode = "login",
+}: AuthContainerProps) {
+ return (
+ <>
+
+
+
{children}
+
+
+
+ {mode === "login" ? (
+ <>
+ 판다마켓이 처음이신가요? 회원가입
+ >
+ ) : (
+ <>
+ 이미 회원이신가요? 로그인
+ >
+ )}
+
+
+
+ >
+ );
+}
diff --git a/src/app/(auth)/_components/LoginForm.tsx b/src/app/(auth)/_components/LoginForm.tsx
new file mode 100644
index 000000000..22700608d
--- /dev/null
+++ b/src/app/(auth)/_components/LoginForm.tsx
@@ -0,0 +1,86 @@
+"use client";
+
+import { useRouter } from "next/navigation";
+import { Form, FieldItem, Input } from "@components/Field";
+import { Button } from "@components/ui";
+import useFormWithError from "@hooks/useFormWithError";
+import { zodResolver } from "@hookform/resolvers/zod";
+import { signinFormSchmea, SigninFormType } from "@schemas/auth";
+import { FieldAdapter } from "@components/adaptor/rhf";
+import { signIn } from "next-auth/react";
+
+export default function LoginForm() {
+ const router = useRouter();
+
+ const {
+ control,
+ formError,
+ handleSubmit,
+ formState: { isSubmitting, isValid },
+ } = useFormWithError({
+ mode: "onBlur",
+ resolver: zodResolver(signinFormSchmea),
+ defaultValues: {
+ email: "",
+ password: "",
+ },
+ });
+
+ async function onSubmit(data: SigninFormType) {
+ try {
+ const respone = await signIn("credentials", {
+ redirect: false,
+ ...data,
+ });
+
+ if (respone?.error) {
+ throw new Error(respone?.code);
+ }
+
+ alert("로그인에 성공했습니다.");
+ router.replace("/items");
+ } catch (err) {
+ throw err;
+ }
+ }
+
+ return (
+
+ );
+}
diff --git a/src/app/(auth)/_components/Oauth.module.scss b/src/app/(auth)/_components/Oauth.module.scss
new file mode 100644
index 000000000..c5819be1e
--- /dev/null
+++ b/src/app/(auth)/_components/Oauth.module.scss
@@ -0,0 +1,31 @@
+.oauth-container {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: 2.4rem;
+ padding: 1.6rem 2.3rem;
+ border-radius: 8px;
+ background: #e6f2ff;
+
+ .oauth-label {
+ font-weight: 500;
+ }
+
+ .oauth-providers {
+ display: flex;
+ align-items: center;
+ gap: 1.6rem;
+
+ .oauth-provider {
+ display: block;
+ width: 4.2rem;
+ height: 4.2rem;
+ border-radius: 50%;
+
+ img {
+ width: 100%;
+ height: auto;
+ }
+ }
+ }
+}
diff --git a/src/app/(auth)/_components/Oauth.tsx b/src/app/(auth)/_components/Oauth.tsx
new file mode 100644
index 000000000..df5b10f1f
--- /dev/null
+++ b/src/app/(auth)/_components/Oauth.tsx
@@ -0,0 +1,38 @@
+import Image from "next/image";
+import googleIcon from "@assets/img/icon/icon_google.svg";
+import kakaoIcon from "@assets/img/icon/icon_kakao.svg";
+import styles from "./Oauth.module.scss";
+
+export default function Oauth() {
+ return (
+
+ );
+}
diff --git a/src/app/(auth)/_components/SignupForm.tsx b/src/app/(auth)/_components/SignupForm.tsx
new file mode 100644
index 000000000..d6a9c1504
--- /dev/null
+++ b/src/app/(auth)/_components/SignupForm.tsx
@@ -0,0 +1,106 @@
+"use client";
+
+import { useRouter } from "next/navigation";
+import { Form, FieldItem, Input } from "@components/Field";
+import { Button } from "@components/ui";
+import useFormWithError from "@hooks/useFormWithError";
+import { zodResolver } from "@hookform/resolvers/zod";
+import { signupFormSchema, SignupFormType } from "@schemas/auth";
+import { FieldAdapter } from "@components/adaptor/rhf";
+import { signUp } from "@/service/auth";
+
+export default function SignupForm() {
+ const router = useRouter();
+
+ const {
+ control,
+ formError,
+ handleSubmit,
+ formState: { isSubmitting, isValid },
+ } = useFormWithError({
+ mode: "onBlur",
+ resolver: zodResolver(signupFormSchema),
+ defaultValues: {
+ email: "",
+ nickname: "",
+ password: "",
+ passwordConfirmation: "",
+ },
+ });
+
+ async function onSubmit(data: SignupFormType) {
+ try {
+ await signUp(data);
+ alert("회원가입에 성공했습니다. \n로그인 페이지로 이동합니다.");
+ router.replace("/login");
+ } catch (err) {
+ throw err;
+ }
+ }
+
+ return (
+
+ );
+}
diff --git a/src/app/(auth)/layout.tsx b/src/app/(auth)/layout.tsx
new file mode 100644
index 000000000..4aa691d75
--- /dev/null
+++ b/src/app/(auth)/layout.tsx
@@ -0,0 +1,9 @@
+import { PropsWithChildren } from "react";
+
+export default function Layout({ children }: PropsWithChildren) {
+ return (
+ <>
+ {children}
+ >
+ );
+}
diff --git a/src/app/(auth)/login/page.tsx b/src/app/(auth)/login/page.tsx
new file mode 100644
index 000000000..070ca13a5
--- /dev/null
+++ b/src/app/(auth)/login/page.tsx
@@ -0,0 +1,18 @@
+import { redirect } from "next/navigation";
+import AuthContainer from "../_components/AuthContainer";
+import LoginForm from "../_components/LoginForm";
+import { auth } from "@/auth";
+
+export default async function LoginPage() {
+ const session = await auth();
+
+ if (session) {
+ redirect("/");
+ }
+
+ return (
+
+
+
+ );
+}
diff --git a/src/app/(auth)/signup/page.tsx b/src/app/(auth)/signup/page.tsx
new file mode 100644
index 000000000..699b27944
--- /dev/null
+++ b/src/app/(auth)/signup/page.tsx
@@ -0,0 +1,18 @@
+import { redirect } from "next/navigation";
+import AuthContainer from "../_components/AuthContainer";
+import SignupForm from "../_components/SignupForm";
+import { auth } from "@/auth";
+
+export default async function SignupPage() {
+ const session = await auth();
+
+ if (session) {
+ redirect("/");
+ }
+
+ return (
+
+
+
+ );
+}
diff --git a/src/app/(common)/(board)/addBoard/page.tsx b/src/app/(common)/(board)/addBoard/page.tsx
new file mode 100644
index 000000000..b46d02b4a
--- /dev/null
+++ b/src/app/(common)/(board)/addBoard/page.tsx
@@ -0,0 +1,5 @@
+import { Temporary } from "@/components/ui";
+
+export default function AddBoardPage() {
+ return ;
+}
diff --git a/src/app/(common)/(board)/boards/(lists)/@all/loading.tsx b/src/app/(common)/(board)/boards/(lists)/@all/loading.tsx
new file mode 100644
index 000000000..1c8669b09
--- /dev/null
+++ b/src/app/(common)/(board)/boards/(lists)/@all/loading.tsx
@@ -0,0 +1,5 @@
+import { Message } from "@/components/ui";
+
+export default function Loading() {
+ return 게시물 가져오는중...;
+}
diff --git a/src/app/(common)/(board)/boards/(lists)/@all/page.tsx b/src/app/(common)/(board)/boards/(lists)/@all/page.tsx
new file mode 100644
index 000000000..fd5cd8d8a
--- /dev/null
+++ b/src/app/(common)/(board)/boards/(lists)/@all/page.tsx
@@ -0,0 +1,32 @@
+import { getArticles } from "@/service/article";
+import { Section } from "@/components/Section";
+import BoardList from "../_components/BoardList";
+import BoardFilter from "../_components/BoardFilter";
+
+type ItemsPageQueryParams = {
+ page?: string;
+ orderBy?: string;
+ keyword?: string;
+};
+export default async function AllListPage({
+ searchParams,
+}: {
+ searchParams: Promise;
+}) {
+ const { page, orderBy, keyword } = await searchParams;
+ const data = await getArticles({
+ page: Number(page) || 1,
+ orderBy: orderBy || "recent",
+ keyword: keyword || "",
+ });
+
+ return (
+
+ );
+}
diff --git a/src/app/(common)/(board)/boards/(lists)/@best/loading.tsx b/src/app/(common)/(board)/boards/(lists)/@best/loading.tsx
new file mode 100644
index 000000000..c750861a2
--- /dev/null
+++ b/src/app/(common)/(board)/boards/(lists)/@best/loading.tsx
@@ -0,0 +1,5 @@
+import { Message } from "@/components/ui";
+
+export default function Loading() {
+ return 베스트 게시물 가져오는중...;
+}
diff --git a/src/app/(common)/(board)/boards/(lists)/@best/page.tsx b/src/app/(common)/(board)/boards/(lists)/@best/page.tsx
new file mode 100644
index 000000000..e6428ce99
--- /dev/null
+++ b/src/app/(common)/(board)/boards/(lists)/@best/page.tsx
@@ -0,0 +1,28 @@
+import { getArticles } from "@/service/article";
+import { Section } from "@/components/Section";
+import BestList from "../_components/BestList";
+
+type BestItemsPageQueryParams = {
+ bestPageSize?: string;
+};
+
+export default async function BestListPage({
+ searchParams,
+}: {
+ searchParams: Promise;
+}) {
+ const { bestPageSize } = await searchParams;
+ const data = await getArticles({
+ orderBy: "like",
+ pageSize: Number(bestPageSize) || 3,
+ });
+
+ return (
+
+ );
+}
diff --git a/src/app/(common)/(board)/boards/(lists)/_components/BestItem.module.scss b/src/app/(common)/(board)/boards/(lists)/_components/BestItem.module.scss
new file mode 100644
index 000000000..5d2a3e033
--- /dev/null
+++ b/src/app/(common)/(board)/boards/(lists)/_components/BestItem.module.scss
@@ -0,0 +1,55 @@
+.item {
+ display: block;
+ background: var(--color-secondary-100);
+ padding: 0 2.4rem 1.6rem;
+ border-radius: 0.8rem;
+ transition: transform 0.2s;
+}
+
+.item:hover {
+ transform: translateY(-4px);
+}
+
+.status {
+ margin-bottom: 1.6rem;
+}
+
+.header {
+ display: flex;
+ gap: 0.8rem;
+ margin-bottom: 1.6rem;
+}
+
+.content {
+ flex: 1;
+ min-width: 0;
+}
+
+.title {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: -webkit-box;
+ -webkit-line-clamp: 3;
+ -webkit-box-orient: vertical;
+ font-size: 2rem;
+ font-weight: 600;
+}
+
+.title:hover {
+ text-decoration: underline;
+}
+
+.thumbnail {
+ width: 7.2rem;
+}
+
+.meta {
+ display: flex;
+ align-items: center;
+ gap: 0.8rem;
+}
+
+.date {
+ flex: none;
+ margin-left: auto;
+}
diff --git a/src/app/(common)/(board)/boards/(lists)/_components/BestItem.tsx b/src/app/(common)/(board)/boards/(lists)/_components/BestItem.tsx
new file mode 100644
index 000000000..3d93ae55a
--- /dev/null
+++ b/src/app/(common)/(board)/boards/(lists)/_components/BestItem.tsx
@@ -0,0 +1,41 @@
+import Link from "next/link";
+import Image from "next/image";
+import { Article } from "@/types/article";
+import { Author, Badge, Date, Like, Thumbnail } from "@/components/ui";
+import bestIcon from "@assets/img/icon/icon_best.svg";
+import styles from "./BestItem.module.scss";
+
+export default function BestItem({ data }: { data: Article }) {
+ const { likeCount, writer, image, title, updatedAt, id } = data;
+ const thumbnailImage = image || undefined;
+
+ return (
+
+
+ } />
+
+
+
+
+ );
+}
diff --git a/src/app/(common)/(board)/boards/(lists)/_components/BestList.tsx b/src/app/(common)/(board)/boards/(lists)/_components/BestList.tsx
new file mode 100644
index 000000000..2a50356f4
--- /dev/null
+++ b/src/app/(common)/(board)/boards/(lists)/_components/BestList.tsx
@@ -0,0 +1,38 @@
+"use client";
+
+import { useEffect } from "react";
+import useResponsive from "@/hooks/useResponsive";
+import useParams from "@/hooks/useParams";
+import { PaginationResponse } from "@/types/common";
+import { Article } from "@/types/article";
+import BoardListWrapper from "./BoardListWrapper";
+import BestItem from "./BestItem";
+
+interface BestListProps {
+ data: PaginationResponse;
+}
+
+export default function BestList({ data }: BestListProps) {
+ const { searchParams, handleParams } = useParams();
+ const currentSize = Number(searchParams.get("bestPageSize")) || 3;
+ const pageSize = useResponsive({
+ pc: 3,
+ tablet: 2,
+ mobile: 1,
+ });
+ const { list } = data;
+
+ useEffect(() => {
+ if (pageSize === currentSize) return;
+
+ handleParams({ bestPageSize: pageSize });
+ }, [pageSize, currentSize, handleParams]);
+
+ return (
+ <>
+
+ {(item) => }
+
+ >
+ );
+}
diff --git a/src/app/(common)/(board)/boards/(lists)/_components/BoardFilter.module.scss b/src/app/(common)/(board)/boards/(lists)/_components/BoardFilter.module.scss
new file mode 100644
index 000000000..dad32ad60
--- /dev/null
+++ b/src/app/(common)/(board)/boards/(lists)/_components/BoardFilter.module.scss
@@ -0,0 +1,9 @@
+.filter {
+ display: flex;
+ gap: 1.6rem;
+ margin-bottom: 2.4rem;
+}
+
+.keyword {
+ flex: 1;
+}
diff --git a/src/app/(common)/(board)/boards/(lists)/_components/BoardFilter.tsx b/src/app/(common)/(board)/boards/(lists)/_components/BoardFilter.tsx
new file mode 100644
index 000000000..be67de824
--- /dev/null
+++ b/src/app/(common)/(board)/boards/(lists)/_components/BoardFilter.tsx
@@ -0,0 +1,65 @@
+"use client";
+
+import useParams from "@/hooks/useParams";
+import { Recent, Search } from "@/components/Search";
+import { Select } from "@/components/ui";
+import styles from "./BoardFilter.module.scss";
+import useRecentSearch from "@/hooks/useRecentSearch";
+
+export default function BoardFilter() {
+ const { searchParams, handleParams } = useParams();
+
+ const keyword = searchParams.get("keyword") || "";
+ const orderBy = searchParams.get("orderBy") || "recent";
+
+ const {
+ searchInput,
+ recentSearch,
+ handleSearchSubmit,
+ handleSearchChange,
+ handleSearchClear,
+ handleRecentSearchClick,
+ handleRecentSearchRemove,
+ handleRecentSearchClear,
+ } = useRecentSearch({ initialKeyword: keyword, onChange: handleSearch });
+
+ function handleSearch(keyword: string) {
+ handleParams({ keyword, page: 1 });
+ }
+
+ function handleOrderBy(orderBy: string) {
+ handleParams({ orderBy, page: 1 });
+ }
+
+ return (
+
+ );
+}
diff --git a/src/app/(common)/(board)/boards/(lists)/_components/BoardItem.module.scss b/src/app/(common)/(board)/boards/(lists)/_components/BoardItem.module.scss
new file mode 100644
index 000000000..b6e586d8a
--- /dev/null
+++ b/src/app/(common)/(board)/boards/(lists)/_components/BoardItem.module.scss
@@ -0,0 +1,48 @@
+@use "@assets/scss/base/mixins";
+
+.item {
+ padding: 1rem 1rem 2.4rem;
+ border-bottom: 1px solid var(--color-secondary-200);
+}
+
+.header {
+ display: flex;
+ gap: 0.8rem;
+ margin-bottom: 1.6rem;
+}
+
+.content {
+ flex: 1;
+ min-width: 0;
+}
+
+.title {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ display: -webkit-box;
+ -webkit-line-clamp: 3;
+ -webkit-box-orient: vertical;
+ font-size: 2rem;
+ font-weight: 600;
+}
+
+.title:hover {
+ text-decoration: underline;
+}
+
+.thumbnail {
+ width: 7.2rem;
+}
+
+.meta {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 0.8rem;
+}
+
+@include mixins.mobile {
+ .title {
+ font-size: 1.8rem;
+ }
+}
diff --git a/src/app/(common)/(board)/boards/(lists)/_components/BoardItem.tsx b/src/app/(common)/(board)/boards/(lists)/_components/BoardItem.tsx
new file mode 100644
index 000000000..3c9b79575
--- /dev/null
+++ b/src/app/(common)/(board)/boards/(lists)/_components/BoardItem.tsx
@@ -0,0 +1,30 @@
+import Link from "next/link";
+import { Article } from "@/types/article";
+import { Author, Like, Thumbnail } from "@/components/ui";
+import styles from "./BoardItem.module.scss";
+
+export default function BoardItem({ data }: { data: Article }) {
+ const { likeCount, writer, image, title, updatedAt, id } = data;
+ const thumbnailImage = image || undefined;
+
+ return (
+
+
+
+
+
{title}
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/app/(common)/(board)/boards/(lists)/_components/BoardList.tsx b/src/app/(common)/(board)/boards/(lists)/_components/BoardList.tsx
new file mode 100644
index 000000000..69ffa085d
--- /dev/null
+++ b/src/app/(common)/(board)/boards/(lists)/_components/BoardList.tsx
@@ -0,0 +1,50 @@
+"use client";
+
+import useParams from "@/hooks/useParams";
+import usePagination from "@/hooks/usePagination";
+import { PaginationResponse } from "@/types/common";
+import { Article } from "@/types/article";
+import { Pagination } from "@/components/Pagination";
+import { Message } from "@/components/ui";
+import BoardItem from "./BoardItem";
+import BoardListWrapper from "./BoardListWrapper";
+
+interface BoardListProps {
+ data: PaginationResponse;
+}
+export default function BoardList({ data }: BoardListProps) {
+ const { searchParams, handleParams } = useParams();
+ const page = Number(searchParams.get("page")) || 1;
+ const pageSize = Number(searchParams.get("pageSize")) || 10;
+ const keyword = searchParams.get("keyword") || "";
+ const visibleCount = 5;
+ const { list, totalCount } = data;
+
+ const pagination = usePagination({
+ page,
+ pageSize,
+ totalCount,
+ visibleCount,
+ onChange: (pageNumber) => {
+ handleParams({ page: pageNumber.toString() });
+ },
+ });
+
+ if (list.length === 0) {
+ return (
+
+ {keyword
+ ? `"${keyword}"로 검색된 결과가 없습니다.`
+ : "게시글이 없습니다."}
+
+ );
+ }
+ return (
+ <>
+
+ {(item) => }
+
+
+ >
+ );
+}
diff --git a/src/app/(common)/(board)/boards/(lists)/_components/BoardListWrapper.module.scss b/src/app/(common)/(board)/boards/(lists)/_components/BoardListWrapper.module.scss
new file mode 100644
index 000000000..75a745650
--- /dev/null
+++ b/src/app/(common)/(board)/boards/(lists)/_components/BoardListWrapper.module.scss
@@ -0,0 +1,29 @@
+@use "@assets/scss/base/mixins";
+.item {
+ margin-bottom: 2.4rem;
+}
+
+.best {
+ display: flex;
+ gap: 2.4rem;
+
+ .item {
+ width: 100%;
+ }
+
+ @include mixins.tablet {
+ .item:nth-child(n + 3) {
+ display: none;
+ }
+ }
+
+ @include mixins.mobile {
+ .list {
+ gap: 1.6rem;
+ }
+
+ .item:nth-child(n + 2) {
+ display: none;
+ }
+ }
+}
diff --git a/src/app/(common)/(board)/boards/(lists)/_components/BoardListWrapper.tsx b/src/app/(common)/(board)/boards/(lists)/_components/BoardListWrapper.tsx
new file mode 100644
index 000000000..ac77cc503
--- /dev/null
+++ b/src/app/(common)/(board)/boards/(lists)/_components/BoardListWrapper.tsx
@@ -0,0 +1,26 @@
+import { ReactNode } from "react";
+import clsx from "clsx";
+import { Article, ListMode } from "@/types/article";
+import styles from "./BoardListWrapper.module.scss";
+
+interface BoardListWrapper {
+ mode: ListMode;
+ items: Article[];
+ children: (item: Article) => ReactNode;
+}
+
+export default function BoardListWrapper({
+ mode,
+ items,
+ children,
+}: BoardListWrapper) {
+ return (
+
+ {items.map((item) => (
+ -
+ {children(item)}
+
+ ))}
+
+ );
+}
diff --git a/src/app/(common)/(board)/boards/(lists)/layout.tsx b/src/app/(common)/(board)/boards/(lists)/layout.tsx
new file mode 100644
index 000000000..b233600db
--- /dev/null
+++ b/src/app/(common)/(board)/boards/(lists)/layout.tsx
@@ -0,0 +1,20 @@
+import { PageWrapper } from "@/components/Page";
+import { ReactNode } from "react";
+
+export default function dss({
+ all,
+ best,
+ children,
+}: {
+ all: ReactNode;
+ best: ReactNode;
+ children: ReactNode;
+}) {
+ return (
+
+ {best}
+ {all}
+ {children}
+
+ );
+}
diff --git a/src/app/(common)/(board)/boards/(lists)/page.tsx b/src/app/(common)/(board)/boards/(lists)/page.tsx
new file mode 100644
index 000000000..c035d6f6a
--- /dev/null
+++ b/src/app/(common)/(board)/boards/(lists)/page.tsx
@@ -0,0 +1,3 @@
+export default function BoardsPage() {
+ return <>>;
+}
diff --git a/src/app/(common)/(board)/boards/[id]/loading.tsx b/src/app/(common)/(board)/boards/[id]/loading.tsx
new file mode 100644
index 000000000..04b98aafc
--- /dev/null
+++ b/src/app/(common)/(board)/boards/[id]/loading.tsx
@@ -0,0 +1,5 @@
+import { Message } from "@/components/ui";
+
+export default function loading() {
+ return 게시물 상세페이지 가져오는중...;
+}
diff --git a/src/app/(common)/(board)/boards/[id]/page.tsx b/src/app/(common)/(board)/boards/[id]/page.tsx
new file mode 100644
index 000000000..efd6d7fcf
--- /dev/null
+++ b/src/app/(common)/(board)/boards/[id]/page.tsx
@@ -0,0 +1,37 @@
+import { Temporary } from "@/components/ui";
+import { getArticle } from "@/service/article";
+import axios from "axios";
+import { notFound } from "next/navigation";
+
+export default async function BoardDetailPage({
+ params,
+}: {
+ params: Promise<{ id: string }>;
+}) {
+ const id = (await params).id;
+
+ try {
+ const detail = await getArticle(Number(id));
+
+ if (!detail) {
+ notFound();
+ }
+
+ return (
+
+ );
+ } catch (error) {
+ if (axios.isAxiosError(error)) {
+ if (error.status === 404) {
+ notFound();
+ }
+
+ throw new Error("게시물 정보를 가져오는데 실패했습니다");
+ }
+
+ throw new Error("알 수 없는 에러가 발생했습니다.");
+ }
+}
diff --git a/src/app/(common)/(etc)/faq/page.tsx b/src/app/(common)/(etc)/faq/page.tsx
new file mode 100644
index 000000000..c352abcd7
--- /dev/null
+++ b/src/app/(common)/(etc)/faq/page.tsx
@@ -0,0 +1,12 @@
+import { Temporary } from "@/components/ui";
+
+export const dynamic = "force-static";
+
+export default function FagPage() {
+ return (
+
+ );
+}
diff --git a/src/app/(common)/(etc)/privacy/page.tsx b/src/app/(common)/(etc)/privacy/page.tsx
new file mode 100644
index 000000000..12513b5cd
--- /dev/null
+++ b/src/app/(common)/(etc)/privacy/page.tsx
@@ -0,0 +1,12 @@
+import { Temporary } from "@/components/ui";
+
+export const dynamic = "force-static";
+
+export default function PrivacyPage() {
+ return (
+
+ );
+}
diff --git a/src/app/(common)/(landing)/_components/Banner.module.scss b/src/app/(common)/(landing)/_components/Banner.module.scss
new file mode 100644
index 000000000..49ef663df
--- /dev/null
+++ b/src/app/(common)/(landing)/_components/Banner.module.scss
@@ -0,0 +1,137 @@
+@use "@assets/scss/base/mixins";
+
+.banner {
+ position: relative;
+ height: 54rem;
+ padding: 0 calc(20rem - var(--gutter));
+ background: #cfe5ff;
+
+ @include mixins.tablet {
+ height: auto;
+ padding: 0;
+ }
+
+ .inner {
+ @include mixins.inner;
+ position: relative;
+ display: flex;
+ flex-direction: column;
+ justify-content: flex-end;
+ height: 100%;
+
+ @media (width < 1440px) {
+ justify-content: flex-start;
+ padding-top: 10rem;
+ }
+
+ @include mixins.tablet {
+ overflow: hidden;
+ align-items: center;
+ padding-top: 8.4rem;
+ text-align: center;
+ }
+
+ @include mixins.mobile {
+ padding-top: 4.8rem;
+ }
+ }
+
+ .banner-content {
+ position: relative;
+ z-index: 1;
+ margin-bottom: 10rem;
+
+ @include mixins.tablet {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin-bottom: 21rem;
+ }
+
+ @include mixins.mobile {
+ margin-bottom: 13.2rem;
+ }
+ }
+
+ .banner-title {
+ margin-bottom: 3.2rem;
+ font-size: 4rem;
+ font-weight: 700;
+ line-height: 1.4;
+ letter-spacing: 0.08rem;
+ color: var(--color-secondary-700);
+ white-space: pre-wrap;
+
+ @include mixins.tablet {
+ white-space: normal;
+ }
+
+ @include mixins.mobile {
+ margin-bottom: 1.8rem;
+ font-size: 3.2rem;
+ white-space: pre-wrap;
+ }
+ }
+
+ .banner-img {
+ position: absolute;
+ right: 2.4rem;
+ bottom: 0;
+ width: min(55vw, 74.6rem);
+ height: auto;
+
+ @include mixins.tablet {
+ position: relative;
+ right: auto;
+ bottom: auto;
+ width: calc(100% + var(--gutter) * 2);
+ margin: 0;
+ }
+ }
+}
+
+.hero-banner {
+ .banner-img {
+ @include mixins.mobile {
+ width: 120vw;
+ }
+ }
+}
+
+.footer-banner {
+ margin-top: 13.8rem;
+
+ @include mixins.tablet {
+ margin-top: 0;
+ }
+
+ .inner {
+ @include mixins.tablet {
+ padding-top: 20.1rem;
+ }
+
+ @include mixins.mobile {
+ padding-top: 12.1rem;
+ }
+ }
+
+ .banner-content {
+ margin-bottom: 17.2rem;
+
+ @include mixins.tablet {
+ margin-bottom: 21.7rem;
+ }
+
+ @include mixins.mobile {
+ margin-bottom: 13.1rem;
+ }
+ }
+
+ .banner-title {
+ margin-bottom: 0;
+
+ @include mixins.tablet {
+ white-space: pre-wrap;
+ }
+ }
+}
diff --git a/src/app/(common)/(landing)/_components/Banner.tsx b/src/app/(common)/(landing)/_components/Banner.tsx
new file mode 100644
index 000000000..5f8cdcee1
--- /dev/null
+++ b/src/app/(common)/(landing)/_components/Banner.tsx
@@ -0,0 +1,43 @@
+import { Button } from "@components/ui";
+import styles from "./Banner.module.scss";
+import Image from "next/image";
+
+export interface BannerProps {
+ title: string;
+ bannerType: "hero" | "footer";
+ action?: {
+ to: string;
+ label: string;
+ };
+ bannerImg: {
+ src: string;
+ alt: string;
+ };
+}
+
+export default function Banner({
+ title,
+ bannerType = "hero",
+ action,
+ bannerImg,
+}: BannerProps) {
+ return (
+
+
+
+
{title}
+ {action && (
+
+ )}
+
+
+
+
+ );
+}
diff --git a/src/app/(common)/(landing)/_components/Feature.module.scss b/src/app/(common)/(landing)/_components/Feature.module.scss
new file mode 100644
index 000000000..04091ac91
--- /dev/null
+++ b/src/app/(common)/(landing)/_components/Feature.module.scss
@@ -0,0 +1,146 @@
+@use "@assets/scss/base/mixins";
+
+.features {
+ @include mixins.tablet {
+ padding: 2.4rem 0 5.6rem;
+ }
+ @include mixins.mobile {
+ padding: 5.2rem 0 8.3rem;
+ }
+}
+
+.feature {
+ padding: 13.8rem 0;
+ background: #fff;
+
+ @include mixins.tablet {
+ padding: 0;
+ margin-bottom: 5.2rem;
+ background: transparent;
+ }
+
+ @include mixins.mobile {
+ margin-bottom: 4rem;
+ }
+
+ &:last-child {
+ @include mixins.tablet {
+ margin-bottom: 0;
+ }
+ }
+
+ .inner {
+ @include mixins.inner;
+ max-width: calc(98.8rem + var(--gutter) * 2);
+ }
+
+ .feature-card {
+ overflow: hidden;
+ display: flex;
+ gap: 6.4rem;
+ height: 44.4rem;
+ border-radius: 12px;
+ background: #fcfcfc;
+
+ @include mixins.tablet {
+ display: block;
+ height: auto;
+ border-radius: 0;
+ background: none;
+ }
+
+ .feature-image {
+ @include mixins.tablet {
+ overflow: hidden;
+ margin-bottom: 2.4rem;
+ border-radius: 12px;
+ }
+
+ img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+
+ @include mixins.tablet {
+ height: auto;
+ object-fit: unset;
+ }
+ }
+ }
+
+ .feature-content {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ flex: 0 0 34.5rem;
+ padding-right: 4rem;
+ word-break: keep-all;
+
+ .feature-keyword {
+ margin-bottom: 1.2rem;
+ color: var(--color-primary-100);
+ font-size: 1.8rem;
+ font-weight: 700;
+
+ @include mixins.tablet {
+ margin-bottom: 1.6rem;
+ }
+
+ @include mixins.mobile {
+ margin-bottom: 0.8rem;
+ font-size: 1.6rem;
+ }
+ }
+
+ .feature-title {
+ margin-bottom: 2.4rem;
+ font-size: 4rem;
+ font-weight: 700;
+ line-height: 1.4;
+ color: var(--color-secondary-700);
+ white-space: pre-wrap;
+
+ @include mixins.tablet {
+ margin-bottom: 2.4rem;
+ font-size: 3.2rem;
+ white-space: normal;
+ }
+
+ @include mixins.mobile {
+ margin-bottom: 1.6rem;
+ font-size: 2.4rem;
+ line-height: 1.3;
+ }
+ }
+
+ .feature-description {
+ font-size: 2.4rem;
+ font-weight: 500;
+ color: var(--color-secondary-700);
+ white-space: pre-wrap;
+
+ @include mixins.tablet {
+ font-size: 1.8rem;
+ line-height: 1.4;
+ }
+
+ @include mixins.mobile {
+ font-size: 1.6rem;
+ line-height: 1.6;
+ }
+ }
+ }
+ }
+
+ &.reverse {
+ .feature-card {
+ flex-direction: row-reverse;
+ text-align: right;
+ }
+
+ .feature-content {
+ padding-left: 4rem;
+ padding-right: 0;
+ }
+ }
+}
diff --git a/src/app/(common)/(landing)/_components/Feature.tsx b/src/app/(common)/(landing)/_components/Feature.tsx
new file mode 100644
index 000000000..2f737607c
--- /dev/null
+++ b/src/app/(common)/(landing)/_components/Feature.tsx
@@ -0,0 +1,57 @@
+import Image from "next/image";
+import styles from "./Feature.module.scss";
+
+type Featrue = {
+ keyword: string;
+ title: string;
+ description: string;
+ featureImg: {
+ src: string;
+ alt: string;
+ };
+ reverse?: boolean;
+};
+
+interface FeatureProps {
+ list: Featrue[];
+}
+
+export default function Feature({ list }: FeatureProps) {
+ return (
+
+ 판다마켓의 기능들
+ {list.map((feature, index) => (
+
+ ))}
+
+ );
+}
+
+function FeatureItem({
+ reverse,
+ keyword,
+ title,
+ featureImg,
+ description,
+}: Featrue) {
+ return (
+
+
+
+
+
+
{keyword}
+
{title}
+
{description}
+
+
+
+
+ );
+}
diff --git a/src/app/(common)/(landing)/_components/landingContents.ts b/src/app/(common)/(landing)/_components/landingContents.ts
new file mode 100644
index 000000000..c7489ac39
--- /dev/null
+++ b/src/app/(common)/(landing)/_components/landingContents.ts
@@ -0,0 +1,55 @@
+import heroBannerImg from "@assets/img/landing/banner_img_hero.svg";
+import bottomBannerImg from "@assets/img/landing/banner_img_bottom.svg";
+import featureImg1 from "@assets/img/landing/landing_content_01.svg";
+import featureImg2 from "@assets/img/landing/landing_content_02.svg";
+import featureImg3 from "@assets/img/landing/landing_content_03.svg";
+import { BannerProps } from "./Banner";
+
+export const heroBannerData: BannerProps = {
+ bannerType: "hero",
+ title: "일상의 모든 물건을 \n거래해 보세요",
+ action: { to: "/items", label: "구경하러가기" },
+ bannerImg: {
+ src: heroBannerImg,
+ alt: "일상의 모든 물건을 거래해보세요. 판다마켓",
+ },
+};
+
+export const footerBannerData: BannerProps = {
+ bannerType: "footer",
+ title: "믿을 수 있는 \n판다마켓 중고 거래",
+ bannerImg: {
+ src: bottomBannerImg,
+ alt: "믿을 수 있는 판다마켓 중고 거래",
+ },
+};
+
+export const featureList = [
+ {
+ keyword: "Hot item",
+ title: "인기 상품을 \n확인해 보세요",
+ description: "가장 HOT한 중고거래 물품을 \n판다 마켓에서 확인해 보세요",
+ featureImg: {
+ src: featureImg1,
+ alt: "인기 상품을 확인해 보세요",
+ },
+ },
+ {
+ keyword: "Search",
+ title: "구매를 원하는 \n상품을 검색하세요",
+ description: "구매하고 싶은 물품은 검색해서 \n쉽게 찾아보세요",
+ featureImg: {
+ src: featureImg2,
+ alt: "구매를 원하는 상품을 검색하세요",
+ },
+ },
+ {
+ keyword: "Register",
+ title: "판매를 원하는 \n상품을 등록하세요",
+ description: "어떤 물건이든 판매하고 싶은 \n상품을 쉽게 등록하세요",
+ featureImg: {
+ src: featureImg3,
+ alt: "판매를 원하는 상품을 등록하세요",
+ },
+ },
+];
diff --git a/src/app/(common)/(landing)/page.tsx b/src/app/(common)/(landing)/page.tsx
new file mode 100644
index 000000000..c8abc1b1c
--- /dev/null
+++ b/src/app/(common)/(landing)/page.tsx
@@ -0,0 +1,19 @@
+import Banner from "./_components/Banner";
+import Feature from "./_components/Feature";
+import {
+ heroBannerData,
+ footerBannerData,
+ featureList,
+} from "./_components/landingContents";
+
+export const dynamic = "force-static";
+
+export default function LandingPage() {
+ return (
+ <>
+
+
+
+ >
+ );
+}
diff --git a/src/app/(common)/(market)/_components/Comments.tsx b/src/app/(common)/(market)/_components/Comments.tsx
new file mode 100644
index 000000000..2f2544d00
--- /dev/null
+++ b/src/app/(common)/(market)/_components/Comments.tsx
@@ -0,0 +1,19 @@
+"use client";
+
+import { BoardName, CommentList as CommentListType } from "@/types/comment";
+import { CommentAdd, CommentList } from "@/components/Comment";
+import CommentsProvider from "@/context/CommentContext";
+
+type CommentsType = {
+ name: BoardName;
+ data: CommentListType;
+};
+
+export default function Comments({ name, data }: CommentsType) {
+ return (
+
+
+
+
+ );
+}
diff --git a/src/app/(common)/(market)/_components/ProductDetail.module.scss b/src/app/(common)/(market)/_components/ProductDetail.module.scss
new file mode 100644
index 000000000..ec5279547
--- /dev/null
+++ b/src/app/(common)/(market)/_components/ProductDetail.module.scss
@@ -0,0 +1,112 @@
+@use "@assets/scss/base/mixins";
+
+.detail {
+ display: flex;
+ gap: 2.4rem;
+ padding-bottom: 4rem;
+ margin-bottom: 4rem;
+ border-bottom: 1px solid var(--color-secondary-200);
+
+ @include mixins.tablet {
+ gap: 1.6rem;
+ }
+
+ @include mixins.mobile {
+ flex-direction: column;
+ }
+
+ .cover {
+ max-width: 48.6rem;
+ flex: 0 1 50%;
+
+ @include mixins.mobile {
+ max-width: 100%;
+ }
+ }
+
+ .content {
+ flex: 1;
+ }
+
+ .detail-header {
+ display: flex;
+ justify-content: space-between;
+ padding-bottom: 1.6rem;
+ margin-bottom: 2.4rem;
+ border-bottom: 1px solid var(--color-secondary-200);
+
+ .info {
+ font-weight: 600;
+ color: var(--color-secondary-800);
+ }
+
+ .title {
+ margin-bottom: 1.6rem;
+ font-size: 2.4rem;
+
+ @include mixins.tablet {
+ font-size: 2rem;
+ }
+
+ @include mixins.tablet {
+ font-size: 1.6rem;
+ }
+ }
+
+ .price {
+ font-size: 4rem;
+
+ @include mixins.tablet {
+ font-size: 3.2rem;
+ }
+
+ @include mixins.tablet {
+ font-size: 2.4rem;
+ }
+ }
+ }
+
+ .tags {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.8rem;
+
+ div {
+ transition: all 0.2s;
+ }
+
+ a:hover {
+ font-weight: 500;
+
+ & > div {
+ transform: translateY(-3px);
+ background: var(--color-secondary-200);
+ }
+ }
+ }
+
+ .meta {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-top: 6.2rem;
+
+ .controls {
+ margin-left: 2.4rem;
+ padding-left: 2.4rem;
+ border-left: 1px solid var(--color-secondary-200);
+ }
+ }
+}
+
+.section {
+ margin-bottom: 2.8rem;
+ color: var(--color-secondary-600);
+ line-height: 1.625;
+
+ .title {
+ margin-bottom: 1.6rem;
+ font-size: 1.6rem;
+ font-weight: 600;
+ }
+}
diff --git a/src/app/(common)/(market)/_components/ProductDetail.tsx b/src/app/(common)/(market)/_components/ProductDetail.tsx
new file mode 100644
index 000000000..0355323e8
--- /dev/null
+++ b/src/app/(common)/(market)/_components/ProductDetail.tsx
@@ -0,0 +1,129 @@
+"use client";
+
+import { ReactNode } from "react";
+import {
+ Chip,
+ Thumbnail,
+ Author,
+ LikeButton,
+ Fullscreen,
+} from "@components/ui";
+import { More } from "@components/Button";
+import { toWon } from "@util/formatter";
+import styles from "./ProductDetail.module.scss";
+import { Product } from "@type/product";
+import Link from "next/link";
+import { useRouter } from "next/navigation";
+import useProductActions from "./useProductActions";
+import { useSession } from "next-auth/react";
+
+interface ProductDetail {
+ detail: Product;
+}
+
+export default function ProductDetail({ detail }: ProductDetail) {
+ const {
+ id,
+ images,
+ name,
+ price,
+ description,
+ tags,
+ ownerId,
+ ownerNickname,
+ updatedAt,
+ favoriteCount,
+ isFavorite,
+ } = detail;
+ const { data: session } = useSession();
+ const router = useRouter();
+ const { handleLike, handleProductDelete } = useProductActions(id);
+ const isOwner = ownerId === Number(session?.user?.id);
+
+ async function handleToggleLike() {
+ if (!session?.user) {
+ return alert("로그인이 필요합니다.");
+ }
+ await handleLike(!isFavorite);
+ router.refresh();
+ }
+
+ function handleModify() {
+ if (!isOwner) {
+ return alert("작성자만 수정이 가능합니다.");
+ }
+
+ router.push(`/modifyItem/${id}`);
+ }
+
+ async function handleDelete() {
+ if (!isOwner) {
+ return alert("작성자만 삭제가 가능합니다.");
+ }
+
+ if (confirm("정말 삭제할까요?")) {
+ try {
+ await handleProductDelete();
+ alert("상품을 삭제했습니다.");
+ router.replace("/items");
+ } catch (err) {
+ console.log(err);
+ }
+ }
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
{name}
+
{toWon(price)}
+
+
+
+
+
+
+
+
+ {tags.map((tag) => (
+
+
+
+ ))}
+
+
+
+
+
+ );
+}
+
+function Section({ title, children }: { title: string; children: ReactNode }) {
+ return (
+
+ );
+}
diff --git a/src/app/(common)/(market)/_components/ProductForm.tsx b/src/app/(common)/(market)/_components/ProductForm.tsx
new file mode 100644
index 000000000..5a47771bc
--- /dev/null
+++ b/src/app/(common)/(market)/_components/ProductForm.tsx
@@ -0,0 +1,139 @@
+"use client";
+
+import { Section } from "@components/Section";
+import {
+ FieldItem,
+ Form,
+ ImageUpload,
+ Input,
+ NumberInput,
+ TagsInput,
+ Textarea,
+} from "@components/Field";
+import { Button } from "@components/ui";
+import useFormWithError from "@hooks/useFormWithError";
+import { ProductFormSchema, ProductFormType } from "@schemas/product";
+import { zodResolver } from "@hookform/resolvers/zod";
+import { Product } from "@type/product";
+import { FieldAdapter } from "@components/adaptor/rhf";
+import { useRouter } from "next/navigation";
+import useProductActions from "./useProductActions";
+
+interface ProductFormProps {
+ initialData?: Product;
+ mode?: "add" | "edit";
+ productId?: number;
+}
+
+export default function ProductForm({
+ initialData,
+ mode = "add",
+ productId,
+}: ProductFormProps) {
+ const router = useRouter();
+ const { handleProductAdd, handleProductModify } =
+ useProductActions(productId);
+ const onFormSubmit = mode === "add" ? handleProductAdd : handleProductModify;
+
+ const {
+ control,
+ formError,
+ handleSubmit,
+ formState: { isSubmitting, isValid },
+ } = useFormWithError({
+ mode: "onBlur",
+ resolver: zodResolver(ProductFormSchema),
+ defaultValues: initialData || {
+ images: [],
+ name: "",
+ description: "",
+ price: 0,
+ tags: [],
+ },
+ });
+
+ async function onSubmit(data: ProductFormType) {
+ try {
+ await onFormSubmit(data);
+ alert(
+ mode === "add" ? "성공적으로 작성했습니다." : "성공적으로 수정했습니다."
+ );
+ router.replace(mode === "add" ? "/items" : `/items/${initialData?.id}`);
+ } catch (err) {
+ throw err;
+ }
+ }
+
+ return (
+
+ );
+}
diff --git a/src/app/(common)/(market)/_components/useProductActions.ts b/src/app/(common)/(market)/_components/useProductActions.ts
new file mode 100644
index 000000000..0c17eac4f
--- /dev/null
+++ b/src/app/(common)/(market)/_components/useProductActions.ts
@@ -0,0 +1,63 @@
+import { ProductFormType } from "@schemas/product";
+import {
+ addProduct,
+ deleteProduct,
+ modifyProduct,
+ toggleLike,
+ uploadProductImage,
+} from "@service/product";
+
+export default function useProductActions(productId?: number) {
+ async function handleLike(flag: boolean) {
+ if (!productId) return;
+
+ return toggleLike(productId, flag);
+ }
+
+ async function handleProductAdd(formData: ProductFormType) {
+ try {
+ if (formData.images[0] instanceof File) {
+ const imgFormData = new FormData();
+ imgFormData.append("image", formData.images[0]);
+
+ const { url } = await uploadProductImage(imgFormData);
+ formData.images = [url];
+ }
+
+ await addProduct(formData);
+ } catch (err) {
+ throw err;
+ }
+ }
+
+ async function handleProductModify(formData: ProductFormType) {
+ if (!productId) return;
+
+ try {
+ if (formData.images[0] instanceof File) {
+ const imgFormData = new FormData();
+ imgFormData.append("image", formData.images[0]);
+
+ const { url } = await uploadProductImage(imgFormData);
+ formData.images = [url];
+ }
+
+ await modifyProduct(productId, formData);
+ } catch (err) {
+ throw err;
+ }
+ }
+
+ async function handleProductDelete() {
+ if (!productId) return;
+
+ return deleteProduct(productId);
+ }
+
+ return {
+ handleLike,
+ handleProductAdd,
+ handleProductModify,
+ handleProductDelete,
+ };
+}
diff --git a/src/app/(common)/(market)/addItem/page.tsx b/src/app/(common)/(market)/addItem/page.tsx
new file mode 100644
index 000000000..355603c3d
--- /dev/null
+++ b/src/app/(common)/(market)/addItem/page.tsx
@@ -0,0 +1,10 @@
+import { PageWrapper } from "@/components/Page";
+import ProductForm from "../_components/ProductForm";
+
+export default function AddItemPage() {
+ return (
+
+
+
+ );
+}
diff --git a/src/app/(common)/(market)/items/(lists)/@all/loading.tsx b/src/app/(common)/(market)/items/(lists)/@all/loading.tsx
new file mode 100644
index 000000000..1f368b102
--- /dev/null
+++ b/src/app/(common)/(market)/items/(lists)/@all/loading.tsx
@@ -0,0 +1,5 @@
+import { Message } from "@/components/ui";
+
+export default function Loading() {
+ return 전체 상품을 불러오는중입니다....;
+}
diff --git a/src/app/(common)/(market)/items/(lists)/@all/page.tsx b/src/app/(common)/(market)/items/(lists)/@all/page.tsx
new file mode 100644
index 000000000..25664a825
--- /dev/null
+++ b/src/app/(common)/(market)/items/(lists)/@all/page.tsx
@@ -0,0 +1,36 @@
+import { Section } from "@/components/Section";
+import { getProducts } from "@/service/product";
+import ProductFilter from "../_components/ProductFilter";
+import ProductList from "../_components/ProductList";
+
+type ItemsPageQueryParams = {
+ page?: string;
+ orderBy?: string;
+ keyword?: string;
+ pageSize?: string;
+};
+
+export default async function AllListPage({
+ searchParams,
+}: {
+ searchParams: Promise;
+}) {
+ const { page, orderBy, keyword, pageSize } = await searchParams;
+ const data = await getProducts({
+ page: Number(page) || 1,
+ orderBy: orderBy || "recent",
+ keyword: keyword || "",
+ pageSize: Number(pageSize) || 10,
+ });
+
+ return (
+
+ );
+}
diff --git a/src/app/(common)/(market)/items/(lists)/@best/loading.tsx b/src/app/(common)/(market)/items/(lists)/@best/loading.tsx
new file mode 100644
index 000000000..8fc5f651c
--- /dev/null
+++ b/src/app/(common)/(market)/items/(lists)/@best/loading.tsx
@@ -0,0 +1,5 @@
+import { Message } from "@/components/ui";
+
+export default function Loading() {
+ return 상품상제정보를 가져오는중입니다...;
+}
diff --git a/src/app/(common)/(market)/items/(lists)/@best/page.tsx b/src/app/(common)/(market)/items/(lists)/@best/page.tsx
new file mode 100644
index 000000000..b11ca5a10
--- /dev/null
+++ b/src/app/(common)/(market)/items/(lists)/@best/page.tsx
@@ -0,0 +1,28 @@
+import { Section } from "@/components/Section";
+import { getProducts } from "@/service/product";
+import BestList from "../_components/BestList";
+
+type BestItemsPageQueryParams = {
+ bestPageSize?: string;
+};
+
+export default async function BestListPage({
+ searchParams,
+}: {
+ searchParams: Promise;
+}) {
+ const { bestPageSize } = await searchParams;
+ const data = await getProducts({
+ orderBy: "favorite",
+ pageSize: Number(bestPageSize) || 4,
+ });
+
+ return (
+
+ );
+}
diff --git a/src/app/(common)/(market)/items/(lists)/_components/BestList.tsx b/src/app/(common)/(market)/items/(lists)/_components/BestList.tsx
new file mode 100644
index 000000000..dc69f3445
--- /dev/null
+++ b/src/app/(common)/(market)/items/(lists)/_components/BestList.tsx
@@ -0,0 +1,38 @@
+"use client";
+
+import { useEffect } from "react";
+import useResponsive from "@/hooks/useResponsive";
+import useParams from "@/hooks/useParams";
+import { PaginationResponse } from "@/types/common";
+import { Product } from "@/types/product";
+import ProductItem from "./ProductItem";
+import ProductListWrapper from "./ProductListWrapper";
+
+interface BestListProps {
+ data: PaginationResponse;
+}
+
+export default function BestList({ data }: BestListProps) {
+ const { searchParams, handleParams } = useParams();
+ const currentSize = Number(searchParams.get("bestPageSize")) || 4;
+ const pageSize = useResponsive({
+ pc: 4,
+ tablet: 2,
+ mobile: 1,
+ });
+ const { list } = data;
+
+ useEffect(() => {
+ if (pageSize === currentSize) return;
+
+ handleParams({ bestPageSize: pageSize });
+ }, [pageSize, currentSize, handleParams]);
+
+ return (
+ <>
+
+ {(item) => }
+
+ >
+ );
+}
diff --git a/src/app/(common)/(market)/items/(lists)/_components/ProductFilter.module.scss b/src/app/(common)/(market)/items/(lists)/_components/ProductFilter.module.scss
new file mode 100644
index 000000000..a03f5cc33
--- /dev/null
+++ b/src/app/(common)/(market)/items/(lists)/_components/ProductFilter.module.scss
@@ -0,0 +1,23 @@
+@use "@assets/scss/base/mixins";
+
+.search {
+ width: 100%;
+ max-width: 32.5rem;
+ @include mixins.mobile {
+ order: 2;
+ max-width: 100%;
+ width: calc(100% - 4.2rem - 1.2rem);
+ }
+}
+
+.button {
+ @include mixins.mobile {
+ order: 1;
+ }
+}
+
+.select {
+ @include mixins.mobile {
+ order: 3;
+ }
+}
diff --git a/src/app/(common)/(market)/items/(lists)/_components/ProductFilter.tsx b/src/app/(common)/(market)/items/(lists)/_components/ProductFilter.tsx
new file mode 100644
index 000000000..d4057102a
--- /dev/null
+++ b/src/app/(common)/(market)/items/(lists)/_components/ProductFilter.tsx
@@ -0,0 +1,70 @@
+"use client";
+
+import useRecentSearch from "@/hooks/useRecentSearch";
+import useParams from "@/hooks/useParams";
+import { Recent, Search } from "@/components/Search";
+import { Button, Select } from "@/components/ui";
+import styles from "./ProductFilter.module.scss";
+
+export default function ProductFilter() {
+ const { searchParams, handleParams } = useParams();
+
+ const keyword = searchParams.get("keyword") || "";
+ const orderBy = searchParams.get("orderBy") || "recent";
+
+ const {
+ searchInput,
+ recentSearch,
+ handleSearchSubmit,
+ handleSearchChange,
+ handleSearchClear,
+ handleRecentSearchClick,
+ handleRecentSearchRemove,
+ handleRecentSearchClear,
+ } = useRecentSearch({ initialKeyword: keyword, onChange: handleSearch });
+
+ function handleSearch(keyword: string) {
+ handleParams({ keyword, page: 1 });
+ }
+
+ function handleOrderBy(orderBy: string) {
+ handleParams({ orderBy, page: 1 });
+ }
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/src/app/(common)/(market)/items/(lists)/_components/ProductItem.module.scss b/src/app/(common)/(market)/items/(lists)/_components/ProductItem.module.scss
new file mode 100644
index 000000000..7e567a41b
--- /dev/null
+++ b/src/app/(common)/(market)/items/(lists)/_components/ProductItem.module.scss
@@ -0,0 +1,48 @@
+.item {
+ .thumbnail {
+ margin-bottom: 1.6rem;
+ }
+
+ &:hover {
+ figure {
+ transform: translateY(-4px);
+ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.04);
+ }
+ }
+
+ .content {
+ display: flex;
+ flex-direction: column;
+ gap: 0.6rem;
+ }
+
+ .title {
+ overflow: hidden;
+ font-size: 1.4rem;
+ font-weight: 500;
+ color: var(--color-secondary-800);
+ white-space: nowrap;
+ text-overflow: ellipsis;
+
+ em {
+ color: var(--color-primary-200);
+ font-weight: 700;
+ }
+ }
+
+ .price {
+ font-weight: 700;
+ color: var(--color-secondary-800);
+ }
+
+ .action {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+
+ .count {
+ font-size: 1.2rem;
+ color: var(--color-secondary-600);
+ }
+ }
+}
diff --git a/src/app/(common)/(market)/items/(lists)/_components/ProductItem.tsx b/src/app/(common)/(market)/items/(lists)/_components/ProductItem.tsx
new file mode 100644
index 000000000..0dbb3f603
--- /dev/null
+++ b/src/app/(common)/(market)/items/(lists)/_components/ProductItem.tsx
@@ -0,0 +1,56 @@
+import { Fragment } from "react";
+import Link from "next/link";
+import { Like, Thumbnail } from "@components/ui";
+import { toWon } from "@util/formatter";
+import styles from "./ProductItem.module.scss";
+import { Product } from "@type/product";
+
+function HighLightWithKeyword({
+ content,
+ keyword,
+}: {
+ content: string;
+ keyword?: string;
+}) {
+ if (!keyword) return <>{content}>;
+
+ const textArray = content.split(new RegExp(`(${keyword})`, "gi"));
+ return (
+ <>
+ {textArray.map((text, index) => {
+ return text.toLowerCase() === keyword.toLowerCase() ? (
+ {text}
+ ) : (
+ {text}
+ );
+ })}
+ >
+ );
+}
+
+export default function ProductItem({
+ item,
+ keyword,
+}: {
+ item: Product;
+ keyword?: string;
+}) {
+ const { id, images, name, price, favoriteCount } = item;
+
+ return (
+
+
+
+
+
+
+
+
+
{toWon(price)}
+
+
+
+
+
+ );
+}
diff --git a/src/app/(common)/(market)/items/(lists)/_components/ProductList.module.scss b/src/app/(common)/(market)/items/(lists)/_components/ProductList.module.scss
new file mode 100644
index 000000000..614be914f
--- /dev/null
+++ b/src/app/(common)/(market)/items/(lists)/_components/ProductList.module.scss
@@ -0,0 +1,45 @@
+@use "@assets/scss/base/mixins";
+
+.items {
+ display: flex;
+ gap: 4rem 2.4rem;
+ flex-wrap: wrap;
+
+ .item {
+ width: calc(20% - 1.92rem);
+ }
+
+ @include mixins.tablet {
+ gap: 4rem 1.6rem;
+
+ .item {
+ width: calc(33.333% - 1.067rem);
+ }
+ }
+
+ @include mixins.mobile {
+ gap: 3.2rem 0.8rem;
+
+ .item {
+ width: calc(50% - 0.4rem);
+ }
+ }
+}
+
+.items.best {
+ .item {
+ width: calc(25% - 1.8rem);
+ }
+
+ @include mixins.tablet {
+ .item {
+ width: calc(50% - 0.8rem);
+ }
+ }
+
+ @include mixins.mobile {
+ .item {
+ width: 100%;
+ }
+ }
+}
diff --git a/src/app/(common)/(market)/items/(lists)/_components/ProductList.tsx b/src/app/(common)/(market)/items/(lists)/_components/ProductList.tsx
new file mode 100644
index 000000000..acbe48d52
--- /dev/null
+++ b/src/app/(common)/(market)/items/(lists)/_components/ProductList.tsx
@@ -0,0 +1,64 @@
+"use client";
+
+import { useEffect } from "react";
+import useParams from "@/hooks/useParams";
+import usePagination from "@/hooks/usePagination";
+import useResponsive from "@/hooks/useResponsive";
+import { Product } from "@type/product";
+import { PaginationResponse } from "@/types/common";
+import { Message } from "@components/ui";
+import { Pagination } from "@/components/Pagination";
+import ProductListWrapper from "./ProductListWrapper";
+import ProductItem from "./ProductItem";
+
+interface ProductListProps {
+ data: PaginationResponse;
+}
+
+export default function ProductList({ data }: ProductListProps) {
+ const { searchParams, handleParams } = useParams();
+ const page = Number(searchParams.get("page")) || 1;
+ const currentPageSize = Number(searchParams.get("pageSize")) || 10;
+ const keyword = searchParams.get("keyword") || "";
+ const pageSize = useResponsive({
+ pc: 10,
+ tablet: 6,
+ mobile: 4,
+ });
+ const visibleCount = 5;
+ const { list, totalCount } = data;
+
+ useEffect(() => {
+ if (pageSize === currentPageSize) return;
+
+ handleParams({ pageSize });
+ }, [pageSize, currentPageSize, handleParams]);
+
+ const pagination = usePagination({
+ page,
+ pageSize,
+ totalCount,
+ visibleCount,
+ onChange: (pageNumber) => {
+ handleParams({ page: pageNumber.toString() });
+ },
+ });
+
+ if (list.length === 0) {
+ return (
+
+ {keyword
+ ? `"${keyword}"로 검색된 결과가 없습니다.`
+ : "게시글이 없습니다."}
+
+ );
+ }
+ return (
+ <>
+
+ {(item) => }
+
+
+ >
+ );
+}
diff --git a/src/app/(common)/(market)/items/(lists)/_components/ProductListWrapper.module.scss b/src/app/(common)/(market)/items/(lists)/_components/ProductListWrapper.module.scss
new file mode 100644
index 000000000..2b86d694a
--- /dev/null
+++ b/src/app/(common)/(market)/items/(lists)/_components/ProductListWrapper.module.scss
@@ -0,0 +1,61 @@
+@use "@assets/scss/base/mixins";
+
+.items {
+ display: flex;
+ gap: 4rem 2.4rem;
+ flex-wrap: wrap;
+
+ .item {
+ width: calc(20% - 1.92rem);
+ }
+
+ @include mixins.tablet {
+ gap: 4rem 1.6rem;
+
+ .item {
+ width: calc(33.333% - 1.067rem);
+
+ &:nth-child(n + 7) {
+ display: none;
+ }
+ }
+ }
+
+ @include mixins.mobile {
+ gap: 3.2rem 0.8rem;
+
+ .item {
+ width: calc(50% - 0.4rem);
+ }
+
+ &:nth-child(n + 5) {
+ display: none;
+ }
+ }
+}
+
+.items.best {
+ .item {
+ width: calc(25% - 1.8rem);
+ }
+
+ @include mixins.tablet {
+ .item {
+ width: calc(50% - 0.8rem);
+
+ &:nth-child(n + 3) {
+ display: none;
+ }
+ }
+ }
+
+ @include mixins.mobile {
+ .item {
+ width: 100%;
+
+ &:nth-child(n + 2) {
+ display: none;
+ }
+ }
+ }
+}
diff --git a/src/app/(common)/(market)/items/(lists)/_components/ProductListWrapper.tsx b/src/app/(common)/(market)/items/(lists)/_components/ProductListWrapper.tsx
new file mode 100644
index 000000000..0a5ec7e4d
--- /dev/null
+++ b/src/app/(common)/(market)/items/(lists)/_components/ProductListWrapper.tsx
@@ -0,0 +1,26 @@
+import { ReactNode } from "react";
+import clsx from "clsx";
+import { ListMode, Product } from "@/types/product";
+import styles from "./ProductListWrapper.module.scss";
+
+interface ProductListWrapper {
+ mode: ListMode;
+ items: Product[];
+ children: (item: Product) => ReactNode;
+}
+
+export default function ProductListWrapper({
+ mode,
+ items,
+ children,
+}: ProductListWrapper) {
+ return (
+
+ {items.map((item) => (
+ -
+ {children(item)}
+
+ ))}
+
+ );
+}
diff --git a/src/app/(common)/(market)/items/(lists)/layout.tsx b/src/app/(common)/(market)/items/(lists)/layout.tsx
new file mode 100644
index 000000000..c212166ae
--- /dev/null
+++ b/src/app/(common)/(market)/items/(lists)/layout.tsx
@@ -0,0 +1,20 @@
+import { PageWrapper } from "@/components/Page";
+import { ReactNode } from "react";
+
+export default function ListLayout({
+ all,
+ best,
+ children,
+}: {
+ all: ReactNode;
+ best: ReactNode;
+ children: ReactNode;
+}) {
+ return (
+
+ {best}
+ {all}
+ {children}
+
+ );
+}
diff --git a/src/app/(common)/(market)/items/(lists)/page.tsx b/src/app/(common)/(market)/items/(lists)/page.tsx
new file mode 100644
index 000000000..a70387363
--- /dev/null
+++ b/src/app/(common)/(market)/items/(lists)/page.tsx
@@ -0,0 +1,3 @@
+export default function ItemsPage() {
+ return <>>;
+}
diff --git a/src/app/(common)/(market)/items/[id]/@comments/loading.tsx b/src/app/(common)/(market)/items/[id]/@comments/loading.tsx
new file mode 100644
index 000000000..80dc79b76
--- /dev/null
+++ b/src/app/(common)/(market)/items/[id]/@comments/loading.tsx
@@ -0,0 +1,5 @@
+import { Message } from "@/components/ui";
+
+export default function Loading() {
+ return 코멘트를 가져오는중입니다...;
+}
diff --git a/src/app/(common)/(market)/items/[id]/@comments/page.tsx b/src/app/(common)/(market)/items/[id]/@comments/page.tsx
new file mode 100644
index 000000000..145ddd06f
--- /dev/null
+++ b/src/app/(common)/(market)/items/[id]/@comments/page.tsx
@@ -0,0 +1,30 @@
+import { getComments } from "@/service/comments";
+import axios from "axios";
+import Comments from "../../../_components/Comments";
+import { notFound } from "next/navigation";
+
+export default async function ItemCommentsPage({
+ params,
+}: {
+ params: Promise<{ id: string }>;
+}) {
+ const id = (await params).id;
+ try {
+ const comments = await getComments("products", {
+ productId: Number(id),
+ limit: 5,
+ });
+
+ return ;
+ } catch (error) {
+ if (axios.isAxiosError(error)) {
+ if (error.status === 404) {
+ notFound();
+ }
+
+ throw new Error("댓글 정보를 가져오는데 실패했습니다");
+ }
+
+ throw new Error("알 수 없는 에러가 발생했습니다.");
+ }
+}
diff --git a/src/app/(common)/(market)/items/[id]/@detail/loading.tsx b/src/app/(common)/(market)/items/[id]/@detail/loading.tsx
new file mode 100644
index 000000000..0686d511a
--- /dev/null
+++ b/src/app/(common)/(market)/items/[id]/@detail/loading.tsx
@@ -0,0 +1,5 @@
+import { Message } from "@/components/ui";
+
+export default function Loading() {
+ return 베스트 상품을 불러오는중입니다...;
+}
diff --git a/src/app/(common)/(market)/items/[id]/@detail/page.tsx b/src/app/(common)/(market)/items/[id]/@detail/page.tsx
new file mode 100644
index 000000000..a21d9402e
--- /dev/null
+++ b/src/app/(common)/(market)/items/[id]/@detail/page.tsx
@@ -0,0 +1,31 @@
+import { notFound } from "next/navigation";
+import { getProduct } from "@/service/product";
+import ProductDetail from "../../../_components/ProductDetail";
+import axios from "axios";
+
+export default async function ItemDetailPage({
+ params,
+}: {
+ params: Promise<{ id: string }>;
+}) {
+ const id = (await params).id;
+ try {
+ const detail = await getProduct(Number(id));
+
+ if (!detail) {
+ notFound();
+ }
+
+ return ;
+ } catch (error) {
+ if (axios.isAxiosError(error)) {
+ if (error.status === 404) {
+ notFound();
+ }
+
+ throw new Error("상품 정보를 가져오는데 실패했습니다");
+ }
+
+ throw new Error("알 수 없는 에러가 발생했습니다.");
+ }
+}
diff --git a/src/app/(common)/(market)/items/[id]/layout.tsx b/src/app/(common)/(market)/items/[id]/layout.tsx
new file mode 100644
index 000000000..d04e6f947
--- /dev/null
+++ b/src/app/(common)/(market)/items/[id]/layout.tsx
@@ -0,0 +1,20 @@
+import { PageWrapper } from "@/components/Page";
+import { ReactNode } from "react";
+
+export default function ItemDetailLayout({
+ detail,
+ comments,
+ children,
+}: {
+ detail: ReactNode;
+ comments: ReactNode;
+ children: ReactNode;
+}) {
+ return (
+
+ {children}
+ {detail}
+ {comments}
+
+ );
+}
diff --git a/src/app/(common)/(market)/items/[id]/page.tsx b/src/app/(common)/(market)/items/[id]/page.tsx
new file mode 100644
index 000000000..936f12e0a
--- /dev/null
+++ b/src/app/(common)/(market)/items/[id]/page.tsx
@@ -0,0 +1,3 @@
+export default function ItemDetailPage() {
+ return <>>;
+}
diff --git a/src/app/(common)/(market)/modifyItem/[id]/page.tsx b/src/app/(common)/(market)/modifyItem/[id]/page.tsx
new file mode 100644
index 000000000..e8878e174
--- /dev/null
+++ b/src/app/(common)/(market)/modifyItem/[id]/page.tsx
@@ -0,0 +1,48 @@
+import { PageWrapper } from "@/components/Page";
+import ProductForm from "../../_components/ProductForm";
+import { getProduct } from "@/service/product";
+import { auth } from "@/auth";
+import { notFound, redirect } from "next/navigation";
+import { Suspense } from "react";
+import { Message } from "@/components/ui";
+import axios from "axios";
+
+export default async function ModifyItemPage({
+ params,
+}: {
+ params: Promise<{ id: string }>;
+}) {
+ const session = await auth();
+ const id = (await params).id;
+
+ try {
+ const detail = await getProduct(Number(id));
+ const isOwner = detail.ownerId === Number(session?.user.id);
+
+ if (!isOwner) {
+ redirect("/items");
+ }
+
+ return (
+
+ 상품정보를 가져오는 중입니다...}>
+
+
+
+ );
+ } catch (error) {
+ if (axios.isAxiosError(error)) {
+ if (error.status === 404) {
+ notFound();
+ }
+
+ throw new Error("상품 정보를 가져오는데 실패했습니다");
+ }
+
+ throw new Error("알 수 없는 에러가 발생했습니다.");
+ }
+}
diff --git a/src/app/(common)/layout.module.css b/src/app/(common)/layout.module.css
new file mode 100644
index 000000000..010e9cd57
--- /dev/null
+++ b/src/app/(common)/layout.module.css
@@ -0,0 +1,4 @@
+.main {
+ padding-top: 7rem;
+ min-height: 100vh;
+}
diff --git a/src/app/(common)/layout.tsx b/src/app/(common)/layout.tsx
new file mode 100644
index 000000000..a8fbbc170
--- /dev/null
+++ b/src/app/(common)/layout.tsx
@@ -0,0 +1,18 @@
+import { PropsWithChildren } from "react";
+import { Header, Logo, Nav, Util } from "@components/Header";
+import { Footer } from "@components/Footer";
+import styles from "./layout.module.css";
+
+export default function Layout({ children }: PropsWithChildren) {
+ return (
+ <>
+
+ {children}
+
+ >
+ );
+}
diff --git a/src/app/api/auth/[...nextauth]/route.ts b/src/app/api/auth/[...nextauth]/route.ts
new file mode 100644
index 000000000..7c62e2db1
--- /dev/null
+++ b/src/app/api/auth/[...nextauth]/route.ts
@@ -0,0 +1,2 @@
+import { handlers } from "@/auth";
+export const { GET, POST } = handlers;
diff --git a/src/app/error.tsx b/src/app/error.tsx
new file mode 100644
index 000000000..7214cd865
--- /dev/null
+++ b/src/app/error.tsx
@@ -0,0 +1,12 @@
+"use client";
+
+import { Temporary } from "@/components/ui";
+
+export default function Error() {
+ return (
+
+ );
+}
diff --git a/src/app/favicon.ico b/src/app/favicon.ico
new file mode 100644
index 000000000..b6985b7bc
Binary files /dev/null and b/src/app/favicon.ico differ
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
new file mode 100644
index 000000000..6f44681be
--- /dev/null
+++ b/src/app/layout.tsx
@@ -0,0 +1,35 @@
+import { PropsWithChildren } from "react";
+import type { Metadata } from "next";
+import { AxiosInterCeptor } from "@/context/AxiosInterCeptor";
+import { SessionProvider } from "next-auth/react";
+import "@assets/scss/style.scss";
+import { initServerInterceptor } from "@/service/serverAxios";
+
+export const metadata: Metadata = {
+ title: "판다마켓",
+ description: "일상의 모든 물건을 거래해보세요",
+ openGraph: {
+ type: "website",
+ siteName: "판다마켓",
+ title: "판다마켓",
+ description: "일상의 모든 물건을 거래해보세요",
+ },
+};
+
+// server runtime 환경에서 axios에 interceptor 설정 (server에서만 동작함)
+await initServerInterceptor();
+
+export default function RootLayout({ children }: PropsWithChildren) {
+ return (
+
+
+
+
+
+ );
+}
diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx
new file mode 100644
index 000000000..fc5559590
--- /dev/null
+++ b/src/app/not-found.tsx
@@ -0,0 +1,10 @@
+import { Temporary } from "@/components/ui";
+
+export default function NotFound() {
+ return (
+
+ );
+}
diff --git a/src/app/opengraph-image.png b/src/app/opengraph-image.png
new file mode 100644
index 000000000..511000150
Binary files /dev/null and b/src/app/opengraph-image.png differ
diff --git a/src/assets/img/common/logo_full.svg b/src/assets/img/common/logo_full.svg
new file mode 100644
index 000000000..9b20d2d7c
--- /dev/null
+++ b/src/assets/img/common/logo_full.svg
@@ -0,0 +1,15 @@
+
diff --git a/src/assets/img/common/logo_text.svg b/src/assets/img/common/logo_text.svg
new file mode 100644
index 000000000..eab4eb0bc
--- /dev/null
+++ b/src/assets/img/common/logo_text.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/img/icon/icon_arrow_down.svg b/src/assets/img/icon/icon_arrow_down.svg
new file mode 100644
index 000000000..8308690fd
--- /dev/null
+++ b/src/assets/img/icon/icon_arrow_down.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/img/icon/icon_arrow_left.svg b/src/assets/img/icon/icon_arrow_left.svg
new file mode 100644
index 000000000..040e81c2e
--- /dev/null
+++ b/src/assets/img/icon/icon_arrow_left.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/img/icon/icon_arrow_right.svg b/src/assets/img/icon/icon_arrow_right.svg
new file mode 100644
index 000000000..368742c9f
--- /dev/null
+++ b/src/assets/img/icon/icon_arrow_right.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/img/icon/icon_avatar.svg b/src/assets/img/icon/icon_avatar.svg
new file mode 100644
index 000000000..6bfd8ab37
--- /dev/null
+++ b/src/assets/img/icon/icon_avatar.svg
@@ -0,0 +1,24 @@
+
diff --git a/src/assets/img/icon/icon_back.svg b/src/assets/img/icon/icon_back.svg
new file mode 100644
index 000000000..9ba5ad945
--- /dev/null
+++ b/src/assets/img/icon/icon_back.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/assets/img/icon/icon_best.svg b/src/assets/img/icon/icon_best.svg
new file mode 100644
index 000000000..9a27b0421
--- /dev/null
+++ b/src/assets/img/icon/icon_best.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/assets/img/icon/icon_clear.svg b/src/assets/img/icon/icon_clear.svg
new file mode 100644
index 000000000..f6674f7fd
--- /dev/null
+++ b/src/assets/img/icon/icon_clear.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/assets/img/icon/icon_dots.svg b/src/assets/img/icon/icon_dots.svg
new file mode 100644
index 000000000..63a0344c3
--- /dev/null
+++ b/src/assets/img/icon/icon_dots.svg
@@ -0,0 +1,5 @@
+
diff --git a/src/assets/img/icon/icon_double_arrow_left.svg b/src/assets/img/icon/icon_double_arrow_left.svg
new file mode 100644
index 000000000..08c498ea0
--- /dev/null
+++ b/src/assets/img/icon/icon_double_arrow_left.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/assets/img/icon/icon_double_arrow_right.svg b/src/assets/img/icon/icon_double_arrow_right.svg
new file mode 100644
index 000000000..4dcffd2ed
--- /dev/null
+++ b/src/assets/img/icon/icon_double_arrow_right.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/assets/img/icon/icon_error.svg b/src/assets/img/icon/icon_error.svg
new file mode 100644
index 000000000..83af6103d
--- /dev/null
+++ b/src/assets/img/icon/icon_error.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/img/icon/icon_facebook.svg b/src/assets/img/icon/icon_facebook.svg
new file mode 100644
index 000000000..8491c2f83
--- /dev/null
+++ b/src/assets/img/icon/icon_facebook.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/img/icon/icon_google.svg b/src/assets/img/icon/icon_google.svg
new file mode 100644
index 000000000..39de6337b
--- /dev/null
+++ b/src/assets/img/icon/icon_google.svg
@@ -0,0 +1,10 @@
+
diff --git a/src/assets/img/icon/icon_heart.svg b/src/assets/img/icon/icon_heart.svg
new file mode 100644
index 000000000..cad016c13
--- /dev/null
+++ b/src/assets/img/icon/icon_heart.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/img/icon/icon_heart_fill.svg b/src/assets/img/icon/icon_heart_fill.svg
new file mode 100644
index 000000000..91aded985
--- /dev/null
+++ b/src/assets/img/icon/icon_heart_fill.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/img/icon/icon_inquiry_empty.svg b/src/assets/img/icon/icon_inquiry_empty.svg
new file mode 100644
index 000000000..5444cbbbc
--- /dev/null
+++ b/src/assets/img/icon/icon_inquiry_empty.svg
@@ -0,0 +1,17 @@
+
diff --git a/src/assets/img/icon/icon_instagram.svg b/src/assets/img/icon/icon_instagram.svg
new file mode 100644
index 000000000..c83306f84
--- /dev/null
+++ b/src/assets/img/icon/icon_instagram.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/img/icon/icon_kakao.svg b/src/assets/img/icon/icon_kakao.svg
new file mode 100644
index 000000000..15dc4d0ff
--- /dev/null
+++ b/src/assets/img/icon/icon_kakao.svg
@@ -0,0 +1,12 @@
+
diff --git a/src/assets/img/icon/icon_placeholder.svg b/src/assets/img/icon/icon_placeholder.svg
new file mode 100644
index 000000000..130270f7b
--- /dev/null
+++ b/src/assets/img/icon/icon_placeholder.svg
@@ -0,0 +1,15 @@
+
diff --git a/src/assets/img/icon/icon_plus.svg b/src/assets/img/icon/icon_plus.svg
new file mode 100644
index 000000000..5bb9abf55
--- /dev/null
+++ b/src/assets/img/icon/icon_plus.svg
@@ -0,0 +1,4 @@
+
diff --git a/src/assets/img/icon/icon_search.svg b/src/assets/img/icon/icon_search.svg
new file mode 100644
index 000000000..52241e6d8
--- /dev/null
+++ b/src/assets/img/icon/icon_search.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/img/icon/icon_sort.svg b/src/assets/img/icon/icon_sort.svg
new file mode 100644
index 000000000..657b44f93
--- /dev/null
+++ b/src/assets/img/icon/icon_sort.svg
@@ -0,0 +1,6 @@
+
diff --git a/src/assets/img/icon/icon_twitter.svg b/src/assets/img/icon/icon_twitter.svg
new file mode 100644
index 000000000..14a6069a1
--- /dev/null
+++ b/src/assets/img/icon/icon_twitter.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/img/icon/icon_view_off.svg b/src/assets/img/icon/icon_view_off.svg
new file mode 100644
index 000000000..45ad62321
--- /dev/null
+++ b/src/assets/img/icon/icon_view_off.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/img/icon/icon_view_on.svg b/src/assets/img/icon/icon_view_on.svg
new file mode 100644
index 000000000..35a75305e
--- /dev/null
+++ b/src/assets/img/icon/icon_view_on.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/img/icon/icon_warn.svg b/src/assets/img/icon/icon_warn.svg
new file mode 100644
index 000000000..f08401d1e
--- /dev/null
+++ b/src/assets/img/icon/icon_warn.svg
@@ -0,0 +1,3 @@
+
diff --git a/src/assets/img/icon/icon_youtube.svg b/src/assets/img/icon/icon_youtube.svg
new file mode 100644
index 000000000..12ad22cc1
--- /dev/null
+++ b/src/assets/img/icon/icon_youtube.svg
@@ -0,0 +1,10 @@
+
diff --git a/src/assets/img/landing/banner_img_bottom.svg b/src/assets/img/landing/banner_img_bottom.svg
new file mode 100644
index 000000000..8aac2a059
--- /dev/null
+++ b/src/assets/img/landing/banner_img_bottom.svg
@@ -0,0 +1,111 @@
+
diff --git a/src/assets/img/landing/banner_img_hero.svg b/src/assets/img/landing/banner_img_hero.svg
new file mode 100644
index 000000000..687771db6
--- /dev/null
+++ b/src/assets/img/landing/banner_img_hero.svg
@@ -0,0 +1,78 @@
+
diff --git a/src/assets/img/landing/landing_content_01.svg b/src/assets/img/landing/landing_content_01.svg
new file mode 100644
index 000000000..e8a4d5a06
--- /dev/null
+++ b/src/assets/img/landing/landing_content_01.svg
@@ -0,0 +1,73 @@
+
diff --git a/src/assets/img/landing/landing_content_02.svg b/src/assets/img/landing/landing_content_02.svg
new file mode 100644
index 000000000..05fcfd7fd
--- /dev/null
+++ b/src/assets/img/landing/landing_content_02.svg
@@ -0,0 +1,29 @@
+
diff --git a/src/assets/img/landing/landing_content_03.svg b/src/assets/img/landing/landing_content_03.svg
new file mode 100644
index 000000000..79da61f06
--- /dev/null
+++ b/src/assets/img/landing/landing_content_03.svg
@@ -0,0 +1,65 @@
+
diff --git a/src/assets/scss/base/_font.scss b/src/assets/scss/base/_font.scss
new file mode 100644
index 000000000..2ad26cd72
--- /dev/null
+++ b/src/assets/scss/base/_font.scss
@@ -0,0 +1 @@
+@import url("https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/static/pretendard.min.css");
diff --git a/src/assets/scss/base/_global.scss b/src/assets/scss/base/_global.scss
new file mode 100644
index 000000000..e698d01a9
--- /dev/null
+++ b/src/assets/scss/base/_global.scss
@@ -0,0 +1,12 @@
+html {
+ font-size: 62.5%;
+}
+
+body {
+ min-width: 37.5rem;
+ background: #fcfcfc;
+ font-family: "Pretendard", sans-serif;
+ font-size: 1.6rem;
+ line-height: 1.3;
+ color: var(--color-secondary-800);
+}
diff --git a/src/assets/scss/base/_helper.scss b/src/assets/scss/base/_helper.scss
new file mode 100644
index 000000000..b274ff184
--- /dev/null
+++ b/src/assets/scss/base/_helper.scss
@@ -0,0 +1,12 @@
+.a11y {
+ overflow: hidden;
+ position: absolute;
+ clip: rect(0, 0, 0, 0);
+ clip-path: circle(0);
+ width: 1px;
+ height: 1px;
+ margin: -1px;
+ border: 0;
+ padding: 0;
+ white-space: nowrap;
+}
diff --git a/src/assets/scss/base/_index.scss b/src/assets/scss/base/_index.scss
new file mode 100644
index 000000000..26834b6d9
--- /dev/null
+++ b/src/assets/scss/base/_index.scss
@@ -0,0 +1,5 @@
+@forward "variables";
+@forward "font";
+@forward "reset";
+@forward "global";
+@forward "helper";
diff --git a/src/assets/scss/base/_mixins.scss b/src/assets/scss/base/_mixins.scss
new file mode 100644
index 000000000..2a912191f
--- /dev/null
+++ b/src/assets/scss/base/_mixins.scss
@@ -0,0 +1,32 @@
+$breakpoint-mobile: 768px;
+$breakpoint-tablet: 1200px;
+
+@mixin mobile {
+ @media (width < $breakpoint-mobile) {
+ @content;
+ }
+}
+
+@mixin tablet {
+ @media (width < $breakpoint-tablet) {
+ @content;
+ }
+}
+
+@mixin inner {
+ max-width: calc(112rem + var(--gutter) * 2);
+ margin: 0 auto;
+ padding: 0 var(--gutter);
+}
+
+@mixin tabletOnly {
+ @media ($breakpoint-mobile <= width <= $breakpoint-tablet) {
+ @content;
+ }
+}
+
+@mixin pcOnly {
+ @media (width >= $breakpoint-tablet) {
+ @content;
+ }
+}
diff --git a/src/assets/scss/base/_reset.scss b/src/assets/scss/base/_reset.scss
new file mode 100644
index 000000000..8d5cf4b78
--- /dev/null
+++ b/src/assets/scss/base/_reset.scss
@@ -0,0 +1,83 @@
+/* http://meyerweb.com/eric/tools/css/reset/
+ v2.0 | 20110126
+ License: none (public domain)
+*/
+/* prettier-ignore */
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed,
+figure, figcaption, footer, header, hgroup,
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ font: inherit;
+ vertical-align: baseline;
+}
+/* HTML5 display-role reset for older browsers */
+/* prettier-ignore */
+article, aside, details, figcaption, figure,
+footer, header, hgroup, menu, nav, section {
+ display: block;
+}
+body {
+ line-height: 1;
+}
+ol,
+ul {
+ list-style: none;
+}
+blockquote,
+q {
+ quotes: none;
+}
+blockquote:before,
+blockquote:after,
+q:before,
+q:after {
+ content: "";
+ content: none;
+}
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+
+/* additional reset css */
+*,
+*::before,
+*::after {
+ box-sizing: border-box;
+}
+a {
+ color: inherit;
+ text-decoration: none;
+}
+button {
+ margin: 0;
+ padding: 0;
+ background: transparent;
+ border: none;
+ cursor: pointer;
+ font: inherit;
+ color: inherit;
+}
+img {
+ vertical-align: top;
+}
+input,
+textarea {
+ padding: 0;
+ margin: 0;
+ border: none;
+ font: inherit;
+}
diff --git a/src/assets/scss/base/_variables.scss b/src/assets/scss/base/_variables.scss
new file mode 100644
index 000000000..8a730c130
--- /dev/null
+++ b/src/assets/scss/base/_variables.scss
@@ -0,0 +1,31 @@
+@use "mixins";
+
+:root {
+ --color-primary-300: #1251aa;
+ --color-primary-200: #1967d6;
+ --color-primary-100: #3692ff;
+ --color-secondary-900: #111827;
+ --color-secondary-800: #1f2937;
+ --color-secondary-700: #374151;
+ --color-secondary-600: #4b5563;
+ --color-secondary-500: #6b7280;
+ --color-secondary-400: #9ca3af;
+ --color-secondary-200: #e5e7eb;
+ --color-secondary-100: #f3f4f6;
+ --color-secondary-50: #f9fafb;
+ --color-error: #f74747;
+ --color-error-100: #f74747;
+ --color-error-200: #da2d2d;
+ --color-error-300: #bd2020;
+ --color-white: #fff;
+ --color-grey: #dfdfdf;
+ --color-black: #4b5563;
+
+ --gutter: 2.4rem;
+}
+
+@include mixins.mobile {
+ :root {
+ --gutter: 1.6rem;
+ }
+}
diff --git a/src/assets/scss/style.scss b/src/assets/scss/style.scss
new file mode 100644
index 000000000..271103ab3
--- /dev/null
+++ b/src/assets/scss/style.scss
@@ -0,0 +1 @@
+@use "base";
diff --git a/src/auth.ts b/src/auth.ts
new file mode 100644
index 000000000..1b732b7d4
--- /dev/null
+++ b/src/auth.ts
@@ -0,0 +1,121 @@
+import { signinFormSchmea } from "@/schemas/auth";
+import { login, refreshAccessToken } from "@/service/auth";
+import axios from "axios";
+import { jwtDecode } from "jwt-decode";
+import NextAuth, { CredentialsSignin } from "next-auth";
+import Credentials from "next-auth/providers/credentials";
+import { ZodError } from "zod";
+
+declare module "next-auth" {
+ interface User {
+ accessToken: string;
+ refreshToken: string;
+ nickname: string;
+ }
+
+ interface Session {
+ user: User;
+ accessToken: string;
+ refreshToken: string;
+ }
+
+ interface JWT {
+ user: User;
+ accessToken: string;
+ refreshToken: string;
+ }
+}
+
+export const { handlers, signIn, signOut, auth } = NextAuth({
+ providers: [
+ Credentials({
+ credentials: {
+ email: {},
+ password: {},
+ },
+ authorize: async (credentials) => {
+ try {
+ const result = await signinFormSchmea.parseAsync(credentials);
+ const { user, accessToken, refreshToken } = await login(result);
+
+ return {
+ id: user.id.toString(),
+ name: user.nickname,
+ email: result.email,
+ nickname: user.nickname,
+ image: user.image,
+ accessToken,
+ refreshToken,
+ };
+ } catch (error) {
+ if (error instanceof ZodError) {
+ throw new Error("잘못된 입력값");
+ }
+
+ if (axios.isAxiosError(error)) {
+ const message = error.response?.data?.message;
+ const credentialsSignin = new CredentialsSignin();
+ credentialsSignin.message = message;
+ credentialsSignin.code = message;
+
+ throw credentialsSignin;
+ }
+
+ throw new Error("로그인 실패");
+ }
+ },
+ }),
+ ],
+ session: {
+ strategy: "jwt",
+ maxAge: 60 * 60 * 24 * 7,
+ },
+ pages: {
+ signIn: "/login",
+ },
+ callbacks: {
+ jwt: async ({ token, user, trigger, session }) => {
+ // 쿠키에 저장된 token내역이 있으면 검증
+ if (token?.accessToken && typeof token.accessToken === "string") {
+ // accessToken이 만료됬으면 재발급;
+ const decodedToken = jwtDecode(token.accessToken as string);
+ const expiredTime = (decodedToken.exp || 0) * 1000;
+ if (Date.now() > expiredTime) {
+ try {
+ const { accessToken } = await refreshAccessToken(
+ token.refreshToken as string
+ );
+ token.accessToken = accessToken;
+ } catch (err) {
+ console.error(err);
+ }
+ }
+ }
+
+ // useSession의 update를 통해서 accessToken을 줄때
+ if (trigger === "update" && session.accessToken) {
+ token.accessToken = session.accessToken;
+ }
+
+ // 로그인 시도가 있었을때
+ if (user) {
+ token.id = user.id;
+ token.nickname = user.nickname;
+ token.accessToken = user.accessToken;
+ token.refreshToken = user.refreshToken;
+ }
+
+ return token;
+ },
+ session: async ({ session, token }) => {
+ if (token) {
+ session.user.id = token.id as string;
+ session.user.nickname = token.nickname as string;
+ session.accessToken = token.accessToken as string;
+ session.refreshToken = token.refreshToken as string;
+ }
+
+ return session;
+ },
+ },
+});
diff --git a/src/components/Button/BackToList.module.scss b/src/components/Button/BackToList.module.scss
new file mode 100644
index 000000000..eb5e3e7a6
--- /dev/null
+++ b/src/components/Button/BackToList.module.scss
@@ -0,0 +1,7 @@
+.controls {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 1rem;
+ margin: 4rem 0;
+}
diff --git a/src/components/Button/BackToList.tsx b/src/components/Button/BackToList.tsx
new file mode 100644
index 000000000..cb19188a2
--- /dev/null
+++ b/src/components/Button/BackToList.tsx
@@ -0,0 +1,14 @@
+import Image from "next/image";
+import { Button } from "@components/ui";
+import iconBack from "@assets/img/icon/icon_back.svg";
+import styles from "./BackToList.module.scss";
+
+export function BackToList() {
+ return (
+
+
+
+ );
+}
diff --git a/src/components/Button/More.module.scss b/src/components/Button/More.module.scss
new file mode 100644
index 000000000..cefe02487
--- /dev/null
+++ b/src/components/Button/More.module.scss
@@ -0,0 +1,11 @@
+.icon {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 3rem;
+ height: 3rem;
+ border-radius: 4px;
+ &:hover {
+ background: var(--color-secondary-100);
+ }
+}
diff --git a/src/components/Button/More.tsx b/src/components/Button/More.tsx
new file mode 100644
index 000000000..853cf1c01
--- /dev/null
+++ b/src/components/Button/More.tsx
@@ -0,0 +1,30 @@
+import Image from "next/image";
+import { Dropdown } from "@components/ui";
+import dotsIcon from "@assets/img/icon/icon_dots.svg";
+import styles from "./More.module.scss";
+
+interface MoreProps {
+ options: {
+ label: string;
+ action: () => void;
+ }[];
+}
+
+export function More({ options }: MoreProps) {
+ return (
+
+
+
+
+
+
+
+ {options.map((option) => (
+
+ {option.label}
+
+ ))}
+
+
+ );
+}
diff --git a/src/components/Button/index.ts b/src/components/Button/index.ts
new file mode 100644
index 000000000..6c091c715
--- /dev/null
+++ b/src/components/Button/index.ts
@@ -0,0 +1,2 @@
+export * from "./BackToList";
+export * from "./More";
diff --git a/src/components/Comment/Comment.module.scss b/src/components/Comment/Comment.module.scss
new file mode 100644
index 000000000..823ef2540
--- /dev/null
+++ b/src/components/Comment/Comment.module.scss
@@ -0,0 +1,19 @@
+.item {
+ margin-bottom: 2.4rem;
+ padding-bottom: 2.4rem;
+ border-bottom: 1px solid var(--color-secondary-200);
+}
+
+.comment {
+ display: flex;
+ gap: 2rem;
+}
+
+.content {
+ flex: 1;
+}
+
+.text {
+ margin-bottom: 2.4rem;
+ white-space: pre-wrap;
+}
diff --git a/src/components/Comment/Comment.tsx b/src/components/Comment/Comment.tsx
new file mode 100644
index 000000000..19aed0dbc
--- /dev/null
+++ b/src/components/Comment/Comment.tsx
@@ -0,0 +1,84 @@
+import { useState } from "react";
+import useComment from "./useComment";
+import { Author } from "@components/ui";
+import { More } from "@components/Button";
+import { CommentForm } from ".";
+import styles from "./Comment.module.scss";
+import { BoardName, Comment as CommentItem } from "@type/comment";
+import { useComments } from "@/context/CommentContext";
+import { useSession } from "next-auth/react";
+
+interface Comment {
+ name: BoardName;
+ comment: CommentItem;
+}
+
+export function Comment({ name, comment }: Comment) {
+ const { data: session } = useSession();
+
+ const [isModify, setIsModify] = useState(false);
+ const {
+ content,
+ updatedAt,
+ writer: { nickname, image, id: writerId },
+ } = comment;
+ const { refreshComments } = useComments();
+ const {
+ isOwner,
+ handleUpdate,
+ handleDelete: handleDeleteComment,
+ } = useComment(name, comment);
+
+ function handleModify() {
+ if (Number(session?.user?.id) !== writerId) {
+ return alert("작성자만 수정이 가능합니다.");
+ }
+ setIsModify(true);
+ }
+
+ function handleClose() {
+ setIsModify(false);
+ }
+
+ async function handleDelete() {
+ await handleDeleteComment();
+ refreshComments();
+ }
+
+ if (isModify) {
+ return (
+
+
+
+
+
+ );
+ }
+
+ return (
+
+
+
+ {isOwner && (
+
+ )}
+
+
+ );
+}
diff --git a/src/components/Comment/CommentAdd.module.scss b/src/components/Comment/CommentAdd.module.scss
new file mode 100644
index 000000000..d36cc7558
--- /dev/null
+++ b/src/components/Comment/CommentAdd.module.scss
@@ -0,0 +1,3 @@
+.form {
+ margin-bottom: 4rem;
+}
diff --git a/src/components/Comment/CommentAdd.tsx b/src/components/Comment/CommentAdd.tsx
new file mode 100644
index 000000000..2b65a0acf
--- /dev/null
+++ b/src/components/Comment/CommentAdd.tsx
@@ -0,0 +1,15 @@
+import { CommentForm } from ".";
+import useComment from "./useComment";
+import styles from "./CommentAdd.module.scss";
+import { useComments } from "@/context/CommentContext";
+
+export function CommentAdd() {
+ const { name, refreshComments } = useComments();
+ const { handleSubmit } = useComment(name);
+
+ return (
+
+
+
+ );
+}
diff --git a/src/components/Comment/CommentForm.module.scss b/src/components/Comment/CommentForm.module.scss
new file mode 100644
index 000000000..73d100d5d
--- /dev/null
+++ b/src/components/Comment/CommentForm.module.scss
@@ -0,0 +1,15 @@
+.meta {
+ display: flex;
+ width: 100%;
+ justify-content: space-between;
+}
+
+.controls {
+ display: flex;
+ gap: 1rem;
+}
+
+.footer {
+ display: flex;
+ justify-content: flex-end;
+}
diff --git a/src/components/Comment/CommentForm.tsx b/src/components/Comment/CommentForm.tsx
new file mode 100644
index 000000000..e7634d3c6
--- /dev/null
+++ b/src/components/Comment/CommentForm.tsx
@@ -0,0 +1,118 @@
+import { FieldItem, Form, Textarea } from "@components/Field";
+import { Author, Button } from "@components/ui";
+import styles from "./CommentForm.module.scss";
+import { Comment } from "@type/comment";
+import useFormWithError from "@hooks/useFormWithError";
+import { CommentFormSchema, CommentFormType } from "@schemas/comment";
+import { zodResolver } from "@hookform/resolvers/zod";
+import { FieldAdapter } from "@components/adaptor/rhf";
+import { useSession } from "next-auth/react";
+
+interface CommentForm {
+ initialData?: Comment;
+ onCommentSubmit: (data: CommentFormType) => Promise;
+ onClose?: () => void;
+ isEdit?: boolean;
+ onRefresh: () => void;
+}
+
+export function CommentForm({
+ initialData,
+ onCommentSubmit,
+ onClose,
+ isEdit,
+ onRefresh,
+}: CommentForm) {
+ const {
+ control,
+ formError,
+ reset,
+ handleSubmit,
+ formState: { isSubmitting, isValid },
+ } = useFormWithError({
+ mode: "onChange",
+ resolver: zodResolver(CommentFormSchema),
+ defaultValues: initialData,
+ });
+ const { data: session } = useSession();
+
+ function handleClose() {
+ reset();
+ onClose?.();
+ }
+
+ const message = isEdit
+ ? "성공적으로 수정했습니다."
+ : "성공적으로 작성했습니다.";
+
+ async function onSubmit(data: CommentFormType) {
+ if (!session?.user) {
+ return alert("로그인이 필요합니다.");
+ }
+
+ try {
+ await onCommentSubmit(data);
+ alert(message);
+ onRefresh();
+ reset({ content: "" });
+ onClose?.();
+ } catch (err) {
+ throw err;
+ }
+ }
+
+ return (
+
+ );
+}
diff --git a/src/components/Comment/CommentList.module.scss b/src/components/Comment/CommentList.module.scss
new file mode 100644
index 000000000..349a00689
--- /dev/null
+++ b/src/components/Comment/CommentList.module.scss
@@ -0,0 +1,19 @@
+.comments {
+ .control {
+ display: flex;
+ justify-content: center;
+ }
+
+ .button {
+ padding: 1rem 2rem;
+ border-radius: 9999px;
+ background: #eee;
+ font-size: 1.4rem;
+ color: var(--color-secondary-500);
+
+ &:hover {
+ background: #ddd;
+ color: var(--color-secondary-700);
+ }
+ }
+}
diff --git a/src/components/Comment/CommentList.tsx b/src/components/Comment/CommentList.tsx
new file mode 100644
index 000000000..d04531b15
--- /dev/null
+++ b/src/components/Comment/CommentList.tsx
@@ -0,0 +1,43 @@
+import { Alert, Message } from "@components/ui";
+import { Comment } from "./Comment";
+import emptyIcon from "@assets/img/icon/icon_inquiry_empty.svg";
+import styles from "./CommentList.module.scss";
+import { useComments } from "@/context/CommentContext";
+
+export function CommentList() {
+ const { name, comments, handleLoad, isLoading, error } = useComments();
+ const { list, nextCursor } = comments;
+
+ return (
+
+ {list.length === 0 ? (
+
+ 아직 문의가 없어요
+
+ ) : (
+
+ {list?.map((comment) => (
+
+ ))}
+
+ )}
+ {error &&
{error.message}}
+
+ {nextCursor && (
+
+ {isLoading ? (
+ 문의를 더 불러오고 있습니다.
+ ) : (
+
+ )}
+
+ )}
+
+ );
+}
diff --git a/src/components/Comment/index.ts b/src/components/Comment/index.ts
new file mode 100644
index 000000000..64e566826
--- /dev/null
+++ b/src/components/Comment/index.ts
@@ -0,0 +1,4 @@
+export * from "./Comment";
+export * from "./CommentList";
+export * from "./CommentAdd";
+export * from "./CommentForm";
diff --git a/src/components/Comment/useComment.ts b/src/components/Comment/useComment.ts
new file mode 100644
index 000000000..150bc5692
--- /dev/null
+++ b/src/components/Comment/useComment.ts
@@ -0,0 +1,53 @@
+import { addComment, removeComment, updateComment } from "@service/comments";
+import { BoardName, Comment } from "@type/comment";
+import { CommentFormType } from "@schemas/comment";
+import { useParams } from "next/navigation";
+import { useSession } from "next-auth/react";
+
+export default function useComment(name: BoardName, comment?: Comment) {
+ const { data: session } = useSession();
+ const { id } = useParams();
+ const productId = Number(id);
+ const isOwner = comment && Number(session?.user?.id) === comment.writer.id;
+
+ async function handleSubmit(data: CommentFormType) {
+ try {
+ await addComment(name, productId, data);
+ } catch (err) {
+ throw err;
+ }
+ }
+
+ async function handleUpdate(data: CommentFormType) {
+ if (!comment) return;
+
+ if (!isOwner) {
+ return alert("작성자만 수정이 가능합니다.");
+ }
+
+ try {
+ await updateComment(comment.id, data);
+ } catch (err) {
+ throw err;
+ }
+ }
+
+ async function handleDelete() {
+ if (!comment) return;
+
+ if (!isOwner) {
+ return alert("작성자만 삭제가 가능합니다.");
+ }
+
+ if (confirm("정말 삭제할까요?")) {
+ try {
+ await removeComment(comment.id);
+ alert("문의를 삭제했습니다.");
+ } catch (err) {
+ console.log(err);
+ }
+ }
+ }
+
+ return { isOwner, handleSubmit, handleUpdate, handleDelete };
+}
diff --git a/src/components/Comment/useComments.ts b/src/components/Comment/useComments.ts
new file mode 100644
index 000000000..58a924cf3
--- /dev/null
+++ b/src/components/Comment/useComments.ts
@@ -0,0 +1,45 @@
+import { useState } from "react";
+import useAsync from "@hooks/useAsync";
+import { getComments } from "@service/comments";
+import { BoardName, CommentList } from "@type/comment";
+import { useParams } from "next/navigation";
+
+export default function useComments(
+ name: BoardName,
+ initialComments: CommentList
+) {
+ const { id: productId } = useParams();
+ const [comments, setComments] = useState(initialComments);
+ const { isLoading, error, wrappedFn: getData } = useAsync(getComments);
+
+ async function handleLoad() {
+ try {
+ const result = await getData(name, {
+ productId: Number(productId),
+ cursor: comments.nextCursor,
+ });
+
+ if (!result) return;
+
+ const { list, nextCursor: newCursor } = result;
+
+ setComments((prev) => ({
+ ...prev,
+ nextCursor: newCursor,
+ list: [...prev.list, ...list],
+ }));
+ } catch (err) {
+ console.log(err);
+ }
+ }
+
+ async function refreshComments() {
+ const data = await getComments(name, {
+ productId: Number(productId),
+ limit: 5,
+ });
+ setComments(data);
+ }
+
+ return { comments, handleLoad, refreshComments, isLoading, error };
+}
diff --git a/src/components/Field/Error.module.scss b/src/components/Field/Error.module.scss
new file mode 100644
index 000000000..cbd219cad
--- /dev/null
+++ b/src/components/Field/Error.module.scss
@@ -0,0 +1,7 @@
+.item-error {
+ margin-top: 0.8rem;
+ padding-left: 1.6rem;
+ font-size: 1.4rem;
+ font-weight: 600;
+ color: var(--color-error-100);
+}
diff --git a/src/components/Field/Error.tsx b/src/components/Field/Error.tsx
new file mode 100644
index 000000000..974788447
--- /dev/null
+++ b/src/components/Field/Error.tsx
@@ -0,0 +1,9 @@
+import styles from "./Error.module.scss";
+
+export function Error({ error }: { error: string }) {
+ return (
+
+ {error || "오류가 발생했습니다."}
+
+ );
+}
diff --git a/src/components/Field/FieldItem.module.scss b/src/components/Field/FieldItem.module.scss
new file mode 100644
index 000000000..2a7170406
--- /dev/null
+++ b/src/components/Field/FieldItem.module.scss
@@ -0,0 +1,26 @@
+@use "@assets/scss/base/mixins";
+
+.form-item {
+ margin-bottom: 2.4rem;
+ position: relative;
+
+ @include mixins.mobile {
+ margin-bottom: 1.6rem;
+ }
+
+ .item-label {
+ display: inline-block;
+ margin-bottom: 1.6rem;
+ font-size: 1.8rem;
+ font-weight: 700;
+
+ @include mixins.mobile {
+ margin-bottom: 0.8rem;
+ font-size: 1.4rem;
+ }
+ }
+
+ .item-field {
+ position: relative;
+ }
+}
diff --git a/src/components/Field/FieldItem.tsx b/src/components/Field/FieldItem.tsx
new file mode 100644
index 000000000..3a9afcd5c
--- /dev/null
+++ b/src/components/Field/FieldItem.tsx
@@ -0,0 +1,22 @@
+import { ReactNode } from "react";
+import styles from "./FieldItem.module.scss";
+
+export function FieldItem({ children }: { children: ReactNode }) {
+ return {children}
;
+}
+
+export function Label({
+ htmlFor,
+ children,
+}: {
+ htmlFor?: string;
+ children: ReactNode;
+}) {
+ return (
+
+ );
+}
+
+FieldItem.Label = Label;
diff --git a/src/components/Field/Form.tsx b/src/components/Field/Form.tsx
new file mode 100644
index 000000000..c2698847f
--- /dev/null
+++ b/src/components/Field/Form.tsx
@@ -0,0 +1,21 @@
+import { FormEvent, ReactNode } from "react";
+import { Alert, LoadingSpinner } from "@components/ui";
+
+interface FormProps {
+ isLoading: boolean;
+ error: Error | null;
+ onSubmit: (e: FormEvent) => void;
+ children: ReactNode;
+}
+
+export function Form({ isLoading, error, onSubmit, children }: FormProps) {
+ return (
+ <>
+ {isLoading && }
+ {error && (
+ {error.message || "오류가 발생했습니다."}
+ )}
+
+ >
+ );
+}
diff --git a/src/components/Field/ImageUpload.module.scss b/src/components/Field/ImageUpload.module.scss
new file mode 100644
index 000000000..a6040124e
--- /dev/null
+++ b/src/components/Field/ImageUpload.module.scss
@@ -0,0 +1,42 @@
+.thumbnail-list {
+ display: flex;
+ gap: 2.4rem;
+}
+
+.upload-button {
+ overflow: hidden;
+ position: relative;
+ display: block;
+ width: 100%;
+ max-width: 28.2rem;
+ border-radius: 1.6rem;
+ background: var(--color-secondary-100);
+ cursor: pointer;
+
+ &:before {
+ content: "";
+ display: block;
+ width: 100%;
+ height: 0;
+ padding-bottom: 100%;
+ }
+
+ .upload-label {
+ position: absolute;
+ left: 0;
+ top: 0;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 1.3rem;
+ width: 100%;
+ height: 100%;
+ color: var(--color-secondary-400);
+ }
+}
+
+.preview {
+ max-width: 28.2rem;
+ width: 100%;
+}
diff --git a/src/components/Field/ImageUpload.tsx b/src/components/Field/ImageUpload.tsx
new file mode 100644
index 000000000..e4cd41b7a
--- /dev/null
+++ b/src/components/Field/ImageUpload.tsx
@@ -0,0 +1,80 @@
+import { ChangeEvent, forwardRef, useEffect, useRef } from "react";
+import { Thumbnail } from "@components/ui";
+import { Error } from "@components/Field";
+import iconPlus from "@assets/img/icon/icon_plus.svg";
+import styles from "./ImageUpload.module.scss";
+import Image from "next/image";
+
+interface ImageUploadProps {
+ value: (File | string)[];
+ onChange: (file: (File | string)[]) => void;
+ error?: string;
+ placeholder?: string;
+}
+
+export const ImageUpload = forwardRef(
+ ({ value, onChange, error, placeholder }: ImageUploadProps, _) => {
+ const preview =
+ value?.[0] instanceof File ? URL.createObjectURL(value[0]) : value?.[0];
+ const fileRef = useRef(null);
+
+ useEffect(() => {
+ return () => {
+ if (preview && value?.[0] instanceof File) {
+ URL.revokeObjectURL(preview);
+ }
+ };
+ }, [preview, value]);
+
+ function handleChange(e: ChangeEvent) {
+ if (!e.target.files) return;
+
+ const files = e.target.files;
+
+ onChange(Array.from(files));
+
+ if (fileRef.current) {
+ fileRef.current.value = "";
+ }
+ }
+
+ function handleRemove() {
+ if (!fileRef.current) return;
+
+ fileRef.current.value = "";
+ onChange([]);
+ }
+
+ return (
+ <>
+
+
+
+ {preview && (
+
+ )}
+
+
+ {error && }
+ >
+ );
+ }
+);
+
+ImageUpload.displayName = "ImageUpload";
diff --git a/src/components/Field/Input.module.scss b/src/components/Field/Input.module.scss
new file mode 100644
index 000000000..4c42bdd57
--- /dev/null
+++ b/src/components/Field/Input.module.scss
@@ -0,0 +1,87 @@
+@use "@assets/scss/base/mixins";
+
+.field {
+ position: relative;
+
+ .field-box {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ height: 5.6rem;
+ padding: 0 2.4rem;
+ border: 1px solid transparent;
+ border-radius: 12px;
+ background: var(--color-secondary-100);
+
+ &:focus,
+ &.valid {
+ border: 1px solid var(--color-primary-100);
+ outline: none;
+ }
+
+ &.error {
+ border: 1px solid var(--color-error-100);
+ outline: none;
+ }
+
+ &::placeholder {
+ color: var(--color-secondary-400);
+ }
+
+ &:has(~ button) {
+ padding-right: 5rem;
+ }
+ }
+
+ textarea.field-box {
+ height: 28.2rem;
+ padding: 1.8rem 2.4rem;
+ resize: none;
+ line-height: 1.625;
+ }
+
+ textarea.sm {
+ height: 10.4rem;
+
+ @include mixins.mobile {
+ height: 13rem;
+ }
+ }
+}
+
+.item-btn {
+ position: absolute;
+ top: 50%;
+ right: 2.4rem;
+ transform: translateY(-50%);
+ width: 2.4rem;
+ height: 2.4rem;
+ background-repeat: no-repeat;
+ background-size: 100% auto;
+ background-position: center;
+}
+
+.visibility-btn .icon-visibility-off,
+.visibility-btn.on .icon-visibility-on {
+ display: none;
+}
+
+.visibility-btn.on .icon-visibility-off {
+ display: block;
+}
+
+.formatted {
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ pointer-events: none;
+}
+
+input[type="number"]:focus ~ .formatted {
+ display: none;
+}
+.placeholder {
+ color: var(--color-secondary-400);
+}
diff --git a/src/components/Field/Input.tsx b/src/components/Field/Input.tsx
new file mode 100644
index 000000000..9d796e7c0
--- /dev/null
+++ b/src/components/Field/Input.tsx
@@ -0,0 +1,61 @@
+import { forwardRef, InputHTMLAttributes, useState } from "react";
+import Image from "next/image";
+import clsx from "clsx";
+import { Error } from "@components/Field";
+import iconViewOn from "@assets/img/icon/icon_view_on.svg";
+import iconViewOff from "@assets/img/icon/icon_view_off.svg";
+import styles from "./Input.module.scss";
+
+interface InputProps extends InputHTMLAttributes {
+ value: string;
+ isValid: boolean;
+ error?: string;
+}
+
+export const Input = forwardRef(function Input(
+ { type = "text", value, onChange, isValid, error, ...props },
+ ref
+) {
+ const [currentType, setCurrentType] = useState(type);
+ const valid = isValid && value;
+ const css = clsx(
+ styles["field-box"],
+ valid && styles.valid,
+ error && styles.error
+ );
+ function handleVisibility() {
+ setCurrentType((prev) => (prev === "password" ? "text" : "password"));
+ }
+
+ return (
+ <>
+
+
+ {type === "password" && (
+
+ )}
+
+ {error && }
+ >
+ );
+});
diff --git a/src/components/Field/NumberInput.tsx b/src/components/Field/NumberInput.tsx
new file mode 100644
index 000000000..99db5283e
--- /dev/null
+++ b/src/components/Field/NumberInput.tsx
@@ -0,0 +1,60 @@
+import { forwardRef, InputHTMLAttributes } from "react";
+import clsx from "clsx";
+import { Error } from "@components/Field";
+import styles from "./Input.module.scss";
+import { toWon } from "@util/formatter";
+
+interface NumberInputProps extends InputHTMLAttributes {
+ value: number;
+ isValid: boolean;
+ error?: string;
+}
+
+export const NumberInput = forwardRef(
+ (
+ {
+ value,
+ onChange,
+ error,
+ isValid,
+ placeholder,
+ ...props
+ }: NumberInputProps,
+ ref
+ ) => {
+ const valid = isValid && value;
+ const css = clsx(
+ styles["field-box"],
+ valid && styles.valid,
+ error && styles.error
+ );
+
+ const formattedCss = clsx(
+ css,
+ styles.formatted,
+ !value && styles.placeholder
+ );
+
+ return (
+ <>
+
+
+
+ {value ? toWon(value) : placeholder}
+
+
+ {error && }
+ >
+ );
+ }
+);
+
+NumberInput.displayName = "NumberInput";
diff --git a/src/components/Field/TagsInput.tsx b/src/components/Field/TagsInput.tsx
new file mode 100644
index 000000000..6c1d5fc69
--- /dev/null
+++ b/src/components/Field/TagsInput.tsx
@@ -0,0 +1,67 @@
+import { forwardRef, KeyboardEvent, useRef } from "react";
+import clsx from "clsx";
+import { Tags } from "@components/ui";
+import { Error } from "@components/Field";
+import styles from "./Input.module.scss";
+import { Tags as TagsType } from "@type/product";
+
+interface TagsInputProps {
+ value: TagsType;
+ onChange: (tags: TagsType) => void;
+ placeholder?: string;
+ isValid: boolean;
+ error?: string;
+}
+
+export const TagsInput = forwardRef(
+ (
+ { value, onChange, error, isValid, placeholder = "" }: TagsInputProps,
+ _
+ ) => {
+ const inputRef = useRef(null);
+ const valid = isValid && value.length;
+ const css = clsx(
+ styles["field-box"],
+ valid && styles.valid,
+ error && styles.error
+ );
+
+ function handleKeyDown(e: KeyboardEvent) {
+ if (e.nativeEvent.isComposing) return;
+
+ if (e.key === "Enter") {
+ e.preventDefault();
+ if (!inputRef.current) return;
+
+ const tag = inputRef.current.value.trim();
+ if (tag && !value.includes(tag)) {
+ const newTags = [...value, tag];
+ onChange(newTags);
+ }
+ inputRef.current.value = "";
+ }
+ }
+
+ function handleRemove(tag: string) {
+ const newTags = value.filter((item) => item !== tag);
+ onChange(newTags);
+ }
+ return (
+ <>
+
+
+
+
+ {error && }
+ >
+ );
+ }
+);
+
+TagsInput.displayName = "TagsInput";
diff --git a/src/components/Field/Textarea.tsx b/src/components/Field/Textarea.tsx
new file mode 100644
index 000000000..faf8f427e
--- /dev/null
+++ b/src/components/Field/Textarea.tsx
@@ -0,0 +1,40 @@
+import { forwardRef, TextareaHTMLAttributes } from "react";
+import clsx from "clsx";
+import { Error } from "@components/Field";
+import styles from "./Input.module.scss";
+
+interface TextareaProps extends TextareaHTMLAttributes {
+ value: string;
+ size?: "sm" | "lg";
+ isValid: boolean;
+ error?: string;
+}
+
+export const Textarea = forwardRef(
+ ({ error, isValid, value, onChange, size, ...props }: TextareaProps, ref) => {
+ const valid = isValid && value;
+ const css = clsx(
+ styles["field-box"],
+ size && styles[size],
+ valid && styles.valid,
+ error && styles.error
+ );
+
+ return (
+ <>
+
+
+
+ {error && }
+ >
+ );
+ }
+);
+
+Textarea.displayName = "Textarea";
diff --git a/src/components/Field/index.ts b/src/components/Field/index.ts
new file mode 100644
index 000000000..f3dce48a4
--- /dev/null
+++ b/src/components/Field/index.ts
@@ -0,0 +1,8 @@
+export * from "./Form";
+export * from "./Error";
+export * from "./FieldItem";
+export * from "./Input";
+export * from "./Textarea";
+export * from "./TagsInput";
+export * from "./ImageUpload";
+export * from "./NumberInput";
diff --git a/src/components/Footer/Footer.module.scss b/src/components/Footer/Footer.module.scss
new file mode 100644
index 000000000..23ba38c00
--- /dev/null
+++ b/src/components/Footer/Footer.module.scss
@@ -0,0 +1,64 @@
+@use "@assets/scss/base/mixins";
+
+.footer {
+ padding: 3.2rem calc(20rem - var(--gutter)) 10.8rem;
+ background: var(--color-secondary-900);
+ color: var(--color-white);
+
+ @include mixins.tablet {
+ padding: 3.2rem calc(10.4rem - var(--gutter)) 10.8rem;
+ }
+
+ @include mixins.mobile {
+ padding: 3.2rem calc(3.2rem - var(--gutter));
+ }
+
+ .inner {
+ @include mixins.inner;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ @include mixins.mobile {
+ flex-wrap: wrap;
+ gap: 6rem 0;
+ }
+ }
+
+ .copyright {
+ color: var(--color-secondary-400);
+
+ @include mixins.mobile {
+ order: 3;
+ width: 100%;
+ }
+ }
+
+ .footer-nav-list {
+ display: flex;
+ align-items: center;
+ gap: 3rem;
+
+ .nav-item {
+ color: var(--color-secondary-200);
+ }
+ }
+
+ .sns-list {
+ display: flex;
+ align-items: center;
+ gap: 1.2rem;
+
+ .sns-item {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 2rem;
+ height: 2rem;
+
+ img {
+ width: 100%;
+ }
+ }
+ }
+}
diff --git a/src/components/Footer/Footer.tsx b/src/components/Footer/Footer.tsx
new file mode 100644
index 000000000..ccb98d06f
--- /dev/null
+++ b/src/components/Footer/Footer.tsx
@@ -0,0 +1,82 @@
+import Link from "next/link";
+import Image from "next/image";
+import styles from "./Footer.module.scss";
+
+import facebookIcon from "@assets/img/icon/icon_facebook.svg";
+import twitterIcon from "@assets/img/icon/icon_twitter.svg";
+import youtubeIcon from "@assets/img/icon/icon_youtube.svg";
+import instagramIcon from "@assets/img/icon/icon_instagram.svg";
+
+export function Footer() {
+ return (
+
+ );
+}
diff --git a/src/components/Footer/index.ts b/src/components/Footer/index.ts
new file mode 100644
index 000000000..5fca53f7d
--- /dev/null
+++ b/src/components/Footer/index.ts
@@ -0,0 +1 @@
+export * from "./Footer";
diff --git a/src/components/Header/Header.module.scss b/src/components/Header/Header.module.scss
new file mode 100644
index 000000000..157db45e2
--- /dev/null
+++ b/src/components/Header/Header.module.scss
@@ -0,0 +1,24 @@
+@use "@assets/scss/base/mixins";
+
+.header {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ z-index: 100;
+ height: 7rem;
+ padding: 0 calc(20rem - var(--gutter));
+ border-bottom: 1px solid var(--color-grey);
+ background: #fff;
+
+ @include mixins.tablet {
+ padding: 0;
+ }
+
+ .nav {
+ @include mixins.inner;
+ display: flex;
+ align-items: center;
+ height: 100%;
+ }
+}
diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx
new file mode 100644
index 000000000..47d09105a
--- /dev/null
+++ b/src/components/Header/Header.tsx
@@ -0,0 +1,10 @@
+import { ReactNode } from "react";
+import styles from "./Header.module.scss";
+
+export function Header({ children }: { children: ReactNode }) {
+ return (
+
+ );
+}
diff --git a/src/components/Header/Logo.module.scss b/src/components/Header/Logo.module.scss
new file mode 100644
index 000000000..6f8d31d25
--- /dev/null
+++ b/src/components/Header/Logo.module.scss
@@ -0,0 +1,36 @@
+@use "@assets/scss/base/mixins";
+
+.logo {
+ display: block;
+ height: 5.1rem;
+ margin-right: 3.2rem;
+
+ @include mixins.mobile {
+ height: auto;
+ margin-right: 1rem;
+ }
+
+ a {
+ display: block;
+ height: 100%;
+ }
+
+ img {
+ width: auto;
+ height: 100%;
+
+ &.logo-pc {
+ @include mixins.mobile {
+ display: none;
+ }
+ }
+
+ &.logo-mobile {
+ display: none;
+
+ @include mixins.mobile {
+ display: block;
+ }
+ }
+ }
+}
diff --git a/src/components/Header/Logo.tsx b/src/components/Header/Logo.tsx
new file mode 100644
index 000000000..c39e4d50a
--- /dev/null
+++ b/src/components/Header/Logo.tsx
@@ -0,0 +1,20 @@
+import Link from "next/link";
+import Image from "next/image";
+import logoPC from "@assets/img/common/logo_full.svg";
+import logoMobile from "@assets/img/common/logo_text.svg";
+import styles from "./Logo.module.scss";
+
+export function Logo() {
+ return (
+
+
+
+
+
+
+ );
+}
diff --git a/src/components/Header/Nav.module.scss b/src/components/Header/Nav.module.scss
new file mode 100644
index 000000000..46b4ac107
--- /dev/null
+++ b/src/components/Header/Nav.module.scss
@@ -0,0 +1,26 @@
+@use "@assets/scss/base/mixins";
+
+.gnb {
+ display: flex;
+ height: 100%;
+
+ .gnb-item {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 100%;
+ padding: 0 1.5rem;
+ font-size: 1.8rem;
+ font-weight: 700;
+ color: var(--color-secondary-600);
+
+ @include mixins.mobile {
+ padding: 0.4rem;
+ font-size: 1.6rem;
+ }
+ }
+
+ .active {
+ color: var(--color-primary-100);
+ }
+}
diff --git a/src/components/Header/Nav.tsx b/src/components/Header/Nav.tsx
new file mode 100644
index 000000000..7ebbdc2ab
--- /dev/null
+++ b/src/components/Header/Nav.tsx
@@ -0,0 +1,49 @@
+"use client";
+
+import { usePathname } from "next/navigation";
+import Link from "next/link";
+import clsx from "clsx";
+import styles from "./Nav.module.scss";
+
+const MENU = [
+ {
+ path: "/boards",
+ title: "자유게시판",
+ activePathList: ["/boards", "/addboard", "/board"],
+ },
+ {
+ path: "/items",
+ reload: true,
+ title: "중고마켓",
+ activePathList: ["/items", "/addItem", "/modifyItem"],
+ },
+];
+
+function isInclude(path: string, list: string[] = []) {
+ return list.some((item) => path.startsWith(item));
+}
+
+export function Nav() {
+ const pathname = usePathname();
+
+ return (
+
+ {MENU.map((item) => {
+ return (
+ -
+
+ {item.title}
+
+
+ );
+ })}
+
+ );
+}
diff --git a/src/components/Header/Profile.tsx b/src/components/Header/Profile.tsx
new file mode 100644
index 000000000..921c60833
--- /dev/null
+++ b/src/components/Header/Profile.tsx
@@ -0,0 +1,26 @@
+import { Dropdown, Avatar } from "@components/ui";
+import { signOut } from "next-auth/react";
+
+interface ProfileProps {
+ nickname: string;
+ image: string;
+}
+
+export function Profile({ nickname, image }: ProfileProps) {
+ function handleLogout() {
+ if (confirm("정말로 로그아웃 하시겠습니까?")) {
+ signOut();
+ }
+ }
+
+ return (
+
+
+
+
+
+ 로그아웃
+
+
+ );
+}
diff --git a/src/components/Header/Util.module.scss b/src/components/Header/Util.module.scss
new file mode 100644
index 000000000..abea0d8fc
--- /dev/null
+++ b/src/components/Header/Util.module.scss
@@ -0,0 +1,8 @@
+.util {
+ flex: none;
+ margin-left: auto;
+
+ .login-btn {
+ width: 12.8rem;
+ }
+}
diff --git a/src/components/Header/Util.tsx b/src/components/Header/Util.tsx
new file mode 100644
index 000000000..e5f1b3a1a
--- /dev/null
+++ b/src/components/Header/Util.tsx
@@ -0,0 +1,25 @@
+"use client";
+
+import { Button } from "@components/ui";
+import { Profile } from "@components/Header";
+import styles from "./Util.module.scss";
+import { useSession } from "next-auth/react";
+
+export function Util() {
+ const { data: session } = useSession();
+
+ return (
+
+ {session?.user ? (
+
+ ) : (
+
+ )}
+
+ );
+}
diff --git a/src/components/Header/index.ts b/src/components/Header/index.ts
new file mode 100644
index 000000000..9af4766cf
--- /dev/null
+++ b/src/components/Header/index.ts
@@ -0,0 +1,5 @@
+export * from "./Header";
+export * from "./Logo";
+export * from "./Nav";
+export * from "./Profile";
+export * from "./Util";
diff --git a/src/components/Page/PageWrapper.module.scss b/src/components/Page/PageWrapper.module.scss
new file mode 100644
index 000000000..158d06061
--- /dev/null
+++ b/src/components/Page/PageWrapper.module.scss
@@ -0,0 +1,6 @@
+@use "@assets/scss/base/mixins";
+
+.container {
+ @include mixins.inner;
+ margin: 2.4rem auto 10rem;
+}
diff --git a/src/components/Page/PageWrapper.tsx b/src/components/Page/PageWrapper.tsx
new file mode 100644
index 000000000..15b01560e
--- /dev/null
+++ b/src/components/Page/PageWrapper.tsx
@@ -0,0 +1,6 @@
+import { ReactNode } from "react";
+import styles from "./PageWrapper.module.scss";
+
+export function PageWrapper({ children }: { children: ReactNode }) {
+ return {children}
;
+}
diff --git a/src/components/Page/index.ts b/src/components/Page/index.ts
new file mode 100644
index 000000000..d6a489213
--- /dev/null
+++ b/src/components/Page/index.ts
@@ -0,0 +1 @@
+export * from "./PageWrapper";
diff --git a/src/components/Pagination/Pagination.module.scss b/src/components/Pagination/Pagination.module.scss
new file mode 100644
index 000000000..77e367fcb
--- /dev/null
+++ b/src/components/Pagination/Pagination.module.scss
@@ -0,0 +1,34 @@
+.list {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 4px;
+ margin: 4rem 0;
+
+ .item {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 4rem;
+ height: 4rem;
+ border-radius: 50%;
+ border: 1px solid var(--color-secondary-200);
+ font-weight: 600;
+ color: var(--color-secondary-500);
+
+ &:hover {
+ background: var(--color-secondary-100);
+ }
+
+ &.active {
+ border-color: var(--color-primary-200);
+ background: var(--color-primary-200);
+ color: var(--color-white);
+ }
+
+ &:disabled {
+ opacity: 0.3;
+ }
+ }
+}
diff --git a/src/components/Pagination/Pagination.tsx b/src/components/Pagination/Pagination.tsx
new file mode 100644
index 000000000..e7bd5b5dd
--- /dev/null
+++ b/src/components/Pagination/Pagination.tsx
@@ -0,0 +1,95 @@
+import { MouseEvent } from "react";
+import Image from "next/image";
+import clsx from "clsx";
+import arrowLeft from "@assets/img/icon/icon_arrow_left.svg";
+import arrowRight from "@assets/img/icon/icon_arrow_right.svg";
+import doubleArrowLeft from "@assets/img/icon/icon_double_arrow_left.svg";
+import doubleArrowRight from "@assets/img/icon/icon_double_arrow_right.svg";
+import styles from "./Pagination.module.scss";
+
+interface PaginationProps {
+ page: number;
+ pageNumbers: number[];
+ isPrevDisabled: boolean;
+ isNextDisabled: boolean;
+ isPrevGroupDisabled: boolean;
+ isNextGroupDisabled: boolean;
+ onPrevClick: () => void;
+ onNextClick: () => void;
+ onPageClick: (e: MouseEvent) => void;
+ onPrevGroupClick: () => void;
+ onNextGroupClick: () => void;
+}
+
+export function Pagination({
+ page,
+ pageNumbers,
+ isPrevDisabled,
+ isNextDisabled,
+ isPrevGroupDisabled,
+ isNextGroupDisabled,
+ onPrevClick,
+ onNextClick,
+ onPageClick,
+ onPrevGroupClick,
+ onNextGroupClick,
+}: PaginationProps) {
+ if (!pageNumbers.length) return null;
+
+ return (
+
+ -
+
+
+ -
+
+
+ {pageNumbers.map((number) => (
+ -
+
+
+ ))}
+ -
+
+
+ -
+
+
+
+ );
+}
diff --git a/src/components/Pagination/index.ts b/src/components/Pagination/index.ts
new file mode 100644
index 000000000..8404fe460
--- /dev/null
+++ b/src/components/Pagination/index.ts
@@ -0,0 +1 @@
+export * from "./Pagination";
diff --git a/src/components/Search/Recent.module.scss b/src/components/Search/Recent.module.scss
new file mode 100644
index 000000000..a26dd8072
--- /dev/null
+++ b/src/components/Search/Recent.module.scss
@@ -0,0 +1,96 @@
+.container {
+ position: relative;
+
+ .modal {
+ z-index: 1;
+ position: absolute;
+ top: 5rem;
+ width: 100%;
+ border-radius: 1.2rem;
+ background: var(--color-secondary-100);
+ font-size: 1.3rem;
+ box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
+
+ .header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 1.2em 1em 1em;
+ font-size: 1.2rem;
+
+ .title {
+ color: var(--color-secondary-500);
+ }
+
+ .button {
+ opacity: 0.3;
+
+ &:hover {
+ opacity: 1;
+ }
+ }
+ }
+
+ .empty {
+ padding: 1em;
+ text-align: center;
+ color: var(--color-secondary-400);
+ }
+
+ .list {
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+ padding: 3px;
+
+ .item {
+ display: flex;
+ align-items: center;
+ padding: 0.8em 1em;
+ border-radius: 4px;
+ cursor: pointer;
+
+ &:hover {
+ background: var(--color-secondary-200);
+ }
+
+ .content {
+ flex: 1;
+ overflow: hidden;
+ padding: 0 1em 0 4px;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+
+ .button {
+ flex: none;
+ margin-left: auto;
+ font-size: 1.2rem;
+ opacity: 0.3;
+
+ &:hover {
+ opacity: 1;
+ }
+ }
+ }
+ }
+
+ .control {
+ display: flex;
+ justify-content: flex-end;
+ margin-top: 1em;
+ padding: 1em;
+ border-top: 1px solid var(--color-secondary-200);
+ font-size: 1.2rem;
+
+ .button {
+ font-size: 1.2rem;
+ opacity: 0.3;
+
+ &:hover {
+ opacity: 1;
+ }
+ }
+ }
+ }
+}
diff --git a/src/components/Search/Recent.tsx b/src/components/Search/Recent.tsx
new file mode 100644
index 000000000..0c567c4f8
--- /dev/null
+++ b/src/components/Search/Recent.tsx
@@ -0,0 +1,106 @@
+import { cloneElement, ReactElement, useEffect, useRef, useState } from "react";
+import searchIcon from "@assets/img/icon/icon_search.svg";
+import styles from "./Recent.module.scss";
+import Image from "next/image";
+
+interface RecentProps {
+ title: string;
+ data: string[];
+ onItemClick: (value: string) => void;
+ onItemRemove: (value: string) => void;
+ onItemClear: () => void;
+ children: ReactElement<{
+ onOpenRecent: () => void;
+ onCloseRecent: () => void;
+ }>;
+}
+
+export function Recent({
+ title,
+ data,
+ onItemClick,
+ onItemRemove,
+ onItemClear,
+ children,
+}: RecentProps) {
+ const [isOpen, setIsOpen] = useState(false);
+ const modalRef = useRef(null);
+
+ useEffect(() => {
+ function handleClickOutside(e: MouseEvent) {
+ if (modalRef.current && !modalRef.current.contains(e.target as Node)) {
+ setIsOpen(false);
+ }
+ }
+ document.addEventListener("click", handleClickOutside);
+
+ return () => {
+ document.removeEventListener("click", handleClickOutside);
+ };
+ }, []);
+
+ function handleClick(keyword: string) {
+ onItemClick(keyword);
+ setIsOpen(false);
+ }
+
+ function handleRemove(e: React.MouseEvent, keyword: string) {
+ e.stopPropagation();
+ onItemRemove(keyword);
+ }
+
+ return (
+
+ {cloneElement(children, {
+ onOpenRecent: () => setIsOpen(true),
+ onCloseRecent: () => setIsOpen(false),
+ })}
+ {isOpen && (
+
+
+ {data.length === 0 && (
+
최근 검색어가 없습니다.
+ )}
+
+ {data?.map((keyword) => (
+ -
+
handleClick(keyword)}
+ >
+
+
{keyword}
+
+
+
+ ))}
+
+
+
+
+
+ )}
+
+ );
+}
diff --git a/src/components/Search/Search.module.scss b/src/components/Search/Search.module.scss
new file mode 100644
index 000000000..1b1f8056d
--- /dev/null
+++ b/src/components/Search/Search.module.scss
@@ -0,0 +1,35 @@
+@use "@assets/scss/base/mixins";
+
+.container {
+ position: relative;
+ width: 100%;
+
+ .search {
+ overflow: hidden;
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ height: 4.2rem;
+ padding: 0 1.6rem;
+ border-radius: 1.2rem;
+ background: var(--color-secondary-100);
+
+ &:has(:focus) {
+ outline: 1px solid var(--color-secondary-400);
+ }
+
+ .input {
+ flex: 1;
+ background: transparent;
+
+ &:focus {
+ outline: none;
+ border: none;
+ }
+
+ &::placeholder {
+ color: var(--color-secondary-400);
+ }
+ }
+ }
+}
diff --git a/src/components/Search/Search.tsx b/src/components/Search/Search.tsx
new file mode 100644
index 000000000..2cdc09dd5
--- /dev/null
+++ b/src/components/Search/Search.tsx
@@ -0,0 +1,69 @@
+import { ChangeEvent, FormEvent, useRef } from "react";
+import Image from "next/image";
+import searchIcon from "@assets/img/icon/icon_search.svg";
+import clearIcon from "@assets/img/icon/icon_clear.svg";
+import styles from "./Search.module.scss";
+
+interface SearchProps {
+ value: string;
+ onChange: (e: ChangeEvent) => void;
+ onSubmit: () => void;
+ onClear: () => void;
+ placeholder: string;
+ onOpenRecent?: () => void;
+ onCloseRecent?: () => void;
+}
+
+export function Search({
+ value,
+ onChange,
+ onSubmit,
+ onClear,
+ placeholder,
+ onOpenRecent,
+ onCloseRecent,
+}: SearchProps) {
+ const inputRef = useRef(null);
+
+ function handleSubmit(e: FormEvent) {
+ e.preventDefault();
+ onSubmit();
+ inputRef.current?.blur();
+ if (onCloseRecent) {
+ onCloseRecent();
+ }
+ }
+
+ function handleClear() {
+ onClear();
+ inputRef.current?.blur();
+ }
+
+ function handleFocus() {
+ if (onOpenRecent) {
+ onOpenRecent();
+ }
+ }
+
+ return (
+
+
+
+ );
+}
diff --git a/src/components/Search/index.ts b/src/components/Search/index.ts
new file mode 100644
index 000000000..6b11e2236
--- /dev/null
+++ b/src/components/Search/index.ts
@@ -0,0 +1,2 @@
+export * from "./Search";
+export * from "./Recent";
diff --git a/src/components/Section/Section.module.scss b/src/components/Section/Section.module.scss
new file mode 100644
index 000000000..7f16625a3
--- /dev/null
+++ b/src/components/Section/Section.module.scss
@@ -0,0 +1,31 @@
+@use "@assets/scss/base/mixins";
+
+.section {
+ position: relative;
+ margin-bottom: 4rem;
+}
+
+.header {
+ display: flex;
+ align-items: center;
+ gap: 0.8rem 1.2rem;
+ margin-bottom: 2.4rem;
+
+ @include mixins.mobile {
+ flex-wrap: wrap;
+ justify-content: flex-end;
+ }
+}
+
+.title {
+ flex: none;
+ margin-right: auto;
+ font-size: 2rem;
+ font-weight: 700;
+ color: var(--color-secondary-900);
+}
+
+.footer {
+ display: flex;
+ justify-content: flex-end;
+}
diff --git a/src/components/Section/Section.tsx b/src/components/Section/Section.tsx
new file mode 100644
index 000000000..69b1c19ea
--- /dev/null
+++ b/src/components/Section/Section.tsx
@@ -0,0 +1,27 @@
+import { ReactNode } from "react";
+import styles from "./Section.module.scss";
+
+export function Section({ children }: { children: ReactNode }) {
+ return ;
+}
+
+function Header({ title, children }: { title: string; children?: ReactNode }) {
+ return (
+
+ );
+}
+
+function Content({ children }: { children: ReactNode }) {
+ return <>{children}>;
+}
+
+function Footer({ children }: { children: ReactNode }) {
+ return {children}
;
+}
+
+Section.Header = Header;
+Section.Content = Content;
+Section.Footer = Footer;
diff --git a/src/components/Section/index.ts b/src/components/Section/index.ts
new file mode 100644
index 000000000..8d851af27
--- /dev/null
+++ b/src/components/Section/index.ts
@@ -0,0 +1 @@
+export * from "./Section";
diff --git a/src/components/adaptor/rhf/FieldAdapter.tsx b/src/components/adaptor/rhf/FieldAdapter.tsx
new file mode 100644
index 000000000..c56aaeb86
--- /dev/null
+++ b/src/components/adaptor/rhf/FieldAdapter.tsx
@@ -0,0 +1,53 @@
+import { ReactElement } from "react";
+import {
+ Control,
+ Controller,
+ FieldPath,
+ FieldPathValue,
+ FieldValues,
+ Path,
+ RefCallBack,
+} from "react-hook-form";
+
+interface FieldAdapterProps> {
+ name: U;
+ control: Control;
+ render: (props: {
+ value: FieldPathValue;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ onChange: (...event: any[]) => void;
+ onBlur: () => void;
+ ref: RefCallBack;
+ name: Path;
+ isValid: boolean;
+ error?: string;
+ }) => ReactElement;
+}
+
+export function FieldAdapter>({
+ name,
+ control,
+ render,
+}: FieldAdapterProps) {
+ return (
+
+ render({
+ ...field,
+ onChange: (e) => {
+ // rhf mode가 onBlur모드일때 벨리데이션하려면 필요 (trigger가 onblur에 되는듯함)
+ // 일반적으로 레스트파라미터로 각 input, textarea에 자동적으로 onblur가 들어가서 괜찮으나
+ // 특수하게 커스텀 컴포넌트를 이용해서 수동으로 업데이트할경우(onchange활용하여) onBlur를 해줘야 벨리데이션이 됨
+ // (useForm의 리턴값중에 setValue를 통해서 업데이트하면 벨리데이션이 됨)
+ field.onChange(e);
+ field.onBlur();
+ },
+ isValid: !fieldState.invalid,
+ error: fieldState.error?.message,
+ })
+ }
+ />
+ );
+}
diff --git a/src/components/adaptor/rhf/index.ts b/src/components/adaptor/rhf/index.ts
new file mode 100644
index 000000000..84b24eb7d
--- /dev/null
+++ b/src/components/adaptor/rhf/index.ts
@@ -0,0 +1 @@
+export * from "./FieldAdapter";
diff --git a/src/components/ui/Alert.module.scss b/src/components/ui/Alert.module.scss
new file mode 100644
index 000000000..5ccf19f6f
--- /dev/null
+++ b/src/components/ui/Alert.module.scss
@@ -0,0 +1,21 @@
+@use "@assets/scss/base/mixins";
+
+.alert {
+ display: flex;
+ align-items: center;
+ gap: 2rem;
+ padding: 2.4rem;
+ border-radius: 1.6rem;
+ margin-bottom: 2rem;
+ font-weight: 500;
+
+ &.error {
+ color: var(--color-error-100);
+ background: #fedde0;
+ }
+
+ &.warn {
+ color: #9c7700;
+ background: #fff1c2;
+ }
+}
diff --git a/src/components/ui/Alert.tsx b/src/components/ui/Alert.tsx
new file mode 100644
index 000000000..340c7196b
--- /dev/null
+++ b/src/components/ui/Alert.tsx
@@ -0,0 +1,25 @@
+import Image from "next/image";
+import { ReactNode } from "react";
+import clsx from "clsx";
+import iconError from "@assets/img/icon/icon_error.svg";
+import iconWarn from "@assets/img/icon/icon_warn.svg";
+import styles from "./Alert.module.scss";
+
+interface AlertProps {
+ mode?: "error" | "warn";
+ children: ReactNode;
+}
+
+const iconImg = {
+ warn: { src: iconWarn, alt: "경고" },
+ error: { src: iconError, alt: "에러" },
+};
+
+export function Alert({ mode = "error", children }: AlertProps) {
+ return (
+
+
+ {children}
+
+ );
+}
diff --git a/src/components/ui/Author.module.scss b/src/components/ui/Author.module.scss
new file mode 100644
index 000000000..c6f1f72e5
--- /dev/null
+++ b/src/components/ui/Author.module.scss
@@ -0,0 +1,33 @@
+.author {
+ display: flex;
+ align-items: center;
+ gap: 1.6rem;
+
+ .info {
+ font-size: 1.4rem;
+
+ .nickname {
+ margin-bottom: 2px;
+ font-weight: 500;
+ color: var(--color-secondary-600);
+ }
+ }
+
+ &.row {
+ gap: 0.8rem;
+
+ figure {
+ width: 2.4rem;
+ height: 2.4rem;
+
+ img {
+ width: 100%;
+ height: 100%;
+ }
+ }
+ .info {
+ display: flex;
+ gap: 0.8rem;
+ }
+ }
+}
diff --git a/src/components/ui/Author.tsx b/src/components/ui/Author.tsx
new file mode 100644
index 000000000..4ffd5f17c
--- /dev/null
+++ b/src/components/ui/Author.tsx
@@ -0,0 +1,29 @@
+import { Avatar, Date } from "@components/ui";
+import styles from "./Author.module.scss";
+import clsx from "clsx";
+
+interface AuthorProps {
+ avatar?: string;
+ nickname: string;
+ updatedAt: string;
+ dir?: "col" | "row";
+ mini?: boolean;
+}
+
+export function Author({
+ avatar,
+ nickname,
+ updatedAt,
+ dir = "col",
+ mini = false,
+}: AuthorProps) {
+ return (
+
+ {!mini &&
}
+
+
{nickname}
+ {!mini &&
}
+
+
+ );
+}
diff --git a/src/components/ui/Avatar.module.scss b/src/components/ui/Avatar.module.scss
new file mode 100644
index 000000000..281a79f6f
--- /dev/null
+++ b/src/components/ui/Avatar.module.scss
@@ -0,0 +1,10 @@
+.avatar {
+ width: 4rem;
+ height: 4rem;
+ border-radius: 50%;
+ overflow: hidden;
+
+ &.hover:hover {
+ outline: 2px solid var(--color-secondary-100);
+ }
+}
diff --git a/src/components/ui/Avatar.tsx b/src/components/ui/Avatar.tsx
new file mode 100644
index 000000000..679093ee0
--- /dev/null
+++ b/src/components/ui/Avatar.tsx
@@ -0,0 +1,27 @@
+import { SyntheticEvent } from "react";
+import Image from "next/image";
+import clsx from "clsx";
+import defaultAvatar from "@assets/img/icon/icon_avatar.svg";
+import styles from "./Avatar.module.scss";
+
+interface AvatarProps {
+ img: string | undefined;
+ nickname: string;
+ hover?: boolean;
+}
+
+export function Avatar({ nickname, img, hover }: AvatarProps) {
+ const avatarImg = img || defaultAvatar;
+
+ function handleError(e: SyntheticEvent) {
+ e.currentTarget.src = defaultAvatar;
+ }
+
+ const css = clsx(styles.avatar, hover && styles.hover);
+
+ return (
+
+ );
+}
diff --git a/src/components/ui/Badge.module.scss b/src/components/ui/Badge.module.scss
new file mode 100644
index 000000000..fd2549f5b
--- /dev/null
+++ b/src/components/ui/Badge.module.scss
@@ -0,0 +1,20 @@
+.badge {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 0.6rem;
+ padding: 0 2.4rem;
+ min-width: 8rem;
+ height: 3rem;
+ font-weight: 600;
+ border-radius: 0 0 1.6rem 1.6rem;
+ background: var(--color-primary-100);
+ color: var(--color-white);
+
+ img {
+ width: auto;
+ height: 1.6rem;
+ margin-top: -2px;
+ margin-left: -4px;
+ }
+}
diff --git a/src/components/ui/Badge.tsx b/src/components/ui/Badge.tsx
new file mode 100644
index 000000000..1d009d66c
--- /dev/null
+++ b/src/components/ui/Badge.tsx
@@ -0,0 +1,16 @@
+import { ReactNode } from "react";
+import styles from "./Badge.module.scss";
+
+interface BadgeProps {
+ label: string;
+ icon: ReactNode;
+}
+
+export function Badge({ label, icon }: BadgeProps) {
+ return (
+
+ {icon}
+ {label}
+
+ );
+}
diff --git a/src/components/ui/Button.module.scss b/src/components/ui/Button.module.scss
new file mode 100644
index 000000000..96483587e
--- /dev/null
+++ b/src/components/ui/Button.module.scss
@@ -0,0 +1,220 @@
+@use "@assets/scss/base/mixins";
+
+.btn {
+ display: inline-flex;
+ justify-content: center;
+ align-items: center;
+ gap: 0.8rem;
+
+ &:disabled {
+ cursor: not-allowed;
+ }
+}
+
+.solid {
+ &.primary {
+ background: var(--color-primary-100);
+ color: var(--color-white);
+
+ &:hover {
+ background: var(--color-primary-200);
+ }
+
+ &:active {
+ background: var(--color-primary-300);
+ }
+
+ &:disabled {
+ background: var(--color-secondary-400);
+ }
+ }
+
+ &.secondary {
+ background: var(--color-secondary-600);
+ color: var(--color-white);
+
+ &:hover {
+ background: var(--color-secondary-700);
+ }
+
+ &:active {
+ background: var(--color-secondary-800);
+ }
+
+ &:disabled {
+ opacity: 0.3;
+ }
+ }
+
+ &.error {
+ background: var(--color-error-100);
+ color: var(--color-white);
+
+ &:hover {
+ background: var(--color-error-200);
+ }
+
+ &:active {
+ background: var(--color-error-300);
+ }
+
+ &:disabled {
+ opacity: 0.3;
+ }
+ }
+}
+
+.outlined {
+ background: transparent;
+ color: #737373;
+ border: 1px solid;
+
+ &.primary {
+ border-color: var(--color-primary-100);
+ color: var(--color-primary-100);
+
+ &:hover {
+ border-color: var(--color-primary-200);
+ }
+
+ &:active {
+ border-color: var(--color-primary-300);
+ }
+
+ &:disabled {
+ opacity: 0.3;
+ }
+ }
+
+ &.secondary {
+ border-color: var(--color-secondary-400);
+ color: var(--color-secondary-500);
+
+ &:hover {
+ border-color: var(--color-secondary-600);
+ }
+
+ &:active {
+ border-color: var(--color-secondary-800);
+ }
+
+ &:disabled {
+ opacity: 0.3;
+ }
+ }
+
+ &.error {
+ border-color: var(--color-error-100);
+ color: var(--color-error-100);
+
+ &:hover {
+ border-color: var(--color-error-200);
+ }
+
+ &:active {
+ border-color: var(--color-error-300);
+ }
+
+ &:disabled {
+ opacity: 0.3;
+ }
+ }
+}
+
+.text {
+ &.primary {
+ background: transparent;
+ color: var(--color-primary-100);
+
+ &:hover {
+ background: var(--color-secondary-100);
+ }
+
+ &:active {
+ background: var(--color-secondary-300);
+ }
+
+ &:disabled {
+ opacity: 0.3;
+ }
+ }
+
+ &.secondary {
+ color: var(--color-secondary-500);
+
+ &:hover {
+ background: var(--color-secondary-100);
+ }
+
+ &:active {
+ background: var(--color-secondary-300);
+ }
+
+ &:disabled {
+ opacity: 0.3;
+ }
+ }
+
+ &.error {
+ color: var(--color-error-100);
+
+ &:hover {
+ background: var(--color-secondary-100);
+ }
+
+ &:active {
+ background: var(--color-secondary-300);
+ }
+
+ &:disabled {
+ opacity: 0.3;
+ }
+ }
+}
+
+.xl {
+ width: 100%;
+ height: 5.6rem;
+ border-radius: 9999px;
+ font-size: 2rem;
+ font-weight: 600;
+}
+
+.lg {
+ width: 35.7rem;
+ height: 5.6rem;
+ border-radius: 9999px;
+ font-size: 2rem;
+ font-weight: 600;
+
+ @include mixins.mobile {
+ width: 24rem;
+ height: 4.8rem;
+ font-size: 1.8rem;
+ }
+}
+
+.md {
+ width: 24rem;
+ height: 4.8rem;
+ border-radius: 9999px;
+ font-size: 1.8rem;
+ font-weight: 600;
+}
+
+.sm {
+ min-width: 8.8rem;
+ height: 4.2rem;
+ padding: 0 2.4rem;
+ border-radius: 8px;
+ font-size: 1.6rem;
+ font-weight: 600;
+}
+
+.sm-48 {
+ width: 8.8rem;
+ height: 4.8rem;
+ border-radius: 8px;
+ font-size: 1.6rem;
+ font-weight: 600;
+}
diff --git a/src/components/ui/Button.tsx b/src/components/ui/Button.tsx
new file mode 100644
index 000000000..52e123ae6
--- /dev/null
+++ b/src/components/ui/Button.tsx
@@ -0,0 +1,52 @@
+import { ButtonHTMLAttributes, ReactNode } from "react";
+import clsx from "clsx";
+import styles from "./Button.module.scss";
+import Link, { LinkProps } from "next/link";
+
+interface BaseButtonProps {
+ href?: string;
+ size?: "sm" | "sm-48" | "md" | "lg" | "xl";
+ variant?: "solid" | "outlined" | "text";
+ color?: "primary" | "secondary" | "error";
+ className?: string;
+ children: ReactNode;
+}
+type ButtonAsButton = ButtonHTMLAttributes & BaseButtonProps;
+type ButtonAsLink = LinkProps & BaseButtonProps;
+type ButtonProps = ButtonAsButton | ButtonAsLink;
+
+export function Button({
+ href,
+ className,
+ children,
+ size = "sm",
+ variant = "solid",
+ color = "primary",
+ ...props
+}: ButtonProps) {
+ const css = clsx(
+ styles.btn,
+ variant && styles[variant],
+ color && styles[color],
+ size && styles[size],
+ className
+ );
+
+ if (href) {
+ return (
+ )}
+ >
+ {children}
+
+ );
+ }
+
+ return (
+
+ );
+}
diff --git a/src/components/ui/Chip.module.scss b/src/components/ui/Chip.module.scss
new file mode 100644
index 000000000..244466aa1
--- /dev/null
+++ b/src/components/ui/Chip.module.scss
@@ -0,0 +1,10 @@
+.chip {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 0.8rem;
+ padding: 0 1.2rem 0 1.6rem;
+ height: 3.6rem;
+ background: var(--color-secondary-100);
+ border-radius: 9999px;
+}
diff --git a/src/components/ui/Chip.tsx b/src/components/ui/Chip.tsx
new file mode 100644
index 000000000..05142da7e
--- /dev/null
+++ b/src/components/ui/Chip.tsx
@@ -0,0 +1,22 @@
+import Image from "next/image";
+import clearIcon from "@assets/img/icon/icon_clear.svg";
+import styles from "./Chip.module.scss";
+
+interface ChipProps {
+ text: string;
+ removable?: boolean;
+ onClick?: () => void;
+}
+
+export function Chip({ removable, text, onClick }: ChipProps) {
+ return (
+
+ {text}
+ {removable && (
+
+ )}
+
+ );
+}
diff --git a/src/components/ui/Date.module.scss b/src/components/ui/Date.module.scss
new file mode 100644
index 000000000..58174d384
--- /dev/null
+++ b/src/components/ui/Date.module.scss
@@ -0,0 +1,4 @@
+.date {
+ color: var(--color-secondary-400);
+ font-size: 1.4rem;
+}
diff --git a/src/components/ui/Date.tsx b/src/components/ui/Date.tsx
new file mode 100644
index 000000000..59657a157
--- /dev/null
+++ b/src/components/ui/Date.tsx
@@ -0,0 +1,6 @@
+import { toDate } from "@/util/formatter";
+import styles from "./Date.module.scss";
+
+export function Date({ date }: { date: string }) {
+ return ;
+}
diff --git a/src/components/ui/Dropdown.module.scss b/src/components/ui/Dropdown.module.scss
new file mode 100644
index 000000000..a26c7cbd4
--- /dev/null
+++ b/src/components/ui/Dropdown.module.scss
@@ -0,0 +1,44 @@
+.list-container {
+ .list-inner {
+ position: relative;
+ }
+ .list {
+ overflow: hidden;
+ z-index: 100;
+ position: absolute;
+ right: 0;
+ top: calc(100% + 0.4rem);
+ width: 13rem;
+ border-radius: 1.2rem;
+ border: 1px solid var(--color-secondary-200);
+ background: #fff;
+ animation: show 150ms cubic-bezier(0.16, 1, 0.3, 1);
+
+ li + li {
+ border-top: 1px solid var(--color-secondary-200);
+ }
+
+ .item {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 4.2rem;
+
+ &:hover {
+ background: var(--color-secondary-100);
+ }
+ }
+ }
+}
+
+@keyframes show {
+ from {
+ opacity: 0;
+ transform: translateY(-30px) scale(0.96);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0) scale(1);
+ }
+}
diff --git a/src/components/ui/Dropdown.tsx b/src/components/ui/Dropdown.tsx
new file mode 100644
index 000000000..27e5f4f0b
--- /dev/null
+++ b/src/components/ui/Dropdown.tsx
@@ -0,0 +1,142 @@
+"use client";
+
+import {
+ cloneElement,
+ createContext,
+ ReactElement,
+ ReactNode,
+ useContext,
+ useEffect,
+ useRef,
+ useState,
+} from "react";
+import styles from "./Dropdown.module.scss";
+
+type DropdownStateContext = {
+ isOpen: boolean;
+};
+
+type DropdownDispatchContext = {
+ onChange?: (value: string) => void;
+ setIsOpen: React.Dispatch>;
+};
+
+/** compound pattern + context api 복습 (mui dropdown 참고) */
+const DropdownStateContext = createContext(null);
+const DropdownDispatchContext = createContext(
+ null
+);
+
+const useDropdownState = () => {
+ const context = useContext(DropdownStateContext);
+ if (!context) {
+ throw new Error("Dropdown components must be used within an Dropdown.");
+ }
+ return context;
+};
+
+const useDropdownDispatch = () => {
+ const context = useContext(DropdownDispatchContext);
+ if (!context) {
+ throw new Error("Dropdown components must be used within an Dropdown.");
+ }
+ return context;
+};
+
+export function Dropdown({ children }: { children: ReactNode }) {
+ const [isOpen, setIsOpen] = useState(false);
+ const dropdownRef = useRef(null);
+
+ const state = { isOpen };
+
+ const dispatch = {
+ setIsOpen,
+ };
+
+ useEffect(() => {
+ function handleClickOutside(e: MouseEvent) {
+ if (
+ dropdownRef.current &&
+ !dropdownRef.current.contains(e.target as Node)
+ ) {
+ setIsOpen(false);
+ }
+ }
+ document.addEventListener("click", handleClickOutside);
+
+ return () => {
+ document.removeEventListener("click", handleClickOutside);
+ };
+ }, []);
+
+ return (
+
+
+
+
+
+ );
+}
+
+function Toggle({
+ children,
+ asChild = false,
+}: {
+ children: ReactElement<{ onClick?: () => void }>;
+ asChild?: boolean;
+}) {
+ const { setIsOpen } = useDropdownDispatch();
+
+ function handleClick() {
+ setIsOpen((prev) => !prev);
+ }
+
+ if (asChild) {
+ return cloneElement(children, { onClick: handleClick });
+ }
+
+ return (
+
+ );
+}
+
+function Menu({ children }: { children: ReactNode }) {
+ const { isOpen } = useDropdownState();
+
+ if (!isOpen) return null;
+
+ return ;
+}
+
+function Item({
+ onClick,
+ children,
+}: {
+ onClick?: () => void;
+ children: ReactNode;
+}) {
+ const { setIsOpen } = useDropdownDispatch();
+
+ function handleClick() {
+ setIsOpen(false);
+ if (onClick) {
+ onClick();
+ }
+ }
+
+ return (
+
+
+
+ );
+}
+
+Dropdown.Toggle = Toggle;
+Dropdown.Menu = Menu;
+Dropdown.Item = Item;
diff --git a/src/components/ui/Fullscreen.module.scss b/src/components/ui/Fullscreen.module.scss
new file mode 100644
index 000000000..7ca63df57
--- /dev/null
+++ b/src/components/ui/Fullscreen.module.scss
@@ -0,0 +1,34 @@
+@use "@assets/scss/base/mixins";
+
+.fullscreen {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background: rgba(0, 0, 0, 0.3);
+ cursor: zoom-out;
+ z-index: 1000;
+
+ .info {
+ position: absolute;
+ bottom: 2rem;
+ left: 50%;
+ transform: translateX(-50%);
+ padding: 1em 1.3em;
+ background: #000;
+ border-radius: 9999px;
+ color: var(--color-white);
+ text-align: center;
+
+ @include mixins.mobile {
+ font-size: 1.2rem;
+ }
+ }
+
+ img {
+ width: 100%;
+ height: 100%;
+ object-fit: contain;
+ }
+}
diff --git a/src/components/ui/Fullscreen.tsx b/src/components/ui/Fullscreen.tsx
new file mode 100644
index 000000000..3c834930e
--- /dev/null
+++ b/src/components/ui/Fullscreen.tsx
@@ -0,0 +1,48 @@
+"use client";
+
+import Image from "next/image";
+import { cloneElement, ReactElement, useState } from "react";
+import { Modal } from "@components/ui";
+import styles from "./Fullscreen.module.scss";
+
+export function Fullscreen({
+ children,
+}: {
+ children: ReactElement<{ onFullScreen?: (src: string) => void }>;
+}) {
+ const [imgSrc, setImgSrc] = useState(null);
+
+ function handleOpenScreen(src: string) {
+ setImgSrc(src);
+ }
+
+ function handleCloseScreen() {
+ setImgSrc(null);
+ }
+
+ return (
+ <>
+ {cloneElement(children, { onFullScreen: handleOpenScreen })}
+ {imgSrc && (
+
+
+
+ )}
+ >
+ );
+}
+
+function ImgViewer({
+ src,
+ onCloseScreen,
+}: {
+ src: string;
+ onCloseScreen: () => void;
+}) {
+ return (
+
+ );
+}
diff --git a/src/components/ui/Like.module.scss b/src/components/ui/Like.module.scss
new file mode 100644
index 000000000..516469063
--- /dev/null
+++ b/src/components/ui/Like.module.scss
@@ -0,0 +1,23 @@
+.like {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 0.8rem;
+ font-size: 1.6rem;
+ color: var(--color-secondary-500);
+
+ img {
+ width: 24px;
+ height: 24px;
+ }
+}
+
+.sm {
+ gap: 0.4rem;
+ font-size: 1.4rem;
+
+ img {
+ width: 16px;
+ height: 16px;
+ }
+}
diff --git a/src/components/ui/Like.tsx b/src/components/ui/Like.tsx
new file mode 100644
index 000000000..73bef4027
--- /dev/null
+++ b/src/components/ui/Like.tsx
@@ -0,0 +1,20 @@
+import Image from "next/image";
+import clsx from "clsx";
+import iconHeart from "@assets/img/icon/icon_heart.svg";
+import styles from "./Like.module.scss";
+import { maxNumber } from "@/util/formatter";
+
+interface LikeProps {
+ size?: "sm" | "lg";
+ count: number;
+ max?: number;
+}
+
+export function Like({ size = "lg", count, max = 9999 }: LikeProps) {
+ return (
+
+
+ {maxNumber(count, max)}
+
+ );
+}
diff --git a/src/components/ui/LikeButton.module.scss b/src/components/ui/LikeButton.module.scss
new file mode 100644
index 000000000..86a313457
--- /dev/null
+++ b/src/components/ui/LikeButton.module.scss
@@ -0,0 +1,32 @@
+.button {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 0.4rem;
+ min-width: 6rem;
+ height: 4rem;
+ padding: 0.4rem 1.2rem;
+ border-radius: 9999px;
+ border: 1px solid var(--color-secondary-200);
+ color: var(--color-secondary-500);
+ font-weight: 500;
+ transition: all 0.2s;
+
+ img {
+ width: 2rem;
+ }
+
+ &:hover {
+ border-color: var(--color-secondary-400);
+ box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
+ }
+
+ &.active {
+ border-color: #ff68cc;
+ color: #ff68cc;
+
+ &:hover {
+ box-shadow: 0 0 10px rgba(225, 71, 110, 0.3);
+ }
+ }
+}
diff --git a/src/components/ui/LikeButton.tsx b/src/components/ui/LikeButton.tsx
new file mode 100644
index 000000000..1a9ed6767
--- /dev/null
+++ b/src/components/ui/LikeButton.tsx
@@ -0,0 +1,21 @@
+import Image from "next/image";
+import iconHeart from "@assets/img/icon/icon_heart.svg";
+import iconHeartFill from "@assets/img/icon/icon_heart_fill.svg";
+import styles from "./LikeButton.module.scss";
+import clsx from "clsx";
+
+interface LikeButtonProps {
+ count: number;
+ isLiked: boolean;
+ onClick: () => void;
+}
+
+export function LikeButton({ count, isLiked, onClick }: LikeButtonProps) {
+ const buttonCss = clsx(styles.button, isLiked && styles.active);
+ return (
+
+ );
+}
diff --git a/src/components/ui/Loading.module.scss b/src/components/ui/Loading.module.scss
new file mode 100644
index 000000000..30ab8782c
--- /dev/null
+++ b/src/components/ui/Loading.module.scss
@@ -0,0 +1,7 @@
+.loading {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 20rem;
+ color: var(--color-secondary-400);
+}
diff --git a/src/components/ui/Loading.tsx b/src/components/ui/Loading.tsx
new file mode 100644
index 000000000..007dff0c0
--- /dev/null
+++ b/src/components/ui/Loading.tsx
@@ -0,0 +1,6 @@
+import { ReactNode } from "react";
+import styles from "./Loading.module.scss";
+
+export function Loading({ children }: { children: ReactNode }) {
+ return {children}
;
+}
diff --git a/src/components/ui/LoadingSpinner.module.scss b/src/components/ui/LoadingSpinner.module.scss
new file mode 100644
index 000000000..e2d8df237
--- /dev/null
+++ b/src/components/ui/LoadingSpinner.module.scss
@@ -0,0 +1,45 @@
+.container {
+ position: fixed;
+ z-index: 300;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ background: rgba(0, 0, 0, 0.3);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ &.absolute {
+ position: absolute;
+ }
+
+ .loader {
+ width: 48px;
+ height: 48px;
+ border: 5px solid #fff;
+ border-bottom-color: transparent;
+ border-radius: 50%;
+ display: inline-block;
+ box-sizing: border-box;
+ animation: rotation 1s linear infinite;
+ }
+
+ &.light {
+ background: rgba(255, 255, 255, 0.3);
+
+ .loader {
+ border: 5px solid rgba(0, 0, 0, 0.5);
+ border-bottom-color: transparent;
+ }
+ }
+}
+
+@keyframes rotation {
+ 0% {
+ transform: rotate(0deg);
+ }
+ 100% {
+ transform: rotate(360deg);
+ }
+}
diff --git a/src/components/ui/LoadingSpinner.tsx b/src/components/ui/LoadingSpinner.tsx
new file mode 100644
index 000000000..f0addcff0
--- /dev/null
+++ b/src/components/ui/LoadingSpinner.tsx
@@ -0,0 +1,24 @@
+import clsx from "clsx";
+import styles from "./LoadingSpinner.module.scss";
+
+interface LoadingSpinnerProps {
+ position?: "fixed" | "absolute";
+ light?: boolean;
+}
+
+export function LoadingSpinner({
+ position = "fixed",
+ light,
+}: LoadingSpinnerProps) {
+ return (
+
+ );
+}
diff --git a/src/components/ui/Message.module.scss b/src/components/ui/Message.module.scss
new file mode 100644
index 000000000..583ab049d
--- /dev/null
+++ b/src/components/ui/Message.module.scss
@@ -0,0 +1,25 @@
+@use "@assets/scss/base/mixins";
+
+.message {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-direction: column;
+ gap: 1.6rem;
+ min-height: 20rem;
+ margin: 4.8rem 0;
+ color: var(--color-secondary-400);
+
+ &.compact {
+ min-height: 0;
+ margin: 2em 0;
+ }
+
+ .icon {
+ width: 19.6rem;
+
+ @include mixins.tablet {
+ width: 14rem;
+ }
+ }
+}
diff --git a/src/components/ui/Message.tsx b/src/components/ui/Message.tsx
new file mode 100644
index 000000000..b64320a3d
--- /dev/null
+++ b/src/components/ui/Message.tsx
@@ -0,0 +1,26 @@
+import Image from "next/image";
+import { ReactNode } from "react";
+import clsx from "clsx";
+import styles from "./Message.module.scss";
+
+interface MessageProps {
+ icon?: string;
+ alt?: string;
+ compact?: boolean;
+ children: ReactNode;
+}
+
+export function Message({
+ icon,
+ alt = "",
+ compact = false,
+ children,
+}: MessageProps) {
+ const css = clsx(styles.message, compact && styles.compact);
+ return (
+
+ {icon && }
+ {children}
+
+ );
+}
diff --git a/src/components/ui/Modal.tsx b/src/components/ui/Modal.tsx
new file mode 100644
index 000000000..0d033a379
--- /dev/null
+++ b/src/components/ui/Modal.tsx
@@ -0,0 +1,6 @@
+import { ReactNode } from "react";
+import { createPortal } from "react-dom";
+
+export function Modal({ children }: { children: ReactNode }) {
+ return createPortal(children, document.querySelector("#root")!);
+}
diff --git a/src/components/ui/Select.module.scss b/src/components/ui/Select.module.scss
new file mode 100644
index 000000000..f30a7fa07
--- /dev/null
+++ b/src/components/ui/Select.module.scss
@@ -0,0 +1,44 @@
+@use "@assets/scss/base/mixins";
+
+.button {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ min-width: 13rem;
+ height: 4.2rem;
+ padding: 0 1.2rem 0 2rem;
+ border-radius: 1.2rem;
+ border: 1px solid var(--color-secondary-200);
+
+ &:hover {
+ background: var(--color-secondary-100);
+ }
+
+ @include mixins.mobile {
+ overflow: hidden;
+ justify-content: center;
+ min-width: 0;
+ width: 4.2rem;
+ padding: 0;
+ }
+
+ .label {
+ @include mixins.mobile {
+ display: none;
+ }
+ }
+
+ .arrow {
+ @include mixins.mobile {
+ display: none;
+ }
+ }
+
+ .sort {
+ display: none;
+
+ @include mixins.mobile {
+ display: block;
+ }
+ }
+}
diff --git a/src/components/ui/Select.tsx b/src/components/ui/Select.tsx
new file mode 100644
index 000000000..761e99e41
--- /dev/null
+++ b/src/components/ui/Select.tsx
@@ -0,0 +1,39 @@
+import Image from "next/image";
+import arrowIcon from "@assets/img/icon/icon_arrow_down.svg";
+import sortIcon from "@assets/img/icon/icon_sort.svg";
+import { Dropdown } from "@components/ui";
+import styles from "./Select.module.scss";
+
+interface SelectProps {
+ value: string;
+ options: {
+ value: string;
+ label: string;
+ }[];
+ onChange: (value: string) => void;
+}
+
+export function Select({ value, options = [], onChange }: SelectProps) {
+ const selectedLabel = options.find((option) => option.value === value)?.label;
+ return (
+
+
+
+
+
+ {options.map((option) => (
+ onChange(option.value)}
+ >
+ {option.label}
+
+ ))}
+
+
+ );
+}
diff --git a/src/components/ui/Tags.module.scss b/src/components/ui/Tags.module.scss
new file mode 100644
index 000000000..fa8ba2268
--- /dev/null
+++ b/src/components/ui/Tags.module.scss
@@ -0,0 +1,6 @@
+.item-tags {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 1.2rem;
+ margin-top: 1.4rem;
+}
diff --git a/src/components/ui/Tags.tsx b/src/components/ui/Tags.tsx
new file mode 100644
index 000000000..c5f0a9471
--- /dev/null
+++ b/src/components/ui/Tags.tsx
@@ -0,0 +1,25 @@
+import { Chip } from "@components/ui";
+import styles from "./Tags.module.scss";
+import { Tags as TagsType } from "@type/product";
+
+interface TagsProps {
+ tags: TagsType;
+ onRemoveItem?: (tag: string) => void;
+}
+
+export function Tags({ tags, onRemoveItem }: TagsProps) {
+ return (
+
+ {tags?.map((tag) => (
+ onRemoveItem(tag),
+ removable: true,
+ })}
+ />
+ ))}
+
+ );
+}
diff --git a/src/components/ui/Temporary.module.scss b/src/components/ui/Temporary.module.scss
new file mode 100644
index 000000000..ed4e8cd19
--- /dev/null
+++ b/src/components/ui/Temporary.module.scss
@@ -0,0 +1,23 @@
+.temp-wrapper {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ gap: 6rem;
+ height: 100vh;
+
+ .page-content {
+ text-align: center;
+ }
+
+ .page-title {
+ margin-bottom: 0.3em;
+ font-size: 4rem;
+ font-weight: 700;
+ color: var(--color-secondary-700);
+ }
+
+ .page-description {
+ color: var(--color-secondary-400);
+ }
+}
diff --git a/src/components/ui/Temporary.tsx b/src/components/ui/Temporary.tsx
new file mode 100644
index 000000000..0a3f4654e
--- /dev/null
+++ b/src/components/ui/Temporary.tsx
@@ -0,0 +1,34 @@
+"use client";
+
+import { useRouter } from "next/navigation";
+import { Button } from "@components/ui";
+import styles from "./Temporary.module.scss";
+
+interface TemporaryProps {
+ title?: string;
+ description?: string;
+}
+
+export function Temporary({
+ title = "임시페이지",
+ description = "페이지를 준비중입니다. 처음으로 돌아가주세요",
+}: TemporaryProps) {
+ const router = useRouter();
+
+ function handleGoBack() {
+ router.back();
+ }
+ return (
+
+
+
{title}
+
{description}
+
+
+
+
+
+ );
+}
diff --git a/src/components/ui/Thumbnail.module.scss b/src/components/ui/Thumbnail.module.scss
new file mode 100644
index 000000000..84f8c13f6
--- /dev/null
+++ b/src/components/ui/Thumbnail.module.scss
@@ -0,0 +1,45 @@
+.cover {
+ overflow: hidden;
+ position: relative;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+ border-radius: 1.6rem;
+ background: var(--color-secondary-100);
+ transition: all 0.2s;
+
+ &.fullscreen {
+ cursor: zoom-in;
+ }
+
+ .img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+
+ &.default {
+ max-width: 11.6rem;
+ height: auto;
+ }
+ }
+
+ .button {
+ z-index: 1;
+ position: absolute;
+ top: 1.2rem;
+ right: 1.2rem;
+ }
+
+ &.mini {
+ border-radius: 0.8rem;
+
+ .default {
+ max-width: 4rem;
+ }
+ }
+
+ &.border {
+ border: 1px solid var(--color-secondary-100);
+ }
+}
diff --git a/src/components/ui/Thumbnail.tsx b/src/components/ui/Thumbnail.tsx
new file mode 100644
index 000000000..ebc2c86e0
--- /dev/null
+++ b/src/components/ui/Thumbnail.tsx
@@ -0,0 +1,63 @@
+"use client";
+
+import { useState } from "react";
+import Image from "next/image";
+import clsx from "clsx";
+import defaultImg from "@assets/img/icon/icon_placeholder.svg";
+import clearIcon from "@assets/img/icon/icon_clear.svg";
+import styles from "./Thumbnail.module.scss";
+
+interface ThumbnailProps {
+ src?: string;
+ alt?: string;
+ onRemove?: () => void;
+ aspectRatio?: string;
+ onFullScreen?: (src: string) => void;
+ mini?: boolean;
+ border?: boolean;
+}
+
+export function Thumbnail({
+ src = defaultImg,
+ alt = "",
+ onRemove,
+ aspectRatio = "1 / 1",
+ onFullScreen,
+ mini = false,
+ border = false,
+}: ThumbnailProps) {
+ const [isDefault, setIsDefault] = useState(src === defaultImg);
+ const hasFullScreen = onFullScreen && !isDefault;
+
+ const coverCss = clsx(
+ styles.cover,
+ hasFullScreen && styles.fullscreen,
+ mini && styles.mini,
+ border && styles.border
+ );
+ const imgCss = clsx(styles.img, isDefault && styles.default);
+
+ return (
+
+ );
+}
diff --git a/src/components/ui/index.ts b/src/components/ui/index.ts
new file mode 100644
index 000000000..d2b6c5254
--- /dev/null
+++ b/src/components/ui/index.ts
@@ -0,0 +1,18 @@
+export * from "./Alert";
+export * from "./Avatar";
+export * from "./Button";
+export * from "./Chip";
+export * from "./Dropdown";
+export * from "./LoadingSpinner";
+export * from "./Select";
+export * from "./Tags";
+export * from "./Temporary";
+export * from "./Thumbnail";
+export * from "./Author";
+export * from "./LikeButton";
+export * from "./Message";
+export * from "./Fullscreen";
+export * from "./Modal";
+export * from "./Date";
+export * from "./Like";
+export * from "./Badge";
diff --git a/src/constants/file.ts b/src/constants/file.ts
new file mode 100644
index 000000000..1dbad9813
--- /dev/null
+++ b/src/constants/file.ts
@@ -0,0 +1,7 @@
+export const MAX_FILE_SIZE = 2 * 1024 * 1024;
+export const ACCEPT_FILE_TYPES = [
+ "image/jpeg",
+ "image/png",
+ "image/gif",
+ "image/webp",
+];
diff --git a/src/constants/message.ts b/src/constants/message.ts
new file mode 100644
index 000000000..7a36bc814
--- /dev/null
+++ b/src/constants/message.ts
@@ -0,0 +1,26 @@
+export const PRODUCT_VALIDATION_MESSAGE = {
+ PRODUCT_IMAGE_REQUIRED: "이미지를 업로드해주세요",
+ PRODUCT_TAGS_REQUIRED: "태그를 입력해주세요",
+ PRODUCT_NAME_REQUIRED: "상품명을 입력해주세요",
+ PRODUCT_DESCRIPTION_REQUIRED: "상품소개를 입력해주세요",
+ PRODUCT_PRICE_REQUIRED: "판매 가격을 입력해주세요",
+ PRODUCT_PRICE_MIN: "원 이상 입력해주세요",
+ INVALID_STRING: "특수문자는 사용할 수 없습니다.",
+ INVALID_NUMBER: "숫자만 입력해주세요",
+ INVALID_IMAGE_TYPE: "지원하지않는 이미지 형식입니다.",
+ INVALID_IMAGE_SIZE: "이미지 용량을 확인해주세요.",
+ INVALID_IMAGE_COUNT: "1개만 업로드 가능합니다.",
+};
+
+export const COMMENT_VALIDATION_MESSAGE = {
+ COMMENT_REQUIRED: "내용을 적어주세요",
+};
+
+export const AUTH_VALIDATION_MESSAGES = {
+ EMAIL_REQUIRED: "이메일을 입력해주세요",
+ INVALID_EMAIL: "잘못된 이메일 형식입니다.",
+ PASSWORD_REQUIRED: "비밀번호를 입력해주세요.",
+ PASSWORD_MIN_LENGTH: "비밀번호를 8자 이상 입력해주세요.",
+ PASSWORD_MISMATCH: "비밀번호가 일치하지 않습니다.",
+ USERNAME_REQUIRED: "닉네임을 입력해주세요",
+};
diff --git a/src/context/AxiosInterCeptor.tsx b/src/context/AxiosInterCeptor.tsx
new file mode 100644
index 000000000..f655fb608
--- /dev/null
+++ b/src/context/AxiosInterCeptor.tsx
@@ -0,0 +1,74 @@
+"use client";
+
+import { useEffect } from "react";
+import { refreshAccessToken } from "@/service/auth";
+import { useSession } from "next-auth/react";
+import { axiosInstance } from "@/service/axios";
+
+async function handleRrefreshToken(refreshToken: string) {
+ try {
+ const { accessToken } = await refreshAccessToken(refreshToken);
+ return accessToken;
+ } catch (err) {
+ throw err;
+ }
+}
+
+export function AxiosInterCeptor() {
+ const { data, status, update } = useSession();
+
+ // request inetercepotr : 요청 헤더에 토큰 넣기 (client)
+ useEffect(() => {
+ if (status !== "authenticated" || !data.accessToken) return;
+
+ const authInterceptor = axiosInstance.interceptors.request.use(
+ async function (config) {
+ if (data?.accessToken) {
+ config.headers.Authorization = `Bearer ${data.accessToken}`;
+ }
+
+ return config;
+ }
+ );
+
+ return () => {
+ axiosInstance.interceptors.request.eject(authInterceptor);
+ };
+ }, [status, data?.accessToken]);
+
+ // response interceptor : 응답 실패시 재발급
+ useEffect(() => {
+ if (!data?.refreshToken) return;
+
+ const refreshInterceptor = axiosInstance.interceptors.response.use(
+ function (response) {
+ return response;
+ },
+ async function (error) {
+ if (error.response?.status === 401 && !error.config._retry) {
+ try {
+ error.config._retry = true;
+ const accessToken = await handleRrefreshToken(data.refreshToken);
+
+ if (accessToken !== data.accessToken) {
+ // next-auth session update
+ await update({ accessToken });
+ error.config.headers.Authorization = `Bearer ${accessToken}`;
+ }
+ return axiosInstance(error.config);
+ } catch (refreshError) {
+ console.error("refresh error", refreshError);
+ return Promise.reject(refreshError);
+ }
+ }
+
+ return Promise.reject(error);
+ }
+ );
+ return () => {
+ axiosInstance.interceptors.response.eject(refreshInterceptor);
+ };
+ }, [data?.refreshToken, data?.accessToken, update]);
+
+ return null;
+}
diff --git a/src/context/CommentContext.tsx b/src/context/CommentContext.tsx
new file mode 100644
index 000000000..e5076c3b6
--- /dev/null
+++ b/src/context/CommentContext.tsx
@@ -0,0 +1,55 @@
+import useCommentList from "@/components/Comment/useComments";
+import { BoardName, CommentList } from "@/types/comment";
+import { createContext, ReactNode, useContext } from "react";
+
+interface CommentsProviderProps {
+ name: BoardName;
+ initialData: CommentList;
+ children: ReactNode;
+}
+
+interface CommentContextProps {
+ name: BoardName;
+ comments: CommentList;
+ handleLoad: () => void;
+ refreshComments: () => void;
+ isLoading: boolean;
+ error: Error | null;
+}
+
+const CommentsContext = createContext(null);
+
+export default function CommentsProvider({
+ children,
+ name,
+ initialData,
+}: CommentsProviderProps) {
+ const { comments, handleLoad, refreshComments, isLoading, error } =
+ useCommentList(name, initialData);
+
+ const value = {
+ name,
+ comments,
+ handleLoad,
+ refreshComments,
+ isLoading,
+ error,
+ };
+
+ return (
+
+ {children}
+
+ );
+}
+
+export function useComments() {
+ const context = useContext(CommentsContext);
+ if (!context) {
+ throw new Error(
+ "useComments는 CommentsProvider 내부에서만 사용가능합니다."
+ );
+ }
+
+ return context;
+}
diff --git a/src/hooks/useAsync.ts b/src/hooks/useAsync.ts
new file mode 100644
index 000000000..8bc3e1e6c
--- /dev/null
+++ b/src/hooks/useAsync.ts
@@ -0,0 +1,37 @@
+import { useCallback, useState } from "react";
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export default function useAsync(asyncFn: (...args: any[]) => Promise) {
+ const [result, setResult] = useState(null);
+ const [isLoading, setIsLoading] = useState(false);
+ const [error, setError] = useState(null);
+
+ const wrappedFn = useCallback(
+ async function wrappedFn(...args: Parameters) {
+ let isAborted = false;
+
+ try {
+ setError(null);
+ setIsLoading(true);
+ const res = await asyncFn(...args);
+ setResult(res);
+ return res;
+ } catch (err) {
+ if (err instanceof Error) {
+ if (err.name === "CanceledError") {
+ isAborted = true;
+ } else {
+ setError(err);
+ }
+ }
+ } finally {
+ if (!isAborted) {
+ setIsLoading(false);
+ }
+ }
+ },
+ [asyncFn]
+ );
+
+ return { isLoading, setIsLoading, error, result, wrappedFn };
+}
diff --git a/src/hooks/useForm.ts b/src/hooks/useForm.ts
new file mode 100644
index 000000000..753ebe0e6
--- /dev/null
+++ b/src/hooks/useForm.ts
@@ -0,0 +1,271 @@
+import { ChangeEvent, FormEvent, useState } from "react";
+
+export type FieldValue = string[] | string | number | File | Blob | undefined;
+
+type FieldValues = {
+ [key: string]: FieldValue;
+};
+
+type Rule = {
+ required?: boolean | string;
+ patterns?: {
+ regex: RegExp;
+ message: string;
+ }[];
+ custom?: {
+ validate: (value: FieldValue) => boolean;
+ message: string;
+ };
+ match?: {
+ field: string;
+ message: string;
+ };
+};
+
+type FormState = {
+ [K in keyof T]: {
+ value: T[K];
+ error: string | null;
+ };
+};
+
+type FormSchema = {
+ [K in keyof T]: {
+ value: T[K];
+ rule: Rule;
+ };
+};
+
+export default function useForm(
+ formSchema: FormSchema,
+ defaultValues: Partial = {}
+) {
+ //rule은 따로 보관하기
+ const rules = Object.fromEntries(
+ Object.entries(formSchema)
+ .filter(([_, value]) => value.rule)
+ .map(([key, value]) => [key, value.rule])
+ ) as Record;
+
+ //상태관리할 벨류값만 추려서 초기state만들기
+ const initialState = Object.fromEntries(
+ Object.entries(formSchema).map(([key, value]) => [
+ key,
+ { value: defaultValues[key] ?? value.value, error: null },
+ ])
+ ) as FormState;
+
+ const [formState, setFormState] = useState>(initialState);
+ const [isLoading, setIsLoading] = useState(false);
+ const [formError, setFormError] = useState(null);
+ const isFormValid = Object.entries(formState).every(([key, item]) =>
+ isValidField(rules[key], item)
+ );
+
+ function isValidField(
+ rule: Rule,
+ item: { value: FieldValue; error: string | null }
+ ) {
+ if (item.error !== null) return false;
+
+ if (rule?.required) {
+ const value = item.value;
+
+ if (typeof value === "string" && value.trim().length === 0) {
+ return false;
+ }
+
+ if (typeof value === "number" && isNaN(value)) {
+ return false;
+ }
+
+ if (Array.isArray(value) && value.length === 0) {
+ return false;
+ }
+
+ if (value === null || value === undefined) return false;
+ }
+
+ return true;
+ }
+
+ function handleInputChange(
+ e: ChangeEvent
+ ) {
+ const { type, name, value } = e.target;
+ let nextValue;
+
+ if (type === "number") {
+ nextValue = value === "" ? undefined : Number(value);
+ } else {
+ nextValue = value;
+ }
+
+ handleChange(name, nextValue);
+ }
+
+ function trigger(name: keyof T) {
+ const value = formState[name].value;
+ handleChange(name, value);
+ }
+
+ function handleChange(name: keyof T | string, value: FieldValue) {
+ const { isValid, message } = validate(name, value);
+
+ setFormState((prev) => ({
+ ...prev,
+ [name]: {
+ ...prev[name],
+ value,
+ error: isValid ? null : message,
+ },
+ }));
+ }
+
+ function validate(name: keyof T, value: FieldValue) {
+ const rule = rules[name];
+
+ if (!rule) {
+ return { isValid: true, message: null };
+ }
+
+ if (rule.required) {
+ const isEmpty =
+ value === null ||
+ value === undefined ||
+ (typeof value === "string" && !value.trim()) ||
+ (typeof value === "number" && isNaN(value)) ||
+ (Array.isArray(value) && value.length === 0);
+
+ if (isEmpty) {
+ return {
+ isValid: false,
+ message:
+ typeof rule.required === "string" ? rule.required : "필수값입니다.",
+ };
+ }
+ }
+
+ if (rule.patterns) {
+ for (const pattern of rule.patterns) {
+ if (
+ Array.isArray(value) &&
+ value.every((item) => typeof item === "string")
+ ) {
+ const isArrayValid = value.every((item) => pattern.regex.test(item));
+ if (!isArrayValid) {
+ return {
+ isValid: false,
+ message:
+ pattern.message || "배열 요소에 유효하지 않은 형식이 있습니다.",
+ };
+ }
+ } else {
+ if (typeof value === "string" && !pattern.regex.test(value)) {
+ return {
+ isValid: false,
+ message: pattern.message || "유효하지 않은 형식입니다.",
+ };
+ }
+ }
+ }
+ }
+
+ if (rule.match) {
+ const targetValue = formState[rule.match.field].value || "";
+ if (value !== targetValue) {
+ return {
+ isValid: false,
+ message: rule.match.message || "값이 일치하지 않습니다.",
+ };
+ }
+ }
+
+ if (rule.custom) {
+ const validateFunc = rule.custom.validate;
+ if (Array.isArray(value)) {
+ const isArrayValid = value.every((item) => validateFunc(item));
+ if (!isArrayValid) {
+ return {
+ isValid: false,
+ message:
+ rule.custom.message ||
+ "배열 요소에 유효하지 않은 값이 있습니다..",
+ };
+ }
+ } else {
+ if (!validateFunc(value)) {
+ return {
+ isValid: false,
+ message: rule.custom.message || "유효하지 않은 값입니다.",
+ };
+ }
+ }
+ }
+
+ return { isValid: true, message: null };
+ }
+
+ function handleSubmit(submitFn: (submitData: T) => Promise) {
+ //다른곳에서 submit과 관련된 비동기코드만 넣으면 되도록
+ //공통적으로 사용되는 코드를 모아두기
+ return async function (e: FormEvent) {
+ e.preventDefault();
+
+ //전체적으로 field들을 다시한번 trigger를 호출해서 재점검
+ Object.keys(formState).forEach((name) => trigger(name));
+
+ if (!isFormValid) {
+ alert("제출할 수 없습니다. 확인을 해주세요.");
+ return;
+ }
+
+ setFormError(null);
+ setIsLoading(true);
+
+ try {
+ return await submitFn(getValues());
+ } catch (err) {
+ if (err instanceof Error) {
+ setFormError(err);
+ }
+ } finally {
+ setIsLoading(false);
+ }
+ };
+ }
+
+ function getValues(): T {
+ return Object.fromEntries(
+ Object.entries(formState).map(([key, value]) => [key, value.value])
+ ) as T;
+ }
+
+ function register(name: K) {
+ return {
+ id: name,
+ name,
+ value: formState[name].value,
+ error: formState[name].error,
+ onChange: handleInputChange,
+ required: rules[name]?.required ? true : false,
+ };
+ }
+
+ function reset() {
+ setFormState(initialState);
+ }
+
+ return {
+ formState,
+ formError,
+ isFormValid,
+ isLoading,
+ handleChange,
+ trigger,
+ handleSubmit,
+ getValues,
+ register,
+ reset,
+ };
+}
diff --git a/src/hooks/useFormWithError.ts b/src/hooks/useFormWithError.ts
new file mode 100644
index 000000000..e86eab0ac
--- /dev/null
+++ b/src/hooks/useFormWithError.ts
@@ -0,0 +1,27 @@
+import { useState } from "react";
+import { FieldValues, useForm, UseFormProps } from "react-hook-form";
+
+export default function useFormWithError(
+ options: UseFormProps
+) {
+ const [formError, setFormError] = useState(null);
+ const form = useForm(options);
+ const { handleSubmit } = form;
+
+ function handleSumbitWithError(submitFn: (data: T) => Promise) {
+ return handleSubmit(async function (data) {
+ try {
+ setFormError(null);
+ await submitFn(data);
+ } catch (error) {
+ setFormError(error as Error);
+ }
+ });
+ }
+
+ return {
+ ...form,
+ formError,
+ handleSubmit: handleSumbitWithError,
+ };
+}
diff --git a/src/hooks/useLocalStorage.ts b/src/hooks/useLocalStorage.ts
new file mode 100644
index 000000000..025fe95ae
--- /dev/null
+++ b/src/hooks/useLocalStorage.ts
@@ -0,0 +1,28 @@
+import { useState } from "react";
+
+export default function useLocalStorage(key: string, initialValue: string[]) {
+ const [state, setState] = useState(() => {
+ if (typeof window === "undefined") return initialValue;
+
+ try {
+ const value = window.localStorage.getItem(key);
+ return value ? JSON.parse(value) : initialValue;
+ } catch (err) {
+ console.error(err);
+ return initialValue;
+ }
+ });
+
+ function setValue(value: string[] | ((value: string[]) => string[])) {
+ try {
+ //useState의 setState에 callback을 넘기는 행동처럼 사용가능하도록
+ const newValue = value instanceof Function ? value(state) : value;
+ window.localStorage.setItem(key, JSON.stringify(newValue));
+ setState(newValue);
+ } catch (err) {
+ console.error(err);
+ }
+ }
+
+ return [state, setValue] as const;
+}
diff --git a/src/hooks/usePagination.ts b/src/hooks/usePagination.ts
new file mode 100644
index 000000000..f068dfd1c
--- /dev/null
+++ b/src/hooks/usePagination.ts
@@ -0,0 +1,74 @@
+import { MouseEvent, useEffect } from "react";
+
+interface PaginationProps {
+ page: number;
+ pageSize: number;
+ totalCount: number;
+ visibleCount: number;
+ onChange: (page: number) => void;
+}
+
+export default function usePagination({
+ page,
+ pageSize,
+ totalCount,
+ visibleCount = 5,
+ onChange,
+}: PaginationProps) {
+ const totalPage = Math.ceil(totalCount / pageSize);
+ const currentGroup = Math.ceil(page / visibleCount);
+ const firstPageInGroup = (currentGroup - 1) * visibleCount + 1;
+ const lastPageInGroup = Math.min(currentGroup * visibleCount, totalPage);
+ const pageLengthInGroup = lastPageInGroup - firstPageInGroup + 1;
+ const pageNumbers = Array.from(
+ { length: pageLengthInGroup },
+ (_, index) => firstPageInGroup + index
+ );
+
+ const isPrevDisabled = page === 1;
+ const isNextDisabled = totalPage === page;
+
+ const isPrevGroupDisabled = currentGroup === 1;
+ const isNextGroupDisabled = lastPageInGroup === totalPage;
+
+ function handleNextClick() {
+ onChange(page + 1);
+ }
+
+ function handlePrevClick() {
+ onChange(page - 1);
+ }
+
+ function handlePageClick(e: MouseEvent) {
+ onChange(Number(e.currentTarget.dataset.number));
+ }
+
+ function handleNextGroupClick() {
+ onChange(lastPageInGroup + 1);
+ }
+
+ function handlePrevGroupClick() {
+ onChange(firstPageInGroup - 1);
+ }
+
+ useEffect(() => {
+ //모바일에서 뒷페이지로 이동후 pc로 돌아올때 페이지번호가 전체페이지를 넘칠때 마지막 페이지로 이동하기
+ if (totalPage > 0 && page > totalPage) {
+ onChange(totalPage);
+ }
+ }, [page, totalPage, onChange]);
+
+ return {
+ page,
+ pageNumbers,
+ isPrevDisabled,
+ isNextDisabled,
+ isPrevGroupDisabled,
+ isNextGroupDisabled,
+ onPrevClick: handlePrevClick,
+ onNextClick: handleNextClick,
+ onPageClick: handlePageClick,
+ onPrevGroupClick: handlePrevGroupClick,
+ onNextGroupClick: handleNextGroupClick,
+ };
+}
diff --git a/src/hooks/useParams.ts b/src/hooks/useParams.ts
new file mode 100644
index 000000000..d5b037991
--- /dev/null
+++ b/src/hooks/useParams.ts
@@ -0,0 +1,28 @@
+import { usePathname, useRouter, useSearchParams } from "next/navigation";
+import { useCallback } from "react";
+
+export default function useParams() {
+ const router = useRouter();
+ const pathname = usePathname();
+ const searchParams = useSearchParams();
+
+ const handleParams = useCallback(
+ function handleParams(updateParams: Record) {
+ const params = new URLSearchParams(searchParams);
+
+ Object.entries(updateParams).forEach(([key, value]) => {
+ const formattedValue = value.toString().trim();
+ if (formattedValue) {
+ params.set(key, formattedValue);
+ } else {
+ params.delete(key);
+ }
+ });
+
+ router.push(`${pathname}?${params.toString()}`);
+ },
+ [searchParams, pathname, router]
+ );
+
+ return { searchParams, handleParams };
+}
diff --git a/src/hooks/useRecentSearch.ts b/src/hooks/useRecentSearch.ts
new file mode 100644
index 000000000..4683216a6
--- /dev/null
+++ b/src/hooks/useRecentSearch.ts
@@ -0,0 +1,72 @@
+import { ChangeEvent, useState } from "react";
+import useLocalStorage from "@hooks/useLocalStorage";
+
+const RECENT_SEARCH_SIZE = 5;
+
+interface useRecentSearchProps {
+ initialKeyword: string;
+ onChange: (keyword: string) => void;
+}
+
+export default function useRecentSearch({
+ initialKeyword,
+ onChange,
+}: useRecentSearchProps) {
+ const [searchInput, setSearchInput] = useState(initialKeyword || "");
+ const [recentSearch, setRecentSearch] = useLocalStorage("keyword", []);
+
+ // 검색창 핸들러 (submit, change, clear)
+ function handleSearchSubmit() {
+ if (searchInput.trim()) {
+ setRecentSearch((prev) =>
+ [
+ searchInput,
+ ...prev.filter((keyword) => keyword !== searchInput),
+ ].slice(0, RECENT_SEARCH_SIZE)
+ );
+ }
+ //검색인풋 초기화가 좋은 UX일까? (검색취소 버튼이 나오도록, 검색어가 떠있는게 좋은것 같음)
+ //setSearchInput("");
+ onChange(searchInput);
+ }
+
+ function handleSearchChange(e: ChangeEvent) {
+ setSearchInput(e.target.value);
+ }
+
+ function handleSearchClear() {
+ setSearchInput("");
+ onChange("");
+ }
+
+ // 최근검색 이벤트 핸들러 (click, remove, clear)
+ function handleRecentSearchClick(value: string) {
+ setRecentSearch((prev) =>
+ [value, ...prev.filter((keyword) => keyword !== value)].slice(
+ 0,
+ RECENT_SEARCH_SIZE
+ )
+ );
+ setSearchInput(value);
+ onChange(value);
+ }
+
+ function handleRecentSearchRemove(value: string) {
+ setRecentSearch((prev) => prev.filter((keyword) => keyword !== value));
+ }
+
+ function handleRecentSearchClear() {
+ setRecentSearch([]);
+ }
+
+ return {
+ searchInput,
+ recentSearch,
+ handleSearchSubmit,
+ handleSearchChange,
+ handleSearchClear,
+ handleRecentSearchClick,
+ handleRecentSearchRemove,
+ handleRecentSearchClear,
+ };
+}
diff --git a/src/hooks/useResponsive.ts b/src/hooks/useResponsive.ts
new file mode 100644
index 000000000..c0bad847d
--- /dev/null
+++ b/src/hooks/useResponsive.ts
@@ -0,0 +1,33 @@
+import { useEffect, useState } from "react";
+import { getDeviceType } from "@util/breakpoints";
+import { debounce } from "@util/debounce";
+
+type ResponsiveNumber = Record<"pc" | "tablet" | "mobile", number>;
+
+export default function useResponsive(
+ initialOption: ResponsiveNumber = {
+ pc: 10,
+ tablet: 6,
+ mobile: 4,
+ }
+) {
+ const [responsiveValue, setResponsiveValue] = useState(
+ () => initialOption[getDeviceType()]
+ );
+
+ useEffect(() => {
+ const debounceHandleResize = debounce(function () {
+ if (typeof window === "undefined") return;
+ const targetSize = initialOption[getDeviceType()];
+ setResponsiveValue(targetSize);
+ }, 100);
+
+ window.addEventListener("resize", debounceHandleResize);
+
+ return () => {
+ window.removeEventListener("resize", debounceHandleResize);
+ };
+ }, [initialOption]);
+
+ return responsiveValue;
+}
diff --git a/src/middleware.ts b/src/middleware.ts
new file mode 100644
index 000000000..871d4d35c
--- /dev/null
+++ b/src/middleware.ts
@@ -0,0 +1,11 @@
+import { auth } from "./auth";
+
+export default auth((req) => {
+ if (!req.auth && req.nextUrl.pathname !== "/login") {
+ return Response.redirect(new URL("/login", req.nextUrl.origin));
+ }
+});
+
+export const config = {
+ matcher: ["/addBoard", "/addItem", "/modifyItem"],
+};
diff --git a/src/schemas/auth.ts b/src/schemas/auth.ts
new file mode 100644
index 000000000..faef054f5
--- /dev/null
+++ b/src/schemas/auth.ts
@@ -0,0 +1,38 @@
+import { AUTH_VALIDATION_MESSAGES as MESSAGE } from "@constants/message";
+import { z } from "zod";
+
+export const signupFormSchema = z
+ .object({
+ email: z
+ .string()
+ .nonempty({ message: MESSAGE.EMAIL_REQUIRED })
+ .email({ message: MESSAGE.INVALID_EMAIL }),
+ nickname: z.string().nonempty({ message: MESSAGE.USERNAME_REQUIRED }),
+ password: z
+ .string()
+ .nonempty({ message: MESSAGE.PASSWORD_REQUIRED })
+ .min(8, { message: MESSAGE.PASSWORD_MIN_LENGTH }),
+ passwordConfirmation: z
+ .string()
+ .nonempty({ message: MESSAGE.PASSWORD_REQUIRED })
+ .min(8, { message: MESSAGE.PASSWORD_MIN_LENGTH }),
+ })
+ .refine((data) => data.password === data.passwordConfirmation, {
+ path: ["passwordConfirmation"],
+ message: MESSAGE.PASSWORD_MISMATCH,
+ });
+
+export type SigninFormType = z.infer;
+
+export const signinFormSchmea = z.object({
+ email: z
+ .string()
+ .nonempty({ message: MESSAGE.EMAIL_REQUIRED })
+ .email({ message: MESSAGE.INVALID_EMAIL }),
+ password: z
+ .string()
+ .nonempty({ message: MESSAGE.PASSWORD_REQUIRED })
+ .min(8, { message: MESSAGE.PASSWORD_MIN_LENGTH }),
+});
+
+export type SignupFormType = z.infer;
diff --git a/src/schemas/comment.ts b/src/schemas/comment.ts
new file mode 100644
index 000000000..9c6a20074
--- /dev/null
+++ b/src/schemas/comment.ts
@@ -0,0 +1,8 @@
+import { z } from "zod";
+import { COMMENT_VALIDATION_MESSAGE as MESSAGE } from "@constants/message";
+
+export const CommentFormSchema = z.object({
+ content: z.string().nonempty({ message: MESSAGE.COMMENT_REQUIRED }),
+});
+
+export type CommentFormType = z.infer;
diff --git a/src/schemas/product.ts b/src/schemas/product.ts
new file mode 100644
index 000000000..209a8586e
--- /dev/null
+++ b/src/schemas/product.ts
@@ -0,0 +1,51 @@
+import { z } from "zod";
+import { PRODUCT_VALIDATION_MESSAGE as MESSAGE } from "@constants/message";
+import { ACCEPT_FILE_TYPES, MAX_FILE_SIZE } from "@constants/file";
+
+export const ProductFormSchema = z.object({
+ images: z
+ .array(z.union([z.instanceof(File), z.string()]))
+ .min(1, { message: MESSAGE.PRODUCT_IMAGE_REQUIRED })
+ .max(1, { message: MESSAGE.INVALID_IMAGE_COUNT })
+ .refine(
+ (files) => {
+ if (files[0] instanceof File) {
+ return files[0].size <= MAX_FILE_SIZE;
+ }
+ return true; // string일 경우는 size 체크 스킵
+ },
+ {
+ message: `${MESSAGE.INVALID_IMAGE_SIZE} (${
+ MAX_FILE_SIZE / 1024 / 1024
+ }MB 초과)`,
+ }
+ )
+ .refine(
+ (files) => {
+ if (files[0] instanceof File) {
+ return ACCEPT_FILE_TYPES.includes(files[0].type);
+ }
+ return true; // string일 경우는 type 체크 스킵
+ },
+ { message: MESSAGE.INVALID_IMAGE_TYPE }
+ ),
+ name: z.string().nonempty({ message: MESSAGE.PRODUCT_NAME_REQUIRED }),
+ description: z.string().nonempty({
+ message: MESSAGE.PRODUCT_DESCRIPTION_REQUIRED,
+ }),
+ price: z.coerce
+ .number()
+ .min(100, { message: 100 + MESSAGE.PRODUCT_PRICE_MIN }),
+ tags: z
+ .array(z.string())
+ .min(1, { message: MESSAGE.PRODUCT_TAGS_REQUIRED })
+ .refine(
+ (tags) =>
+ tags.every((tag) =>
+ /^[^!@#$%^&*(),.?":{}|<>_\-+=\[\]\\\/`~';]*$/.test(tag)
+ ),
+ { message: MESSAGE.INVALID_STRING }
+ ),
+});
+
+export type ProductFormType = z.infer;
diff --git a/src/service/article.ts b/src/service/article.ts
new file mode 100644
index 000000000..f5d661359
--- /dev/null
+++ b/src/service/article.ts
@@ -0,0 +1,22 @@
+import { Article } from "@/types/article";
+import { axiosInstance } from "./axios";
+import { PaginationResponse } from "@/types/common";
+
+export async function getArticles({
+ page = 1,
+ pageSize = 10,
+ orderBy = "recent",
+ keyword = "",
+}) {
+ const query = `page=${page}&pageSize=${pageSize}&orderBy=${orderBy}&keyword=${keyword}`;
+ const response = await axiosInstance.get>(
+ `/articles?${query}`
+ );
+
+ return response.data;
+}
+
+export async function getArticle(articleId: number) {
+ const response = await axiosInstance.get(`/articles/${articleId}`);
+ return response.data;
+}
diff --git a/src/service/auth.ts b/src/service/auth.ts
new file mode 100644
index 000000000..e2584c257
--- /dev/null
+++ b/src/service/auth.ts
@@ -0,0 +1,46 @@
+import { SigninFormType, SignupFormType } from "@schemas/auth";
+import { axiosInstance } from "@service/axios";
+import { RefreshResponse, AuthResponse, User } from "@type/auth";
+import axios from "axios";
+
+export async function login({ email, password }: SigninFormType) {
+ const response = await axiosInstance.post("/auth/signIn", {
+ email,
+ password,
+ });
+
+ return response.data;
+}
+
+export async function signUp({
+ email,
+ nickname,
+ password,
+ passwordConfirmation,
+}: SignupFormType) {
+ const response = await axiosInstance.post("/auth/signUp", {
+ email,
+ nickname,
+ password,
+ passwordConfirmation,
+ });
+
+ return response.data;
+}
+
+export async function getUser() {
+ const response = await axiosInstance.get("/users/me");
+
+ return response.data;
+}
+
+export async function refreshAccessToken(refreshToken: string) {
+ const response = await axios.post(
+ `${process.env.NEXT_PUBLIC_API_URL}/auth/refresh-token`,
+ {
+ refreshToken,
+ }
+ );
+
+ return response.data;
+}
diff --git a/src/service/axios.ts b/src/service/axios.ts
new file mode 100644
index 000000000..81c8b465a
--- /dev/null
+++ b/src/service/axios.ts
@@ -0,0 +1,5 @@
+import axios from "axios";
+
+export const axiosInstance = axios.create({
+ baseURL: process.env.NEXT_PUBLIC_API_URL,
+});
diff --git a/src/service/comments.ts b/src/service/comments.ts
new file mode 100644
index 000000000..f15453100
--- /dev/null
+++ b/src/service/comments.ts
@@ -0,0 +1,57 @@
+import { axiosInstance } from "@service/axios";
+import {
+ BoardName,
+ Comment,
+ DeleteCommentResponse,
+ CommentList,
+} from "@type/comment";
+import { CommentFormType } from "@schemas/comment";
+
+export async function getComments(
+ name: BoardName,
+ {
+ productId,
+ limit = 5,
+ cursor,
+ }: { productId: number; limit?: number; cursor?: number }
+) {
+ const query = `limit=${limit}${cursor ? `&cursor=${cursor}` : ""}`;
+ const response = await axiosInstance.get(
+ `/${name}/${productId}/comments?${query}`
+ );
+
+ return response.data;
+}
+
+export async function addComment(
+ name: BoardName,
+ id: number,
+ formData: CommentFormType
+) {
+ const response = await axiosInstance.post(
+ `/${name}/${id}/comments`,
+ formData
+ );
+
+ return response.data;
+}
+
+export async function removeComment(commentId: number) {
+ const response = await axiosInstance.delete(
+ `/comments/${commentId}`
+ );
+
+ return response.data;
+}
+
+export async function updateComment(
+ commentId: number,
+ formData: CommentFormType
+) {
+ const response = await axiosInstance.patch(
+ `/comments/${commentId}`,
+ formData
+ );
+
+ return response.data;
+}
diff --git a/src/service/product.ts b/src/service/product.ts
new file mode 100644
index 000000000..bd4637fde
--- /dev/null
+++ b/src/service/product.ts
@@ -0,0 +1,72 @@
+import { ProductFormType } from "@schemas/product";
+import { axiosInstance } from "@service/axios";
+import { PaginationResponse } from "@type/common";
+import {
+ DeleteProductResponse,
+ ImageUploadResponse,
+ Product,
+} from "@type/product";
+
+export async function getProducts({
+ page = 1,
+ pageSize = 10,
+ orderBy = "recent",
+ keyword = "",
+}) {
+ const query = `page=${page}&pageSize=${pageSize}&orderBy=${orderBy}&keyword=${keyword}`;
+ const response = await axiosInstance.get>(
+ `/products?${query}`
+ );
+
+ return response.data;
+}
+
+export async function uploadProductImage(formData: FormData) {
+ const response = await axiosInstance.post(
+ "/images/upload",
+ formData
+ );
+
+ return response.data;
+}
+
+export async function addProduct(productData: ProductFormType) {
+ const response = await axiosInstance.post("/products", productData);
+
+ return response.data;
+}
+
+export async function modifyProduct(
+ productId: number,
+ productData: ProductFormType
+) {
+ const response = await axiosInstance.patch(
+ `/products/${productId}`,
+ productData
+ );
+
+ return response.data;
+}
+
+export async function deleteProduct(productId: number) {
+ const response = await axiosInstance.delete(
+ `/products/${productId}`
+ );
+
+ return response.data;
+}
+
+export async function getProduct(productId: number) {
+ const response = await axiosInstance.get(`/products/${productId}`);
+
+ return response.data;
+}
+
+export async function toggleLike(productId: number, flag: boolean) {
+ const response = await axiosInstance({
+ method: flag ? "POST" : "DELETE",
+ url: `/products/${productId}/favorite`,
+ });
+
+ return response.data;
+}
diff --git a/src/service/serverAxios.ts b/src/service/serverAxios.ts
new file mode 100644
index 000000000..01aff8aae
--- /dev/null
+++ b/src/service/serverAxios.ts
@@ -0,0 +1,19 @@
+"use server";
+
+import { auth } from "@/auth";
+import { axiosInstance } from "./axios";
+
+export async function initServerInterceptor() {
+ axiosInstance.interceptors.request.use(
+ async (config) => {
+ const session = await auth();
+ if (session?.accessToken) {
+ config.headers.Authorization = `Bearer ${session?.accessToken}`;
+ }
+ return config;
+ },
+ (error) => {
+ return Promise.reject(error);
+ }
+ );
+}
diff --git a/src/types/article.ts b/src/types/article.ts
new file mode 100644
index 000000000..f41cd51b2
--- /dev/null
+++ b/src/types/article.ts
@@ -0,0 +1,14 @@
+import { BaseData } from "./common";
+
+export type Article = BaseData & {
+ likeCount: number;
+ writer: {
+ nickname: string;
+ id: number;
+ };
+ image: string;
+ content: string;
+ title: string;
+};
+
+export type ListMode = "all" | "best";
diff --git a/src/types/auth.ts b/src/types/auth.ts
new file mode 100644
index 000000000..76a649d4e
--- /dev/null
+++ b/src/types/auth.ts
@@ -0,0 +1,18 @@
+export type User = {
+ updatedAt: string;
+ createdAt: string;
+ image: string;
+ nickname: string;
+ id: number;
+};
+
+export type Tokens = {
+ accessToken: string;
+ refreshToken: string;
+};
+
+export type AuthResponse = Tokens & {
+ user: User;
+};
+
+export type RefreshResponse = Pick;
diff --git a/src/types/comment.ts b/src/types/comment.ts
new file mode 100644
index 000000000..d353c1adb
--- /dev/null
+++ b/src/types/comment.ts
@@ -0,0 +1,16 @@
+import { User } from "./auth";
+import { BaseData } from "./common";
+
+export type BoardName = "articles" | "products";
+
+export type CommentList = {
+ nextCursor: number;
+ list: Comment[];
+};
+
+export type Comment = BaseData & {
+ writer: User;
+ content: string;
+};
+
+export type DeleteCommentResponse = Pick;
diff --git a/src/types/common.ts b/src/types/common.ts
new file mode 100644
index 000000000..fc3ff3ded
--- /dev/null
+++ b/src/types/common.ts
@@ -0,0 +1,17 @@
+export type ListQueryParams = {
+ page: number;
+ pageSize: number;
+ keyword: string;
+ orderBy: string;
+};
+
+export type PaginationResponse = {
+ totalCount: number;
+ list: T[];
+};
+
+export type BaseData = {
+ updatedAt: string;
+ createdAt: string;
+ id: number;
+};
diff --git a/src/types/product.ts b/src/types/product.ts
new file mode 100644
index 000000000..07b9921e2
--- /dev/null
+++ b/src/types/product.ts
@@ -0,0 +1,23 @@
+import { BaseData } from "./common";
+
+export type Tags = string[];
+
+export type Product = BaseData & {
+ favoriteCount: number;
+ ownerNickname: string;
+ ownerId: number;
+ images: string[];
+ tags: Tags;
+ price: number;
+ description: string;
+ name: string;
+ isFavorite: boolean;
+};
+
+export type ImageUploadResponse = {
+ url: string;
+};
+
+export type DeleteProductResponse = Pick;
+
+export type ListMode = "all" | "best";
diff --git a/src/util/breakpoints.ts b/src/util/breakpoints.ts
new file mode 100644
index 000000000..4634537de
--- /dev/null
+++ b/src/util/breakpoints.ts
@@ -0,0 +1,11 @@
+export const BREAKPOINT_TABLET = 1200;
+export const BREAKPOINT_MOBILE = 768;
+
+export function getDeviceType() {
+ if (typeof window === "undefined") return "pc";
+
+ const browserWidth = window.innerWidth;
+ if (browserWidth < BREAKPOINT_MOBILE) return "mobile";
+ if (browserWidth < BREAKPOINT_TABLET) return "tablet";
+ return "pc";
+}
diff --git a/src/util/debounce.ts b/src/util/debounce.ts
new file mode 100644
index 000000000..62e5c3009
--- /dev/null
+++ b/src/util/debounce.ts
@@ -0,0 +1,14 @@
+export function debounce(
+ func: (...args: T) => void,
+ timeout: number = 300
+) {
+ let timer: ReturnType;
+
+ return (...args: T) => {
+ clearTimeout(timer);
+
+ timer = setTimeout(() => {
+ func(...args);
+ }, timeout);
+ };
+}
diff --git a/src/util/formatter.ts b/src/util/formatter.ts
new file mode 100644
index 000000000..bb2a1dbf8
--- /dev/null
+++ b/src/util/formatter.ts
@@ -0,0 +1,13 @@
+import dayjs from "dayjs";
+
+export function toWon(price: string | number | undefined) {
+ return Number(price).toLocaleString() + "원";
+}
+
+export function toDate(date: string) {
+ return dayjs(date).format("YYYY.MM.DD");
+}
+
+export function maxNumber(number: number, max: number) {
+ return number <= max ? number : `${max}+`;
+}
diff --git a/src/util/helper.ts b/src/util/helper.ts
new file mode 100644
index 000000000..f9c551817
--- /dev/null
+++ b/src/util/helper.ts
@@ -0,0 +1,13 @@
+import { jwtDecode } from "jwt-decode";
+
+export function isTokenValid(token: string) {
+ try {
+ const { exp } = jwtDecode(token);
+ if (!exp) return false;
+
+ return Date.now() < exp * 1000;
+ } catch (err) {
+ console.error(err);
+ return false;
+ }
+}
diff --git a/styles/Home.module.css b/styles/Home.module.css
deleted file mode 100644
index 6676d2c66..000000000
--- a/styles/Home.module.css
+++ /dev/null
@@ -1,229 +0,0 @@
-.main {
- display: flex;
- flex-direction: column;
- justify-content: space-between;
- align-items: center;
- padding: 6rem;
- min-height: 100vh;
-}
-
-.description {
- display: inherit;
- justify-content: inherit;
- align-items: inherit;
- font-size: 0.85rem;
- max-width: var(--max-width);
- width: 100%;
- z-index: 2;
- font-family: var(--font-mono);
-}
-
-.description a {
- display: flex;
- justify-content: center;
- align-items: center;
- gap: 0.5rem;
-}
-
-.description p {
- position: relative;
- margin: 0;
- padding: 1rem;
- background-color: rgba(var(--callout-rgb), 0.5);
- border: 1px solid rgba(var(--callout-border-rgb), 0.3);
- border-radius: var(--border-radius);
-}
-
-.code {
- font-weight: 700;
- font-family: var(--font-mono);
-}
-
-.grid {
- display: grid;
- grid-template-columns: repeat(4, minmax(25%, auto));
- max-width: 100%;
- width: var(--max-width);
-}
-
-.card {
- padding: 1rem 1.2rem;
- border-radius: var(--border-radius);
- background: rgba(var(--card-rgb), 0);
- border: 1px solid rgba(var(--card-border-rgb), 0);
- transition: background 200ms, border 200ms;
-}
-
-.card span {
- display: inline-block;
- transition: transform 200ms;
-}
-
-.card h2 {
- font-weight: 600;
- margin-bottom: 0.7rem;
-}
-
-.card p {
- margin: 0;
- opacity: 0.6;
- font-size: 0.9rem;
- line-height: 1.5;
- max-width: 30ch;
-}
-
-.center {
- display: flex;
- justify-content: center;
- align-items: center;
- position: relative;
- padding: 4rem 0;
-}
-
-.center::before {
- background: var(--secondary-glow);
- border-radius: 50%;
- width: 480px;
- height: 360px;
- margin-left: -400px;
-}
-
-.center::after {
- background: var(--primary-glow);
- width: 240px;
- height: 180px;
- z-index: -1;
-}
-
-.center::before,
-.center::after {
- content: '';
- left: 50%;
- position: absolute;
- filter: blur(45px);
- transform: translateZ(0);
-}
-
-.logo {
- position: relative;
-}
-/* Enable hover only on non-touch devices */
-@media (hover: hover) and (pointer: fine) {
- .card:hover {
- background: rgba(var(--card-rgb), 0.1);
- border: 1px solid rgba(var(--card-border-rgb), 0.15);
- }
-
- .card:hover span {
- transform: translateX(4px);
- }
-}
-
-@media (prefers-reduced-motion) {
- .card:hover span {
- transform: none;
- }
-}
-
-/* Mobile */
-@media (max-width: 700px) {
- .content {
- padding: 4rem;
- }
-
- .grid {
- grid-template-columns: 1fr;
- margin-bottom: 120px;
- max-width: 320px;
- text-align: center;
- }
-
- .card {
- padding: 1rem 2.5rem;
- }
-
- .card h2 {
- margin-bottom: 0.5rem;
- }
-
- .center {
- padding: 8rem 0 6rem;
- }
-
- .center::before {
- transform: none;
- height: 300px;
- }
-
- .description {
- font-size: 0.8rem;
- }
-
- .description a {
- padding: 1rem;
- }
-
- .description p,
- .description div {
- display: flex;
- justify-content: center;
- position: fixed;
- width: 100%;
- }
-
- .description p {
- align-items: center;
- inset: 0 0 auto;
- padding: 2rem 1rem 1.4rem;
- border-radius: 0;
- border: none;
- border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25);
- background: linear-gradient(
- to bottom,
- rgba(var(--background-start-rgb), 1),
- rgba(var(--callout-rgb), 0.5)
- );
- background-clip: padding-box;
- backdrop-filter: blur(24px);
- }
-
- .description div {
- align-items: flex-end;
- pointer-events: none;
- inset: auto 0 0;
- padding: 2rem;
- height: 200px;
- background: linear-gradient(
- to bottom,
- transparent 0%,
- rgb(var(--background-end-rgb)) 40%
- );
- z-index: 1;
- }
-}
-
-/* Tablet and Smaller Desktop */
-@media (min-width: 701px) and (max-width: 1120px) {
- .grid {
- grid-template-columns: repeat(2, 50%);
- }
-}
-
-@media (prefers-color-scheme: dark) {
- .vercelLogo {
- filter: invert(1);
- }
-
- .logo {
- filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70);
- }
-}
-
-@keyframes rotate {
- from {
- transform: rotate(360deg);
- }
- to {
- transform: rotate(0deg);
- }
-}
diff --git a/styles/globals.css b/styles/globals.css
deleted file mode 100644
index d4f491e15..000000000
--- a/styles/globals.css
+++ /dev/null
@@ -1,107 +0,0 @@
-:root {
- --max-width: 1100px;
- --border-radius: 12px;
- --font-mono: ui-monospace, Menlo, Monaco, 'Cascadia Mono', 'Segoe UI Mono',
- 'Roboto Mono', 'Oxygen Mono', 'Ubuntu Monospace', 'Source Code Pro',
- 'Fira Mono', 'Droid Sans Mono', 'Courier New', monospace;
-
- --foreground-rgb: 0, 0, 0;
- --background-start-rgb: 214, 219, 220;
- --background-end-rgb: 255, 255, 255;
-
- --primary-glow: conic-gradient(
- from 180deg at 50% 50%,
- #16abff33 0deg,
- #0885ff33 55deg,
- #54d6ff33 120deg,
- #0071ff33 160deg,
- transparent 360deg
- );
- --secondary-glow: radial-gradient(
- rgba(255, 255, 255, 1),
- rgba(255, 255, 255, 0)
- );
-
- --tile-start-rgb: 239, 245, 249;
- --tile-end-rgb: 228, 232, 233;
- --tile-border: conic-gradient(
- #00000080,
- #00000040,
- #00000030,
- #00000020,
- #00000010,
- #00000010,
- #00000080
- );
-
- --callout-rgb: 238, 240, 241;
- --callout-border-rgb: 172, 175, 176;
- --card-rgb: 180, 185, 188;
- --card-border-rgb: 131, 134, 135;
-}
-
-@media (prefers-color-scheme: dark) {
- :root {
- --foreground-rgb: 255, 255, 255;
- --background-start-rgb: 0, 0, 0;
- --background-end-rgb: 0, 0, 0;
-
- --primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0));
- --secondary-glow: linear-gradient(
- to bottom right,
- rgba(1, 65, 255, 0),
- rgba(1, 65, 255, 0),
- rgba(1, 65, 255, 0.3)
- );
-
- --tile-start-rgb: 2, 13, 46;
- --tile-end-rgb: 2, 5, 19;
- --tile-border: conic-gradient(
- #ffffff80,
- #ffffff40,
- #ffffff30,
- #ffffff20,
- #ffffff10,
- #ffffff10,
- #ffffff80
- );
-
- --callout-rgb: 20, 20, 20;
- --callout-border-rgb: 108, 108, 108;
- --card-rgb: 100, 100, 100;
- --card-border-rgb: 200, 200, 200;
- }
-}
-
-* {
- box-sizing: border-box;
- padding: 0;
- margin: 0;
-}
-
-html,
-body {
- max-width: 100vw;
- overflow-x: hidden;
-}
-
-body {
- color: rgb(var(--foreground-rgb));
- background: linear-gradient(
- to bottom,
- transparent,
- rgb(var(--background-end-rgb))
- )
- rgb(var(--background-start-rgb));
-}
-
-a {
- color: inherit;
- text-decoration: none;
-}
-
-@media (prefers-color-scheme: dark) {
- html {
- color-scheme: dark;
- }
-}
diff --git a/tsconfig.json b/tsconfig.json
index 670224f3e..b8e18d5a1 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,6 +1,6 @@
{
"compilerOptions": {
- "target": "es5",
+ "target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
@@ -13,10 +13,24 @@
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
"paths": {
- "@/*": ["./*"]
+ "@/*": ["./src/*"],
+ "@components/*": ["./src/components/*"],
+ "@hooks/*": ["./src/hooks/*"],
+ "@context/*": ["./src/context/*"],
+ "@service/*": ["./src/service/*"],
+ "@util/*": ["./src/util/*"],
+ "@assets/*": ["./src/assets/*"],
+ "@type/*": ["./src/types/*"],
+ "@schemas/*": ["./src/schemas/*"],
+ "@constants/*": ["./src/constants/*"]
}
},
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}