diff --git a/.github/delete-merged-branch-config.yml b/.github/delete-merged-branch-config.yml
new file mode 100644
index 000000000..2a6d27bef
--- /dev/null
+++ b/.github/delete-merged-branch-config.yml
@@ -0,0 +1,15 @@
+name: delete branch on close pr
+
+on:
+ pull_request:
+ types: [closed]
+
+permissions:
+ pull-requests: write
+
+jobs:
+ delete-branch:
+ runs-on: ubuntu-latest
+ steps:
+ - name: delete branch
+ uses: SvanBoxel/delete-merged-branch@main
diff --git a/base.css b/base.css
new file mode 100644
index 000000000..b03cf0605
--- /dev/null
+++ b/base.css
@@ -0,0 +1,5 @@
+*{
+ box-sizing: border-box;
+ font-family: Pretendard;
+ margin: 0;
+}
\ No newline at end of file
diff --git a/image/akar-icons_facebook-fill.svg b/image/akar-icons_facebook-fill.svg
new file mode 100644
index 000000000..af5130815
--- /dev/null
+++ b/image/akar-icons_facebook-fill.svg
@@ -0,0 +1,9 @@
+
diff --git a/image/akar-icons_twitter-fill.svg b/image/akar-icons_twitter-fill.svg
new file mode 100644
index 000000000..4586b559d
--- /dev/null
+++ b/image/akar-icons_twitter-fill.svg
@@ -0,0 +1,5 @@
+
diff --git a/image/akar-icons_youtube-fill.svg b/image/akar-icons_youtube-fill.svg
new file mode 100644
index 000000000..426c2540f
--- /dev/null
+++ b/image/akar-icons_youtube-fill.svg
@@ -0,0 +1,14 @@
+
diff --git a/image/ant-design_instagram-filled.svg b/image/ant-design_instagram-filled.svg
new file mode 100644
index 000000000..acd5df20b
--- /dev/null
+++ b/image/ant-design_instagram-filled.svg
@@ -0,0 +1,5 @@
+
diff --git a/image/folder/logo.svg b/image/folder/logo.svg
new file mode 100644
index 000000000..70dcc424e
--- /dev/null
+++ b/image/folder/logo.svg
@@ -0,0 +1,15 @@
+
diff --git a/image/index/landing.png b/image/index/landing.png
new file mode 100644
index 000000000..d4809f36a
Binary files /dev/null and b/image/index/landing.png differ
diff --git a/image/index/manage-folder.png b/image/index/manage-folder.png
new file mode 100644
index 000000000..27b80aea1
Binary files /dev/null and b/image/index/manage-folder.png differ
diff --git a/image/index/save-link.png b/image/index/save-link.png
new file mode 100644
index 000000000..4397a64dc
Binary files /dev/null and b/image/index/save-link.png differ
diff --git a/image/index/search-link.png b/image/index/search-link.png
new file mode 100644
index 000000000..a48851090
Binary files /dev/null and b/image/index/search-link.png differ
diff --git a/image/index/share-link.png b/image/index/share-link.png
new file mode 100644
index 000000000..653acd59c
Binary files /dev/null and b/image/index/share-link.png differ
diff --git a/image/logo.svg b/image/logo.svg
new file mode 100644
index 000000000..ac750371b
--- /dev/null
+++ b/image/logo.svg
@@ -0,0 +1,15 @@
+
diff --git a/image/search/Search.svg b/image/search/Search.svg
new file mode 100644
index 000000000..0406766fd
--- /dev/null
+++ b/image/search/Search.svg
@@ -0,0 +1,8 @@
+
diff --git a/image/signin/eye-off.svg b/image/signin/eye-off.svg
new file mode 100644
index 000000000..bec50d66f
--- /dev/null
+++ b/image/signin/eye-off.svg
@@ -0,0 +1,6 @@
+
diff --git a/image/signin/eye-on.svg b/image/signin/eye-on.svg
new file mode 100644
index 000000000..61afee898
--- /dev/null
+++ b/image/signin/eye-on.svg
@@ -0,0 +1,6 @@
+
diff --git a/image/social/google.png b/image/social/google.png
new file mode 100644
index 000000000..e6f5aff87
Binary files /dev/null and b/image/social/google.png differ
diff --git a/image/social/kakao.svg b/image/social/kakao.svg
new file mode 100644
index 000000000..7a6062bc6
--- /dev/null
+++ b/image/social/kakao.svg
@@ -0,0 +1,13 @@
+
diff --git a/image/star/state=Default.svg b/image/star/state=Default.svg
new file mode 100644
index 000000000..f7d90ed0b
--- /dev/null
+++ b/image/star/state=Default.svg
@@ -0,0 +1,10 @@
+
diff --git a/index.css b/index.css
new file mode 100644
index 000000000..064931fc9
--- /dev/null
+++ b/index.css
@@ -0,0 +1,355 @@
+/* PC */
+html::-webkit-scrollbar{
+ display: none;
+}
+
+.action-button {
+ padding: 16px 20px;
+
+ color: #F5F5F5;
+ border-radius: 8px;
+
+ font-size: 18px;
+ font-weight: 600;
+ text-align: center;
+ text-decoration: none;
+}
+
+.action-button_nav_add-link {
+ width: 350px;
+
+}
+
+.action-button_nav_signin {
+ width: 128px;
+}
+
+.action-button_grad_blue-sky {
+ background: linear-gradient(91deg, #6D6AFE 0.12%, #6AE3FE 101.84%);
+}
+
+.feature-description {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 157px;
+
+ width: fit-content;
+ max-width: 998px;
+}
+
+.feature-descriptions {
+ display: flex;
+ flex-direction: column;
+ gap: 100px;
+
+ padding: 120px 0 170px;
+
+ background-color: #FFFFFF;
+}
+
+.feature-description__detail-text {
+ color: #6B6B6B;
+ font-size: 16px;
+ font-weight: 500;
+ line-height: 24px;
+}
+
+.feature-description__embrace-text {
+ -webkit-background-clip: text;
+ color: transparent;
+}
+
+.feature-description__embrace-text_grad_blue-gray {
+ background-image: linear-gradient(99deg, #6D7CCD 19.76%, rgba(82, 136, 133, 0.22) 52.69%);
+}
+
+.feature-description__embrace-text_grad_blue-pink {
+ background-image: linear-gradient(271deg, #FE578F -9.84%, #68E8F9 107.18%);
+}
+
+.feature-description__embrace-text_grad_pink-blue {
+ background-image: linear-gradient(96deg, #FE8A8A 1.72%, #A4CEFF 74.97%);
+}
+
+.feature-description__embrace-text_grad_yellow_blue {
+ background-image: linear-gradient(277deg, #6FBAFF 59.22%, #FFD88B 93.66%);
+}
+
+.feature-description__sample-image-background {
+ flex-shrink: 0;
+
+ width: 550px;
+ height: 450px;
+
+ overflow: hidden;
+
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ border-radius: 15px;
+}
+
+.feature-description__sample-image-background_img_manage-folder{
+ background-image: url(./image/index/manage-folder.png);
+}
+
+.feature-description__sample-image-background_img_save-link{
+ background-image: url(./image/index/save-link.png);
+}
+
+.feature-description__sample-image-background_img_search-link{
+ background-image: url(./image/index/search-link.png);
+}
+
+.feature-description__sample-image-background_img_share-link{
+ background-image: url(./image/index/share-link.png);
+}
+.feature-description__text-box {
+ display: flex;
+ flex-direction: column;
+ justify-content: start;
+ gap: 10px;
+}
+
+.feature-description__title {
+ font-size: 48px;
+ font-weight: 700;
+ letter-spacing: -0.3px;
+}
+
+.feature-description_reverse {
+ flex-direction: row-reverse;
+}
+
+.footer {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ padding: 32px 104px 64px;
+ background-color: #111322;
+}
+
+.footer__company-info {
+ font-family: Arial;
+ font-size: 16px;
+ font-weight: 400;
+
+ color: #676767;
+ text-align: center;
+}
+
+.footer__policy-faq {
+ display: flex;
+ align-items: center;
+ gap: 30px;
+
+ font-family: Arial;
+ font-size: 16px;
+ font-weight: 400;
+}
+
+.footer__policy {
+ color: #CFCFCF;
+ text-decoration: none;
+}
+
+.footer__faq {
+ color: #CFCFCF;
+ text-decoration: none;
+}
+
+.footer__sns-icons {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 12px;
+}
+
+.footer__sns-icon {
+ width: 20px;
+ height: 20px;
+ display: block;
+}
+
+.header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 20px 200px;
+ position: sticky;
+ top: 0;
+ z-index: 9999;
+ background-color: #F0F6FF;
+}
+
+.main {
+ background-color: #F0F6FF;
+}
+
+.service-description {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ position: relative;
+ padding-top: 70px;
+ gap: 40px;
+ overflow: hidden;
+}
+
+.service-description__embrace-text {
+ -webkit-background-clip: text;
+ color: transparent;
+}
+
+.service-description__embrace-text_grad_blue-red {
+ background-image: linear-gradient(91deg, #6D6AFE 17.28%, #FF9F9F 74.98%);
+}
+
+.service-description__title {
+ font-size: 64px;
+ font-weight: 700;
+ line-height: 125%;
+ text-align: center;
+}
+
+.service-description__sample-image-background_img_landing {
+ background-image: url(./image/index/landing.png);
+
+}
+
+.service-description__sample-image-background {
+ width: 1200px;
+ height: 590px;
+
+ overflow: hidden;
+
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+}
+
+
+/* Tablet */
+@media all and (max-width:1199px) {
+
+ .feature-description {
+ width: unset;
+ max-width: 698px;
+ gap: 51px;
+ }
+
+ .feature-descriptions {
+ padding: 80px 0 170px;
+ }
+
+ .feature-description__sample-image-background {
+ width: 385px;
+ height: 315px;
+ }
+
+
+ .header{
+ padding: 20px max(calc(100% - 999px),32px);
+ }
+
+ .service-description {
+ width: unset;
+ }
+
+ .service-description__sample-image-background {
+ width: 698px;
+ height: 343px;
+ }
+
+}
+
+/* Mobile */
+@media all and (min-width:375px) and (max-width:767px) {
+
+ .action-button {
+ padding: 10px 16px;
+
+ font-size: 14px;
+ font-weight: 600;
+ }
+
+ .action-button_nav_add-link {
+ width: 200px;
+ }
+
+ .action-button_nav_signin {
+ width: 80px;
+ }
+
+ .feature-description {
+ flex-direction: column;
+ gap: 24px;
+
+ width: unset;
+ width: 100%;
+ }
+
+ .feature-descriptions {
+ padding: 40px 0 80px;
+ gap: 80px;
+ }
+
+
+ .feature-description__detail-text {
+ font-size: 15px;
+ font-weight: 500;
+ line-height: 150%;
+ /* 22.5px */
+ }
+
+ .feature-description__sample-image-background {
+ width: calc(100% - 64px); /* 좌우 여백을 제외한 너비 설정 */
+ height: unset;
+ padding-top: calc((100% - 64px)*265.909/325); /* 높이는 자동으로 설정하여 비율 유지 */
+ }
+
+ .feature-description__text-box{
+ width: 325px;
+ }
+ .feature-description__title {
+ font-size: 24px;
+ font-weight: 700;
+ letter-spacing: -0.3px;
+ }
+
+ .footer{
+ position: relative;
+
+ height: 160px;
+ padding: 32px 32px 64px;
+ }
+
+ .footer__company-info{
+ position:absolute;
+ top: 108px;
+ }
+
+ .header{
+ padding: 13px 32px;
+ }
+
+ .service-description {
+ gap:24px;
+
+ width: unset;
+ }
+
+ .service-description__sample-image-background {
+ width: calc(100% - 64px); /* 좌우 여백을 제외한 너비 설정 */
+ height: unset;
+ padding-top: calc((100% - 64px) * 590/1200); /* 높이는 자동으로 설정하여 비율 유지 */
+ }
+
+ .service-description__title {
+ font-size: 32px;
+ font-weight: 700;
+ line-height: 42px;
+ }
+}
\ No newline at end of file
diff --git a/index.html b/index.html
new file mode 100644
index 000000000..4c2f9650d
--- /dev/null
+++ b/index.html
@@ -0,0 +1,146 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Linkbrary
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 세상의 모든 정보를
+
+ 쉽게 저장하고 관리해 보세요
+
+ 링크 추가하기
+
+
+
+
+
+
+
+
+ 원하는 링크를
+ 저장하세요
+
+
+ 나중에 읽고 싶은 글, 다시 보고 싶은 영상,
+ 사고 싶은 옷, 기억하고 싶은 모든 것을
+ 한 공간에 저장하세요.
+
+
+
+
+
+
+
+
+
+ 링크를 폴더로
+ 관리하세요
+
+
+ 나만의 폴더를 무제한으로 만들고 다양하게 활용할 수 있습니다.
+
+
+
+
+
+
+
+
+ 저장한 링크를
+ 공유해 보세요
+
+
+ 여러 링크를 폴더에 담고 공유할 수 있습니다.
+ 가족, 친구, 동료들에게 쉽고 빠르게 링크를 공유해 보세요.
+
+
+
+
+
+
+
+
+ 저장한 링크를
+ 검색해 보세요
+
+
중요한 정보들을 검색으로 쉽게 찾아보세요.
+
+
+
+
+
+
+
+
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 000000000..eb97d5d55
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,1406 @@
+{
+ "name": "2-weekly-mission",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "dependencies": {
+ "@vitejs/plugin-react": "^4.2.0",
+ "classnames": "^2.3.2",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "vite": "^5.0.2"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
+ "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.0",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.23.4",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.4.tgz",
+ "integrity": "sha512-r1IONyb6Ia+jYR2vvIDhdWdlTGhqbBoFqLTQidzZ4kepUFH15ejXvFHxCVbtl7BOXIudsIubf4E81xeA3h3IXA==",
+ "dependencies": {
+ "@babel/highlight": "^7.23.4",
+ "chalk": "^2.4.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.23.3",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.3.tgz",
+ "integrity": "sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.23.3",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.3.tgz",
+ "integrity": "sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==",
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.22.13",
+ "@babel/generator": "^7.23.3",
+ "@babel/helper-compilation-targets": "^7.22.15",
+ "@babel/helper-module-transforms": "^7.23.3",
+ "@babel/helpers": "^7.23.2",
+ "@babel/parser": "^7.23.3",
+ "@babel/template": "^7.22.15",
+ "@babel/traverse": "^7.23.3",
+ "@babel/types": "^7.23.3",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.23.4",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.4.tgz",
+ "integrity": "sha512-esuS49Cga3HcThFNebGhlgsrVLkvhqvYDTzgjfFFlHJcIfLe5jFmRRfCQ1KuBfc4Jrtn3ndLgKWAKjBE+IraYQ==",
+ "dependencies": {
+ "@babel/types": "^7.23.4",
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "@jridgewell/trace-mapping": "^0.3.17",
+ "jsesc": "^2.5.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
+ "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
+ "dependencies": {
+ "@babel/compat-data": "^7.22.9",
+ "@babel/helper-validator-option": "^7.22.15",
+ "browserslist": "^4.21.9",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-environment-visitor": {
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
+ "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-function-name": {
+ "version": "7.23.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
+ "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
+ "dependencies": {
+ "@babel/template": "^7.22.15",
+ "@babel/types": "^7.23.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-hoist-variables": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
+ "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
+ "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
+ "dependencies": {
+ "@babel/types": "^7.22.15"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.23.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz",
+ "integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==",
+ "dependencies": {
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-module-imports": "^7.22.15",
+ "@babel/helper-simple-access": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/helper-validator-identifier": "^7.22.20"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
+ "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-simple-access": {
+ "version": "7.22.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
+ "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-split-export-declaration": {
+ "version": "7.22.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
+ "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
+ "dependencies": {
+ "@babel/types": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.23.4",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz",
+ "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.22.20",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
+ "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
+ "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.23.4",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.4.tgz",
+ "integrity": "sha512-HfcMizYz10cr3h29VqyfGL6ZWIjTwWfvYBMsBVGwpcbhNGe3wQ1ZXZRPzZoAHhd9OqHadHqjQ89iVKINXnbzuw==",
+ "dependencies": {
+ "@babel/template": "^7.22.15",
+ "@babel/traverse": "^7.23.4",
+ "@babel/types": "^7.23.4"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/highlight": {
+ "version": "7.23.4",
+ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz",
+ "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.22.20",
+ "chalk": "^2.4.2",
+ "js-tokens": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.23.4",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.4.tgz",
+ "integrity": "sha512-vf3Xna6UEprW+7t6EtOmFpHNAuxw3xqPZghy+brsnusscJRW5BMUzzHZc5ICjULee81WeUV2jjakG09MDglJXQ==",
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
+ "version": "7.23.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.23.3.tgz",
+ "integrity": "sha512-qXRvbeKDSfwnlJnanVRp0SfuWE5DQhwQr5xtLBzp56Wabyo+4CMosF6Kfp+eOD/4FYpql64XVJ2W0pVLlJZxOQ==",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
+ "version": "7.23.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.23.3.tgz",
+ "integrity": "sha512-91RS0MDnAWDNvGC6Wio5XYkyWI39FMFO+JK9+4AlgaTH+yWwVTsw7/sn6LK0lH7c5F+TFkpv/3LfCJ1Ydwof/g==",
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.22.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.22.15",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+ "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+ "dependencies": {
+ "@babel/code-frame": "^7.22.13",
+ "@babel/parser": "^7.22.15",
+ "@babel/types": "^7.22.15"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.23.4",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.4.tgz",
+ "integrity": "sha512-IYM8wSUwunWTB6tFC2dkKZhxbIjHoWemdK+3f8/wq8aKhbUscxD5MX72ubd90fxvFknaLPeGw5ycU84V1obHJg==",
+ "dependencies": {
+ "@babel/code-frame": "^7.23.4",
+ "@babel/generator": "^7.23.4",
+ "@babel/helper-environment-visitor": "^7.22.20",
+ "@babel/helper-function-name": "^7.23.0",
+ "@babel/helper-hoist-variables": "^7.22.5",
+ "@babel/helper-split-export-declaration": "^7.22.6",
+ "@babel/parser": "^7.23.4",
+ "@babel/types": "^7.23.4",
+ "debug": "^4.1.0",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.23.4",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.4.tgz",
+ "integrity": "sha512-7uIFwVYpoplT5jp/kVv6EF93VaJ8H+Yn5IczYiaAi98ajzjfoZfslet/e0sLh+wVBjb2qqIut1b0S26VSafsSQ==",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.23.4",
+ "@babel/helper-validator-identifier": "^7.22.20",
+ "to-fast-properties": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.7.tgz",
+ "integrity": "sha512-YGSPnndkcLo4PmVl2tKatEn+0mlVMr3yEpOOT0BeMria87PhvoJb5dg5f5Ft9fbCVgtAz4pWMzZVgSEGpDAlww==",
+ "cpu": [
+ "arm"
+ ],
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.7.tgz",
+ "integrity": "sha512-YEDcw5IT7hW3sFKZBkCAQaOCJQLONVcD4bOyTXMZz5fr66pTHnAet46XAtbXAkJRfIn2YVhdC6R9g4xa27jQ1w==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.7.tgz",
+ "integrity": "sha512-jhINx8DEjz68cChFvM72YzrqfwJuFbfvSxZAk4bebpngGfNNRm+zRl4rtT9oAX6N9b6gBcFaJHFew5Blf6CvUw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.7.tgz",
+ "integrity": "sha512-dr81gbmWN//3ZnBIm6YNCl4p3pjnabg1/ZVOgz2fJoUO1a3mq9WQ/1iuEluMs7mCL+Zwv7AY5e3g1hjXqQZ9Iw==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.7.tgz",
+ "integrity": "sha512-Lc0q5HouGlzQEwLkgEKnWcSazqr9l9OdV2HhVasWJzLKeOt0PLhHaUHuzb8s/UIya38DJDoUm74GToZ6Wc7NGQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.7.tgz",
+ "integrity": "sha512-+y2YsUr0CxDFF7GWiegWjGtTUF6gac2zFasfFkRJPkMAuMy9O7+2EH550VlqVdpEEchWMynkdhC9ZjtnMiHImQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.7.tgz",
+ "integrity": "sha512-CdXOxIbIzPJmJhrpmJTLx+o35NoiKBIgOvmvT+jeSadYiWJn0vFKsl+0bSG/5lwjNHoIDEyMYc/GAPR9jxusTA==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.7.tgz",
+ "integrity": "sha512-Y+SCmWxsJOdQtjcBxoacn/pGW9HDZpwsoof0ttL+2vGcHokFlfqV666JpfLCSP2xLxFpF1lj7T3Ox3sr95YXww==",
+ "cpu": [
+ "arm"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.7.tgz",
+ "integrity": "sha512-inHqdOVCkUhHNvuQPT1oCB7cWz9qQ/Cz46xmVe0b7UXcuIJU3166aqSunsqkgSGMtUCWOZw3+KMwI6otINuC9g==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.7.tgz",
+ "integrity": "sha512-2BbiL7nLS5ZO96bxTQkdO0euGZIUQEUXMTrqLxKUmk/Y5pmrWU84f+CMJpM8+EHaBPfFSPnomEaQiG/+Gmh61g==",
+ "cpu": [
+ "ia32"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.7.tgz",
+ "integrity": "sha512-BVFQla72KXv3yyTFCQXF7MORvpTo4uTA8FVFgmwVrqbB/4DsBFWilUm1i2Oq6zN36DOZKSVUTb16jbjedhfSHw==",
+ "cpu": [
+ "loong64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.7.tgz",
+ "integrity": "sha512-DzAYckIaK+pS31Q/rGpvUKu7M+5/t+jI+cdleDgUwbU7KdG2eC3SUbZHlo6Q4P1CfVKZ1lUERRFP8+q0ob9i2w==",
+ "cpu": [
+ "mips64el"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.7.tgz",
+ "integrity": "sha512-JQ1p0SmUteNdUaaiRtyS59GkkfTW0Edo+e0O2sihnY4FoZLz5glpWUQEKMSzMhA430ctkylkS7+vn8ziuhUugQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.7.tgz",
+ "integrity": "sha512-xGwVJ7eGhkprY/nB7L7MXysHduqjpzUl40+XoYDGC4UPLbnG+gsyS1wQPJ9lFPcxYAaDXbdRXd1ACs9AE9lxuw==",
+ "cpu": [
+ "riscv64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.7.tgz",
+ "integrity": "sha512-U8Rhki5PVU0L0nvk+E8FjkV8r4Lh4hVEb9duR6Zl21eIEYEwXz8RScj4LZWA2i3V70V4UHVgiqMpszXvG0Yqhg==",
+ "cpu": [
+ "s390x"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.7.tgz",
+ "integrity": "sha512-ZYZopyLhm4mcoZXjFt25itRlocKlcazDVkB4AhioiL9hOWhDldU9n38g62fhOI4Pth6vp+Mrd5rFKxD0/S+7aQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.7.tgz",
+ "integrity": "sha512-/yfjlsYmT1O3cum3J6cmGG16Fd5tqKMcg5D+sBYLaOQExheAJhqr8xOAEIuLo8JYkevmjM5zFD9rVs3VBcsjtQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.7.tgz",
+ "integrity": "sha512-MYDFyV0EW1cTP46IgUJ38OnEY5TaXxjoDmwiTXPjezahQgZd+j3T55Ht8/Q9YXBM0+T9HJygrSRGV5QNF/YVDQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.7.tgz",
+ "integrity": "sha512-JcPvgzf2NN/y6X3UUSqP6jSS06V0DZAV/8q0PjsZyGSXsIGcG110XsdmuWiHM+pno7/mJF6fjH5/vhUz/vA9fw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.7.tgz",
+ "integrity": "sha512-ZA0KSYti5w5toax5FpmfcAgu3ZNJxYSRm0AW/Dao5up0YV1hDVof1NvwLomjEN+3/GMtaWDI+CIyJOMTRSTdMw==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.7.tgz",
+ "integrity": "sha512-CTOnijBKc5Jpk6/W9hQMMvJnsSYRYgveN6O75DTACCY18RA2nqka8dTZR+x/JqXCRiKk84+5+bRKXUSbbwsS0A==",
+ "cpu": [
+ "ia32"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.7.tgz",
+ "integrity": "sha512-gRaP2sk6hc98N734luX4VpF318l3w+ofrtTu9j5L8EQXF+FzQKV6alCOHMVoJJHvVK/mGbwBXfOL1HETQu9IGQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
+ "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.0.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.9"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz",
+ "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
+ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.4.15",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.20",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
+ "integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.5.2.tgz",
+ "integrity": "sha512-ee7BudTwwrglFYSc3UnqInDDjCLWHKrFmGNi4aK7jlEyg4CyPa1DCMrZfsN1O13YT76UFEqXz2CoN7BCGpUlJw==",
+ "cpu": [
+ "arm"
+ ],
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.5.2.tgz",
+ "integrity": "sha512-xOuhj9HHtn8128ir8veoQsBbAUBasDbHIBniYTEx02pAmu9EXL+ZjJqngnNEy6ZgZ4h1JwL33GMNu3yJL5Mzow==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.5.2.tgz",
+ "integrity": "sha512-NTGJWoL8bKyqyWFn9/RzSv4hQ4wTbaAv0lHHRwf4OnpiiP4P8W0jiXbm8Nc5BCXKmWAwuvJY82mcIU2TayC20g==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.5.2.tgz",
+ "integrity": "sha512-hlKqj7bpPvU15sZo4za14u185lpMzdwWLMc9raMqPK4wywt0wR23y1CaVQ4oAFXat3b5/gmRntyfpwWTKl+vvA==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.5.2.tgz",
+ "integrity": "sha512-7ZIZx8c3u+pfI0ohQsft/GywrXez0uR6dUP0JhBuCK3sFO5TfdLn/YApnVkvPxuTv3+YKPIZend9Mt7Cz6sS3Q==",
+ "cpu": [
+ "arm"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.5.2.tgz",
+ "integrity": "sha512-7Pk/5mO11JW/cH+a8lL/i0ZxmRGrbpYqN0VwO2DHhU+SJWWOH2zE1RAcPaj8KqiwC8DCDIJOSxjV9+9lLb6aeA==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.5.2.tgz",
+ "integrity": "sha512-KrRnuG5phJx756e62wxvWH2e+TK84MP2IVuPwfge+GBvWqIUfVzFRn09TKruuQBXzZp52Vyma7FjMDkwlA9xpg==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.5.2.tgz",
+ "integrity": "sha512-My+53GasPa2D2tU5dXiyHYwrELAUouSfkNlZ3bUKpI7btaztO5vpALEs3mvFjM7aKTvEbc7GQckuXeXIDKQ0fg==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.5.2.tgz",
+ "integrity": "sha512-/f0Q6Sc+Vw54Ws6N8fxaEe4R7at3b8pFyv+O/F2VaQ4hODUJcRUcCBJh6zuqtgQQt7w845VTkGLFgWZkP3tUoQ==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.5.2.tgz",
+ "integrity": "sha512-NCKuuZWLht6zj7s6EIFef4BxCRX1GMr83S2W4HPCA0RnJ4iHE4FS1695q6Ewoa6A9nFjJe1//yUu0kgBU07Edw==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.5.2.tgz",
+ "integrity": "sha512-J5zL3riR4AOyU/J3M/i4k/zZ8eP1yT+nTmAKztCXJtnI36jYH0eepvob22mAQ/kLwfsK2TB6dbyVY1F8c/0H5A==",
+ "cpu": [
+ "ia32"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.5.2.tgz",
+ "integrity": "sha512-pL0RXRHuuGLhvs7ayX/SAHph1hrDPXOM5anyYUQXWJEENxw3nfHkzv8FfVlEVcLyKPAEgDRkd6RKZq2SMqS/yg==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.6.7",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.7.tgz",
+ "integrity": "sha512-6Sfsq+EaaLrw4RmdFWE9Onp63TOUue71AWb4Gpa6JxzgTYtimbM086WnYTy2U67AofR++QKCo08ZP6pwx8YFHQ==",
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.20.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.4.tgz",
+ "integrity": "sha512-mSM/iKUk5fDDrEV/e83qY+Cr3I1+Q3qqTuEn++HAWYjEa1+NxZr6CNrcJGf2ZTnq4HoFGC3zaTPZTobCzCFukA==",
+ "dependencies": {
+ "@babel/types": "^7.20.7"
+ }
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.2.0.tgz",
+ "integrity": "sha512-+MHTH/e6H12kRp5HUkzOGqPMksezRMmW+TNzlh/QXfI8rRf6l2Z2yH/v12no1UvTwhZgEDMuQ7g7rrfMseU6FQ==",
+ "dependencies": {
+ "@babel/core": "^7.23.3",
+ "@babel/plugin-transform-react-jsx-self": "^7.23.3",
+ "@babel/plugin-transform-react-jsx-source": "^7.23.3",
+ "@types/babel__core": "^7.20.4",
+ "react-refresh": "^0.14.0"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.22.1",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz",
+ "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001541",
+ "electron-to-chromium": "^1.4.535",
+ "node-releases": "^2.0.13",
+ "update-browserslist-db": "^1.0.13"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "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==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ]
+ },
+ "node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/classnames": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
+ "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
+ },
+ "node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="
+ },
+ "node_modules/debug": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
+ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dependencies": {
+ "ms": "2.1.2"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.4.594",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.594.tgz",
+ "integrity": "sha512-xT1HVAu5xFn7bDfkjGQi9dNpMqGchUkebwf1GL7cZN32NSwwlHRPMSDJ1KN6HkS0bWUtndbSQZqvpQftKG2uFQ=="
+ },
+ "node_modules/esbuild": {
+ "version": "0.19.7",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.7.tgz",
+ "integrity": "sha512-6brbTZVqxhqgbpqBR5MzErImcpA0SQdoKOkcWK/U30HtQxnokIpG3TX2r0IJqbFUzqLjhU/zC1S5ndgakObVCQ==",
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/android-arm": "0.19.7",
+ "@esbuild/android-arm64": "0.19.7",
+ "@esbuild/android-x64": "0.19.7",
+ "@esbuild/darwin-arm64": "0.19.7",
+ "@esbuild/darwin-x64": "0.19.7",
+ "@esbuild/freebsd-arm64": "0.19.7",
+ "@esbuild/freebsd-x64": "0.19.7",
+ "@esbuild/linux-arm": "0.19.7",
+ "@esbuild/linux-arm64": "0.19.7",
+ "@esbuild/linux-ia32": "0.19.7",
+ "@esbuild/linux-loong64": "0.19.7",
+ "@esbuild/linux-mips64el": "0.19.7",
+ "@esbuild/linux-ppc64": "0.19.7",
+ "@esbuild/linux-riscv64": "0.19.7",
+ "@esbuild/linux-s390x": "0.19.7",
+ "@esbuild/linux-x64": "0.19.7",
+ "@esbuild/netbsd-x64": "0.19.7",
+ "@esbuild/openbsd-x64": "0.19.7",
+ "@esbuild/sunos-x64": "0.19.7",
+ "@esbuild/win32-arm64": "0.19.7",
+ "@esbuild/win32-ia32": "0.19.7",
+ "@esbuild/win32-x64": "0.19.7"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
+ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "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=="
+ },
+ "node_modules/jsesc": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
+ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "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==",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "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=="
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
+ "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.13",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
+ "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ=="
+ },
+ "node_modules/picocolors": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+ },
+ "node_modules/postcss": {
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.6",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "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"
+ },
+ "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==",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.0"
+ },
+ "peerDependencies": {
+ "react": "^18.2.0"
+ }
+ },
+ "node_modules/react-refresh": {
+ "version": "0.14.0",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz",
+ "integrity": "sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "4.5.2",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.5.2.tgz",
+ "integrity": "sha512-CRK1uoROBfkcqrZKyaFcqCcZWNsvJ6yVYZkqTlRocZhO2s5yER6Z3f/QaYtO8RGyloPnmhwgzuPQpNGeK210xQ==",
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.5.2",
+ "@rollup/rollup-android-arm64": "4.5.2",
+ "@rollup/rollup-darwin-arm64": "4.5.2",
+ "@rollup/rollup-darwin-x64": "4.5.2",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.5.2",
+ "@rollup/rollup-linux-arm64-gnu": "4.5.2",
+ "@rollup/rollup-linux-arm64-musl": "4.5.2",
+ "@rollup/rollup-linux-x64-gnu": "4.5.2",
+ "@rollup/rollup-linux-x64-musl": "4.5.2",
+ "@rollup/rollup-win32-arm64-msvc": "4.5.2",
+ "@rollup/rollup-win32-ia32-msvc": "4.5.2",
+ "@rollup/rollup-win32-x64-msvc": "4.5.2",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
+ "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/to-fast-properties": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+ "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.0.13",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
+ "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "escalade": "^3.1.1",
+ "picocolors": "^1.0.0"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/vite": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.0.2.tgz",
+ "integrity": "sha512-6CCq1CAJCNM1ya2ZZA7+jS2KgnhbzvxakmlIjN24cF/PXhRMzpM/z8QgsVJA/Dm5fWUWnVEsmtBoMhmerPxT0g==",
+ "dependencies": {
+ "esbuild": "^0.19.3",
+ "postcss": "^8.4.31",
+ "rollup": "^4.2.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || >=20.0.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+ }
+ }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 000000000..cdb8104bf
--- /dev/null
+++ b/package.json
@@ -0,0 +1,16 @@
+{
+ "dependencies": {
+ "@vitejs/plugin-react": "^4.2.0",
+ "classnames": "^2.3.2",
+ "react": "^18.2.0",
+ "react-dom": "^18.2.0"
+ },
+ "devDependencies": {
+ "vite": "^5.0.2"
+ },
+ "scripts": {
+ "dev": "vite",
+ "build": "vite build",
+ "serve": "vite preview"
+ }
+}
diff --git a/reset.css b/reset.css
new file mode 100644
index 000000000..b211cb197
--- /dev/null
+++ b/reset.css
@@ -0,0 +1,349 @@
+/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
+
+/* Document
+ ========================================================================== */
+
+/**
+ * 1. Correct the line height in all browsers.
+ * 2. Prevent adjustments of font size after orientation changes in iOS.
+ */
+
+ html {
+ line-height: 1.15; /* 1 */
+ -webkit-text-size-adjust: 100%; /* 2 */
+ }
+
+ /* Sections
+ ========================================================================== */
+
+ /**
+ * Remove the margin in all browsers.
+ */
+
+ body {
+ margin: 0;
+ }
+
+ /**
+ * Render the `main` element consistently in IE.
+ */
+
+ main {
+ display: block;
+ }
+
+ /**
+ * Correct the font size and margin on `h1` elements within `section` and
+ * `article` contexts in Chrome, Firefox, and Safari.
+ */
+
+ h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+ }
+
+ /* Grouping content
+ ========================================================================== */
+
+ /**
+ * 1. Add the correct box sizing in Firefox.
+ * 2. Show the overflow in Edge and IE.
+ */
+
+ hr {
+ box-sizing: content-box; /* 1 */
+ height: 0; /* 1 */
+ overflow: visible; /* 2 */
+ }
+
+ /**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+ pre {
+ font-family: monospace, monospace; /* 1 */
+ font-size: 1em; /* 2 */
+ }
+
+ /* Text-level semantics
+ ========================================================================== */
+
+ /**
+ * Remove the gray background on active links in IE 10.
+ */
+
+ a {
+ background-color: transparent;
+ }
+
+ /**
+ * 1. Remove the bottom border in Chrome 57-
+ * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
+ */
+
+ abbr[title] {
+ border-bottom: none; /* 1 */
+ text-decoration: underline; /* 2 */
+ text-decoration: underline dotted; /* 2 */
+ }
+
+ /**
+ * Add the correct font weight in Chrome, Edge, and Safari.
+ */
+
+ b,
+ strong {
+ font-weight: bolder;
+ }
+
+ /**
+ * 1. Correct the inheritance and scaling of font size in all browsers.
+ * 2. Correct the odd `em` font sizing in all browsers.
+ */
+
+ code,
+ kbd,
+ samp {
+ font-family: monospace, monospace; /* 1 */
+ font-size: 1em; /* 2 */
+ }
+
+ /**
+ * Add the correct font size in all browsers.
+ */
+
+ small {
+ font-size: 80%;
+ }
+
+ /**
+ * Prevent `sub` and `sup` elements from affecting the line height in
+ * all browsers.
+ */
+
+ sub,
+ sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+ }
+
+ sub {
+ bottom: -0.25em;
+ }
+
+ sup {
+ top: -0.5em;
+ }
+
+ /* Embedded content
+ ========================================================================== */
+
+ /**
+ * Remove the border on images inside links in IE 10.
+ */
+
+ img {
+ border-style: none;
+ }
+
+ /* Forms
+ ========================================================================== */
+
+ /**
+ * 1. Change the font styles in all browsers.
+ * 2. Remove the margin in Firefox and Safari.
+ */
+
+ button,
+ input,
+ optgroup,
+ select,
+ textarea {
+ font-family: inherit; /* 1 */
+ font-size: 100%; /* 1 */
+ line-height: 1.15; /* 1 */
+ margin: 0; /* 2 */
+ }
+
+ /**
+ * Show the overflow in IE.
+ * 1. Show the overflow in Edge.
+ */
+
+ button,
+ input { /* 1 */
+ overflow: visible;
+ }
+
+ /**
+ * Remove the inheritance of text transform in Edge, Firefox, and IE.
+ * 1. Remove the inheritance of text transform in Firefox.
+ */
+
+ button,
+ select { /* 1 */
+ text-transform: none;
+ }
+
+ /**
+ * Correct the inability to style clickable types in iOS and Safari.
+ */
+
+ button,
+ [type="button"],
+ [type="reset"],
+ [type="submit"] {
+ -webkit-appearance: button;
+ }
+
+ /**
+ * Remove the inner border and padding in Firefox.
+ */
+
+ button::-moz-focus-inner,
+ [type="button"]::-moz-focus-inner,
+ [type="reset"]::-moz-focus-inner,
+ [type="submit"]::-moz-focus-inner {
+ border-style: none;
+ padding: 0;
+ }
+
+ /**
+ * Restore the focus styles unset by the previous rule.
+ */
+
+ button:-moz-focusring,
+ [type="button"]:-moz-focusring,
+ [type="reset"]:-moz-focusring,
+ [type="submit"]:-moz-focusring {
+ outline: 1px dotted ButtonText;
+ }
+
+ /**
+ * Correct the padding in Firefox.
+ */
+
+ fieldset {
+ padding: 0.35em 0.75em 0.625em;
+ }
+
+ /**
+ * 1. Correct the text wrapping in Edge and IE.
+ * 2. Correct the color inheritance from `fieldset` elements in IE.
+ * 3. Remove the padding so developers are not caught out when they zero out
+ * `fieldset` elements in all browsers.
+ */
+
+ legend {
+ box-sizing: border-box; /* 1 */
+ color: inherit; /* 2 */
+ display: table; /* 1 */
+ max-width: 100%; /* 1 */
+ padding: 0; /* 3 */
+ white-space: normal; /* 1 */
+ }
+
+ /**
+ * Add the correct vertical alignment in Chrome, Firefox, and Opera.
+ */
+
+ progress {
+ vertical-align: baseline;
+ }
+
+ /**
+ * Remove the default vertical scrollbar in IE 10+.
+ */
+
+ textarea {
+ overflow: auto;
+ }
+
+ /**
+ * 1. Add the correct box sizing in IE 10.
+ * 2. Remove the padding in IE 10.
+ */
+
+ [type="checkbox"],
+ [type="radio"] {
+ box-sizing: border-box; /* 1 */
+ padding: 0; /* 2 */
+ }
+
+ /**
+ * Correct the cursor style of increment and decrement buttons in Chrome.
+ */
+
+ [type="number"]::-webkit-inner-spin-button,
+ [type="number"]::-webkit-outer-spin-button {
+ height: auto;
+ }
+
+ /**
+ * 1. Correct the odd appearance in Chrome and Safari.
+ * 2. Correct the outline style in Safari.
+ */
+
+ [type="search"] {
+ -webkit-appearance: textfield; /* 1 */
+ outline-offset: -2px; /* 2 */
+ }
+
+ /**
+ * Remove the inner padding in Chrome and Safari on macOS.
+ */
+
+ [type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+ }
+
+ /**
+ * 1. Correct the inability to style clickable types in iOS and Safari.
+ * 2. Change font properties to `inherit` in Safari.
+ */
+
+ ::-webkit-file-upload-button {
+ -webkit-appearance: button; /* 1 */
+ font: inherit; /* 2 */
+ }
+
+ /* Interactive
+ ========================================================================== */
+
+ /*
+ * Add the correct display in Edge, IE 10+, and Firefox.
+ */
+
+ details {
+ display: block;
+ }
+
+ /*
+ * Add the correct display in all browsers.
+ */
+
+ summary {
+ display: list-item;
+ }
+
+ /* Misc
+ ========================================================================== */
+
+ /**
+ * Add the correct display in IE 10+.
+ */
+
+ template {
+ display: none;
+ }
+
+ /**
+ * Add the correct display in IE 10.
+ */
+
+ [hidden] {
+ display: none;
+ }
\ No newline at end of file
diff --git a/script/SignIn.js b/script/SignIn.js
new file mode 100644
index 000000000..5fb9bdf01
--- /dev/null
+++ b/script/SignIn.js
@@ -0,0 +1,14 @@
+import {signInInputFocusOutCheckHandler, testSignInButtonClickCheckHandler, showIconClickHandler} from './SignUtility.js';
+
+const inputFormInputs = document.querySelectorAll(`.input-form__input`);
+for(const inputFormInput of inputFormInputs){
+ inputFormInput.addEventListener('focusout', signInInputFocusOutCheckHandler);
+}
+
+const showIcons = document.querySelectorAll(`.input-form__show-icon`);
+for(const showIcon of showIcons){
+ showIcon.addEventListener('click', showIconClickHandler);
+}
+
+const loginButton = document.querySelector(`.action-button_signin`);
+loginButton.addEventListener('click', testSignInButtonClickCheckHandler);
\ No newline at end of file
diff --git a/script/SignUtility.js b/script/SignUtility.js
new file mode 100644
index 000000000..48fdf06c5
--- /dev/null
+++ b/script/SignUtility.js
@@ -0,0 +1,306 @@
+const email = `email`;
+const password = `password`;
+const passwordCheck = `password-check`;
+
+const inputFormClass = `input-form`
+const inputFormInputClass = `${inputFormClass}__input`;
+
+const showIconClass = `${inputFormClass}__show-icon`;
+const showIconOffClass = `${showIconClass}_eye-off`;
+
+const errorClass = `${inputFormClass}__input_error`;
+
+const SignRegex = {
+ [email]: /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/,
+ // 갈이 8~20, 영문자, 숫자 1개 이상
+ [password]: /^(?=.*[a-zA-Z])(?=.*[0-9]).{8,20}$/,
+};
+
+const SignErrorMessage = {
+ [email]: {
+ nothing: `이메일을 입력해주세요`,
+ invaild: `올바른 이메일 주소가 아닙니다`,
+ used: `이미 사용 중인 이메일입니다`,
+ other: `이메일을 확인해주세요`,
+ },
+ [password]: {
+ nothing: `비밀번호을 입력해주세요`,
+ invaild: `비밀번호는 영문, 숫자 조합 8자 이상 입력해주세요`,
+ other: `비밀번호을 확인해주세요`,
+ },
+ [passwordCheck]: {
+ different: `비밀번호가 일치하지 않아요`,
+ }
+};
+
+const TestLoginInfo = {
+ [email]: `test@codeit.kr`,
+ [password]: `codeit101`,
+}
+
+function signInInputFocusOutCheckHandler(e) {
+ const { target } = e;
+
+ const errorMessage = getSignInErrorMessageByTarget(target);
+ handleErrorMessageElement(target, errorMessage);
+}
+
+function signUpInputFocusOutCheckHandler(e) {
+ const { target } = e;
+
+ const errorMessage = getSignUpErrorMessageByTarget(target);
+ handleErrorMessageElement(target, errorMessage);
+}
+
+
+function getSignInErrorMessageByTarget(target) {
+ switch (target.name) {
+ case email: {
+ if (nothingErrorCheck(target)) {
+ return SignErrorMessage[email].nothing;
+ }
+
+ if (invalidErrorCheck(target)) {
+ return SignErrorMessage[email].invaild;
+ }
+
+ break;
+ }
+
+ case password: {
+ if (nothingErrorCheck(target)) {
+ return SignErrorMessage[password].nothing;
+ }
+
+ if (invalidErrorCheck(target)) {
+ return SignErrorMessage[password].invaild;
+ }
+
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return undefined;
+}
+
+function getSignUpErrorMessageByTarget(target) {
+ switch (target.name) {
+ case email: {
+ if (nothingErrorCheck(target)) {
+ return SignErrorMessage[email].nothing;
+ }
+
+ if (invalidErrorCheck(target)) {
+ return SignErrorMessage[email].invaild;
+ }
+
+ if (usedErrorCheck(target)) {
+ return SignErrorMessage[email].used;
+ }
+
+ break;
+ }
+
+ case password: {
+ if (nothingErrorCheck(target)) {
+ return SignErrorMessage[password].nothing;
+ }
+
+ if (invalidErrorCheck(target)) {
+ return SignErrorMessage[password].invaild;
+ }
+
+ break;
+ }
+
+ case passwordCheck: {
+ if (differentErrorCheck(target)) {
+ return SignErrorMessage[passwordCheck].different;
+ }
+
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return undefined;
+}
+
+function getErrorMessageElement(elements) {
+
+ for (const element of elements) {
+ if (element.classList.contains(errorClass)) {
+ return element;
+ }
+ }
+
+ return null;
+}
+
+function testSignInButtonClickCheckHandler(e) {
+ const inputFormInputList = findinputFormInputList();
+
+ let isError = false;
+
+ for (const inputFormInput of inputFormInputList) {
+ if (!otherErrorCheck(inputFormInput)) {
+ isError = true;
+ break;
+ }
+ }
+
+ console.log(isError)
+ if (isError) {
+ for (const inputFormInput of inputFormInputList) {
+ putErrorMessageParentsSibling(inputFormInput, SignErrorMessage[inputFormInput.name].other);
+ addErrorClassOnInputForm(inputFormInput);
+ }
+ } else {
+ goToFolderPage();
+ }
+}
+
+function testSignUpButtonClickCheckHandler(e) {
+ const inputFormInputList = findinputFormInputList();
+
+ let isError = false;
+
+ for (const inputFormInput of inputFormInputList) {
+ const errorMessage = getSignUpErrorMessageByTarget(inputFormInput);
+ handleErrorMessageElement(inputFormInput, errorMessage);
+
+ errorMessage? isError = true: null;
+ }
+
+ if(!isError){
+ goToFolderPage();
+ }
+}
+
+/**
+ *
+ * @param {KeyboardEvent} e
+ */
+function testSignUpInputCheckHandler(e){
+ if(e.key === 'Enter'){
+ testSignUpButtonClickCheckHandler(e);
+ }
+}
+
+function findinputFormInputList() {
+ return document.querySelectorAll(`.${inputFormInputClass}`);
+}
+
+function handleErrorMessageElement(target, errorMessage) {
+ if (errorMessage) {
+ putErrorMessageParentsSibling(target, errorMessage);
+ addErrorClassOnInputForm(target);
+ } else {
+ deleteErrorMessageParentsSibling(target);
+ deleteErrorClassOnInputForm(target);
+ }
+}
+
+function nothingErrorCheck(element) {
+ const { value } = element;
+
+ if (value === "") {
+ return true;
+ }
+
+ return false;
+}
+
+function invalidErrorCheck(element) {
+ const { name, value } = element;
+
+ return !SignRegex[name].test(value);
+}
+
+function usedErrorCheck(element) {
+ const { name, value } = element;
+
+ return value === TestLoginInfo[name];
+}
+
+function differentErrorCheck(element) {
+ const { value } = document.querySelector('#signup-password');
+ const passwordCheckValue = element.value;
+
+ if (value !== passwordCheckValue) {
+ return true;
+ }
+
+ return false;
+}
+
+function otherErrorCheck(inputFormInput) {
+ const { value, name } = inputFormInput;
+
+ switch (name) {
+ case email: {
+ return value === TestLoginInfo[email];
+ }
+
+ case password: {
+ return value === TestLoginInfo[password];
+ }
+ }
+}
+
+function goToFolderPage() {
+ location.replace('./folder.html');
+}
+
+function putErrorMessageParentsSibling(target, errorMessage) {
+ const grandParent = target.parentElement.parentElement;
+ const ParentSiblings = target.parentElement.parentElement.children;
+
+ const ErrorMessageElement = getErrorMessageElement(ParentSiblings);
+ if (ErrorMessageElement) {
+ ErrorMessageElement.textContent = errorMessage;
+ } else {
+ const errorMessageElement = document.createElement('span');
+ errorMessageElement.textContent = errorMessage;
+ errorMessageElement.classList.add(errorClass);
+ grandParent.append(errorMessageElement);
+ }
+}
+
+function addErrorClassOnInputForm(target) {
+ target.classList.add(errorClass);
+}
+
+function deleteErrorMessageParentsSibling(target) {
+ const ParentSiblings = target.parentElement.parentElement.children;
+ const ErrorMessageElement = getErrorMessageElement(ParentSiblings);
+ ErrorMessageElement?.remove();
+}
+
+function deleteErrorClassOnInputForm(target) {
+ target?.classList.remove(errorClass);
+}
+
+function showIconClickHandler(e) {
+ const { target } = e;
+
+ const showTarget = [...target.parentElement.children].find((element) => element.classList.contains(inputFormInputClass));
+ changeShowType(target, showTarget);
+}
+
+function changeShowType(iconElement, targetElement) {
+ if (targetElement.type === 'password') {
+ targetElement.type = 'text';
+ iconElement.classList.remove(showIconOffClass);
+ } else {
+ targetElement.type = 'password';
+ iconElement.classList.add(showIconOffClass);
+ }
+}
+
+export { signInInputFocusOutCheckHandler, signUpInputFocusOutCheckHandler, testSignInButtonClickCheckHandler, testSignUpButtonClickCheckHandler, testSignUpInputCheckHandler, showIconClickHandler };
\ No newline at end of file
diff --git a/script/Signup.js b/script/Signup.js
new file mode 100644
index 000000000..faf79618d
--- /dev/null
+++ b/script/Signup.js
@@ -0,0 +1,15 @@
+import {signUpInputFocusOutCheckHandler, testSignUpButtonClickCheckHandler, testSignUpInputCheckHandler, showIconClickHandler} from './SignUtility.js';
+
+const inputFormInputs = document.querySelectorAll(`.input-form__input`);
+for(const inputFormInput of inputFormInputs){
+ inputFormInput.addEventListener('focusout', signUpInputFocusOutCheckHandler);
+ inputFormInput.addEventListener('keydown', testSignUpInputCheckHandler);
+}
+
+const showIcons = document.querySelectorAll(`.input-form__show-icon`);
+for(const showIcon of showIcons){
+ showIcon.addEventListener('click', showIconClickHandler);
+}
+
+const loginButton = document.querySelector(`.action-button_signup`);
+loginButton.addEventListener('click', testSignUpButtonClickCheckHandler);
\ No newline at end of file
diff --git a/script/shared.js b/script/shared.js
new file mode 100644
index 000000000..caf4e41a2
--- /dev/null
+++ b/script/shared.js
@@ -0,0 +1,41 @@
+import ENDPOINTS from "../src/config/api";
+
+//TODO header을 react 컴포넌트로 재구성해야함
+fetch(ENDPOINTS.SAMPLE.USER)
+ .then((response) => response.json())
+ .then((result) => {
+ console.log(result);
+ if (result) {
+ const headerButton = document.querySelector(".header .action-button");
+ headerButton.outerHTML = `
+
+ `;
+
+ const headerUserInfo = document.querySelector(".header__user-info");
+ headerUserInfo.style.cssText = `
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ `;
+
+ const headerUserProfile = document.querySelector(".header__user-profile");
+ headerUserProfile.style.cssText = `
+ width: 28px;
+ height: 28px;
+ border-radius: 100%;
+ `;
+
+ const headerUserEmail = document.querySelector(".header__user-email");
+ headerUserEmail.style.cssText = `
+ color: #373740;
+ font-size: 14px;
+ font-weight: 400;
+ `;
+ }
+ })
+ .catch((error) => {
+ console.error(`데이터 가져오는 중 오류 발생\n${error}`);
+ });
diff --git a/shared.css b/shared.css
new file mode 100644
index 000000000..ebf40c74f
--- /dev/null
+++ b/shared.css
@@ -0,0 +1,143 @@
+.action-button {
+ padding: 16px 20px;
+
+ color: #F5F5F5;
+ border-radius: 8px;
+
+ font-size: 18px;
+ font-weight: 600;
+ text-align: center;
+ text-decoration: none;
+}
+
+.action-button_nav_signin {
+ width: 128px;
+}
+
+.action-button_grad_blue-sky {
+ background: linear-gradient(91deg, #6D6AFE 0.12%, #6AE3FE 101.84%);
+}
+
+.footer {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+ padding: 32px 104px 64px;
+ background-color: #111322;
+}
+
+.footer__company-info {
+ font-family: Arial;
+ font-size: 16px;
+ font-weight: 400;
+
+ color: #676767;
+ text-align: center;
+}
+
+.footer__policy-faq {
+ display: flex;
+ align-items: center;
+ gap: 30px;
+
+ font-family: Arial;
+ font-size: 16px;
+ font-weight: 400;
+}
+
+.footer__policy {
+ color: #CFCFCF;
+ text-decoration: none;
+}
+
+.footer__faq {
+ color: #CFCFCF;
+ text-decoration: none;
+}
+
+.footer__sns-icons {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 12px;
+}
+
+.footer__sns-icon {
+ width: 20px;
+ height: 20px;
+ display: block;
+}
+
+
+.header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 20px 200px;
+ position: sticky;
+ top: 0;
+ z-index: 9999;
+ background-color: #F0F6FF;
+}
+
+#main-root{
+ width: 100%;
+
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+#main-root .folder-info{
+ margin: 20px auto 60px;
+}
+
+#main-root .folder-info::before{
+ height:294px;
+ width: 100%;
+
+ position:absolute;
+ top: 0;
+ z-index: -1;
+
+ background-color :#F0F6FF;
+
+ content: "";
+}
+
+#main-root .search-bar{
+ width: min(1066px, calc(100% - 64px));
+
+ margin: 40px 0 0;
+}
+
+#main-root .table-layout_card{
+ margin: 40px 0 100px;
+}
+
+/* Tablet */
+@media all and (max-width:1199px) {
+ .header{
+ padding: 20px max(calc(100% - 999px),32px);
+ }
+}
+
+
+/* Mobile */
+@media all and (min-width:375px) and (max-width:767px) {
+ .footer{
+ position: relative;
+
+ height: 160px;
+ padding: 32px 32px 64px;
+ }
+
+ .footer__company-info{
+ position:absolute;
+ top: 108px;
+ }
+
+ .header{
+ padding: 13px 32px;
+ }
+}
\ No newline at end of file
diff --git a/shared.html b/shared.html
new file mode 100644
index 000000000..434ea7d14
--- /dev/null
+++ b/shared.html
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+ Linkbrary
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/signin.css b/signin.css
new file mode 100644
index 000000000..ae7a35c32
--- /dev/null
+++ b/signin.css
@@ -0,0 +1,179 @@
+.action-button{
+ padding: 16px 20px;
+
+ color: #F5F5F5;
+ border: 0;
+ border-radius: 8px;
+
+ font-size: 18px;
+ font-weight: 600;
+ text-align: center;
+ text-decoration: none;
+}
+
+.action-button_signin{
+ width: 100%;
+}
+
+.action-button_grad_blue-sky{
+ background: linear-gradient(91deg, #6D6AFE 0.12%, #6AE3FE 101.84%);
+}
+
+.body{
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+
+ width: 400px;
+}
+
+.header{
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+
+ gap: 8px;
+}
+
+.header__logo-image{
+ height: 38px;
+}
+
+.html{
+ background-color: #F0F6FF;
+}
+
+.input-form{
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+.input-form__label{
+ font-size: 14px;
+ font-weight: 400;
+}
+.input-form__input{
+ padding: 18px 15px;
+
+ width: inherit;
+ height: 60px;
+
+ border: 1px solid #373740;
+ border-radius: 8px;
+
+ font-size: 16px;
+ font-weight: 400;
+ line-height: 24px;
+}
+.input-form__input_error{
+ border-color: #FF5B56;
+ color: #FF5B56;
+}
+.input-form__input:focus{
+ outline: 0;
+}
+.input-form__input:focus-visible{
+ border: 1px solid #6D6AFE;
+}
+.input-form__input-wrapper{
+ width: 100%;
+ position: relative;
+}
+.input-form__show-icon{
+ width: 16px;
+ height: 16px;
+ position: absolute;
+ right: 10px;
+ top: 50%;
+ transform: translateY(-50%);
+
+ background-image: url(./image/signin/eye-on.svg);
+ background-position: center;
+ background-repeat: no-repeat;
+}
+
+.input-form__show-icon_eye-off{
+ background-image: url(./image/signin/eye-off.svg);
+}
+
+.main{
+ width: 100%;
+}
+
+.page_centered{
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ height: 100%;
+}
+
+.sign__move-page{
+ color: #6D6AFE;
+
+ font-size: 16px;
+ font-weight: 500;
+ line-height: 24px;
+ text-decoration: underline;
+}
+
+.sign-form{
+ display: flex;
+ flex-direction: column;
+ gap: 24px;
+}
+
+.social-signin{
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ padding: 12px 24px;
+
+ background-color: #E7EFFB;
+ border-radius: 8px;
+ border: 1px solid #CCD5E3;
+}
+
+.social-signin__sns-icons{
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 16px;
+}
+
+.social-signin__sns-icon{
+ display: inline-flex;
+
+ width: 42px;
+ height: 42px;
+
+ border-radius: 100%;
+}
+
+.social-signin__sns-icon_img-google{
+ padding: 10px;
+}
+
+.social-signin__sns-icon_img-kakao{
+ padding: 10px 8px 8px;
+
+}
+
+.social-signin__sns-icon_background_google{
+ background-color: #FFFFFF;
+ border: 1px solid #D3D4DD;
+}
+.social-signin__sns-icon_background_kakao{
+ background-color: #F5E14B;
+ }
+
+
+
+/* Mobile */
+@media all and (min-width:375px) and (max-width:767px) {
+ .body{
+ width: min(400px, calc(100% - 64px));
+ }
+}
\ No newline at end of file
diff --git a/signin.html b/signin.html
new file mode 100644
index 000000000..c5877bcce
--- /dev/null
+++ b/signin.html
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+ 로그인
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+

+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/signup.css b/signup.css
new file mode 100644
index 000000000..eb3d1fa1f
--- /dev/null
+++ b/signup.css
@@ -0,0 +1,177 @@
+.action-button{
+ padding: 16px 20px;
+
+ color: #F5F5F5;
+ border: 0;
+ border-radius: 8px;
+
+ font-size: 18px;
+ font-weight: 600;
+ text-align: center;
+ text-decoration: none;
+}
+
+.action-button_signup{
+ width: 100%;
+}
+
+.action-button_grad_blue-sky{
+ background: linear-gradient(91deg, #6D6AFE 0.12%, #6AE3FE 101.84%);
+}
+
+.body{
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+
+ width: 400px;
+}
+
+.header{
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 8px;
+}
+
+.header__logo-image{
+ height: 38px;
+}
+
+.html{
+ background-color: #F0F6FF;
+}
+
+.input-form{
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+.input-form__label{
+ font-size: 14px;
+ font-weight: 400;
+}
+.input-form__input{
+ padding: 18px 15px;
+
+ width: inherit;
+ height: 60px;
+
+ border: 1px solid #373740;
+ border-radius: 8px;
+
+ font-size: 16px;
+ font-weight: 400;
+ line-height: 24px;
+}
+.input-form__input_error{
+ border-color: #FF5B56;
+ color: #FF5B56;
+}
+
+.input-form__input:focus{
+ outline: 0;
+}
+.input-form__input:focus-visible{
+ border: 1px solid #6D6AFE;
+}
+.input-form__input-wrapper{
+ width: 100%;
+ position: relative;
+}
+
+.input-form__show-icon{
+ width: 16px;
+ height: 16px;
+ position: absolute;
+ right: 10px;
+ top: 50%;
+ transform: translateY(-50%);
+
+ background-image: url(./image/signin/eye-on.svg);
+ background-position: center;
+ background-repeat: no-repeat;
+}
+
+.input-form__show-icon_eye-off{
+ background-image: url(./image/signin/eye-off.svg);
+}
+
+.main{
+ width: 100%;
+}
+
+.page_centered{
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ height: 100%;
+}
+
+.sign__move-page{
+ color: #6D6AFE;
+
+ font-size: 16px;
+ font-weight: 500;
+ line-height: 24px;
+ text-decoration: underline;
+}
+
+.sign-form{
+ display: flex;
+ flex-direction: column;
+ gap: 24px;
+}
+
+.social-signup{
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+
+ padding: 12px 24px;
+
+ background-color: #E7EFFB;
+ border-radius: 8px;
+ border: 1px solid #CCD5E3;
+}
+
+.social-signup__sns-icons{
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 16px;
+}
+
+.social-signup__sns-icon{
+ display: inline-flex;
+
+ width: 42px;
+ height: 42px;
+
+ border-radius: 100%;
+}
+
+.social-signup__sns-icon_img-google{
+ padding: 10px;
+}
+
+.social-signup__sns-icon_img-kakao{
+ padding: 10px 8px 8px;
+}
+
+.social-signup__sns-icon_background_google{
+ background-color: #FFFFFF;
+ border: 1px solid #D3D4DD;
+}
+.social-signup__sns-icon_background_kakao{
+ background-color: #F5E14B;
+}
+
+/* Mobile */
+@media all and (min-width:375px) and (max-width:767px) {
+ .body{
+ width: min(400px, calc(100% - 64px));
+ }
+}
\ No newline at end of file
diff --git a/signup.html b/signup.html
new file mode 100644
index 000000000..d6da0c0c4
--- /dev/null
+++ b/signup.html
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+ 로그인
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+

+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/commons/Card.css b/src/components/commons/Card.css
new file mode 100644
index 000000000..cc94e1fff
--- /dev/null
+++ b/src/components/commons/Card.css
@@ -0,0 +1,108 @@
+.card{
+ width: 340px;
+ height: 334px;
+
+ border-radius: 15px;
+ box-shadow: 0px 5px 25px 0px rgba(0, 0, 0, 0.08);
+
+ overflow: hidden;
+
+ cursor: pointer;
+
+ box-sizing: content-box;
+}
+
+.card:hover{
+ border: 2px solid #6D6AFE;
+ box-shadow: 0px 5px 40px 0px rgba(0, 0, 0, 0.16);
+}
+
+.card:hover .card__image{
+ animation: bigger 0.5s forwards;
+}
+
+.card__content{
+ height: 49px;
+
+ display: -webkit-box;
+
+ color: #000;
+
+ font-size: 16px;
+ font-weight: 400;
+ line-height: 24px;
+
+ overflow: hidden;
+ text-overflow: ellipsis;
+ word-break: break-all;
+
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+}
+
+.card__created-at{
+ color: #333;
+
+ font-size: 14px;
+ font-weight: 400;
+
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.card__created-before{
+ color: #666;
+
+ font-size: 13px;
+ font-weight: 400;
+}
+
+.card__image{
+ min-width: 100%;
+ min-height: 100%;
+ object-fit: cover;
+ overflow: hidden;
+}
+
+.card__image_no-image{
+ width: 133px;
+
+ min-width: unset;
+ min-height: unset;
+}
+
+.card__image-container{
+ height: 199px;
+
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ overflow: hidden;
+}
+
+.card__image-container_no-image{
+ background-color: #DDDFFF;
+}
+
+.card__info{
+ height: 135px;
+ padding: 15px;
+
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+}
+
+
+
+
+@keyframes bigger {
+ from {
+ transform: scale(1);
+ }
+ to {
+ transform: scale(1.3);
+ }
+}
\ No newline at end of file
diff --git a/src/components/commons/Card.jsx b/src/components/commons/Card.jsx
new file mode 100644
index 000000000..18e4f7c6c
--- /dev/null
+++ b/src/components/commons/Card.jsx
@@ -0,0 +1,88 @@
+import React from "react";
+import classNames from "classnames";
+import "./Card.css";
+import { openLinkOnNewTab } from "../../utility/linkUtil";
+import { toKRDateString } from "../../utility/timeUtil";
+
+function Card({ classNameList = [], data }) {
+ const { id, createdAt, url, title, description, imageSource } = data;
+
+ return (
+ openLinkOnNewTab(url)}
+ >
+
+
+
+ );
+}
+
+function CardImage({ src, title }) {
+ return (
+ <>
+ {src ? (
+
+

+
+ ) : (
+
+

+
+ )}
+ >
+ );
+}
+
+function CardInfo({ content, createdAt }) {
+ return (
+
+
{formatCreatedBefore(createdAt)}
+
{content}
+
{formatCreatedAt(createdAt)}
+
+ );
+}
+
+function formatCreatedAt(createdAt) {
+ const date = new Date(createdAt);
+
+ return toKRDateString(date);
+}
+
+function formatCreatedBefore(createdAt) {
+ const date = new Date(createdAt);
+ const now = new Date();
+ const diff = now - date;
+
+ const minutes = Math.floor(diff / 60000);
+ const hours = Math.floor(diff / 3600000);
+ const days = Math.floor(diff / 86400000);
+ const months = Math.floor(diff / 2592000000);
+ const years = Math.floor(diff / 31536000000);
+
+ if (years) {
+ if (years === 1) return `${years} year ago`;
+ else return `${years} years ago`;
+ } else if (months) {
+ if (months === 1) return `${months} month ago`;
+ else return `${months} months ago`;
+ } else if (days) {
+ if (days === 1) return `${days} day ago`;
+ else return `${days} days ago`;
+ } else if (hours) {
+ if (hours === 1) return `${hours} hour ago`;
+ else return `${hours} hours ago`;
+ } else if (minutes) {
+ if (minutes === 1) return `${minutes} minute ago`;
+ else return `${minutes} minutes ago`;
+ } else {
+ return `1 minute ago`;
+ }
+}
+
+export default Card;
diff --git a/src/components/commons/CardFactory.jsx b/src/components/commons/CardFactory.jsx
new file mode 100644
index 000000000..c6671759b
--- /dev/null
+++ b/src/components/commons/CardFactory.jsx
@@ -0,0 +1,16 @@
+import React from "react";
+import Card from "./Card";
+
+const classNames = [`card`];
+
+function CardFactory({ dataList }) {
+ return (
+ <>
+ {dataList?.map((item) => (
+
+ ))}
+ >
+ );
+}
+
+export default CardFactory;
diff --git a/src/components/commons/SearchBar.css b/src/components/commons/SearchBar.css
new file mode 100644
index 000000000..bb522ed14
--- /dev/null
+++ b/src/components/commons/SearchBar.css
@@ -0,0 +1,27 @@
+.search-bar{
+ width: min(1066px, 100%);
+
+ padding: 15px;
+
+ display: flex;
+ align-items: center;
+ gap: 10px;
+
+ background-color: #f5f5f5;
+ border-radius: 10px;
+}
+
+.search-bar__input{
+ width: 100%;
+
+ background-color:unset;
+ border: none;
+
+ color: #666;
+ font-size: 16px;
+ font-weight: 400;
+}
+
+.search-bar__input:focus{
+ outline: none;
+}
\ No newline at end of file
diff --git a/src/components/commons/SearchBar.jsx b/src/components/commons/SearchBar.jsx
new file mode 100644
index 000000000..f59441976
--- /dev/null
+++ b/src/components/commons/SearchBar.jsx
@@ -0,0 +1,16 @@
+import React from 'react';
+
+import SearchIcon from '../../../image/search/Search.svg'
+
+import './SearchBar.css';
+
+function SearchBar() {
+ return (
+
+ );
+}
+
+export default SearchBar;
diff --git a/src/components/layouts/TableLayout.css b/src/components/layouts/TableLayout.css
new file mode 100644
index 000000000..7b25a3759
--- /dev/null
+++ b/src/components/layouts/TableLayout.css
@@ -0,0 +1,24 @@
+.table-layout{
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr;
+}
+
+.table-layout_card{
+ width: fit-content;
+ height: fit-content;
+
+ gap: 25px 20px;
+}
+
+@media screen and (max-width: 1123px){
+ .table-layout{
+ grid-template-columns: 1fr 1fr;
+ }
+}
+
+@media screen and (max-width: 767px){
+ .table-layout{
+ grid-template-columns: 1fr;
+ }
+
+}
\ No newline at end of file
diff --git a/src/components/layouts/TableLayout.jsx b/src/components/layouts/TableLayout.jsx
new file mode 100644
index 000000000..351987140
--- /dev/null
+++ b/src/components/layouts/TableLayout.jsx
@@ -0,0 +1,14 @@
+import React from 'react';
+import classNames from 'classnames';
+
+import './TableLayout.css';
+
+function TableLayout({ children, classNameList = [] }) {
+ return (
+
+ {children}
+
+ );
+}
+
+export default TableLayout;
diff --git a/src/components/shared-screen/FolderInfo.css b/src/components/shared-screen/FolderInfo.css
new file mode 100644
index 000000000..469c2dfa6
--- /dev/null
+++ b/src/components/shared-screen/FolderInfo.css
@@ -0,0 +1,31 @@
+.folder-info {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 20px;
+}
+
+.folder-info__profile {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+}
+
+.folder-info__profile-image {
+ width: 60px;
+ height: 60px;
+
+ border-radius: 100%;
+}
+
+.folder-info__profile-name{
+ color: var(--text-color-light-mode, #000);
+ font-size: 16px;
+ font-weight: 400;
+ line-height: 24px;
+}
+
+.folder-info__title{
+ font-size: 40px;
+ font-weight: 600;
+}
\ No newline at end of file
diff --git a/src/components/shared-screen/FolderInfo.jsx b/src/components/shared-screen/FolderInfo.jsx
new file mode 100644
index 000000000..8a943cb95
--- /dev/null
+++ b/src/components/shared-screen/FolderInfo.jsx
@@ -0,0 +1,41 @@
+import React from "react";
+
+import "./FolderInfo.css";
+
+function FolderInfo({ dataList }) {
+ return (
+ <>
+
+
+
+
+ >
+ );
+}
+
+function FolderProfile({ profileImageSource, profileName }) {
+ return (
+
+

+
+ {`@${profileName ?? ""}`}
+
+
+ );
+}
+
+function FolderTitle({folderName}){
+ return(
+ {folderName}
+ )
+}
+export default FolderInfo;
diff --git a/src/components/shared-screen/SharedMainScreen.jsx b/src/components/shared-screen/SharedMainScreen.jsx
new file mode 100644
index 000000000..0fcabd8a2
--- /dev/null
+++ b/src/components/shared-screen/SharedMainScreen.jsx
@@ -0,0 +1,49 @@
+import React, { useEffect, useState } from "react";
+import ReactDOM from "react-dom/client";
+
+import ENDPOINTS from "../../config/api";
+
+import CardFactory from "../commons/CardFactory";
+import FolderInfo from "./FolderInfo";
+import SearchBar from "../commons/SearchBar";
+import TableLayout from "../layouts/TableLayout";
+
+const root = ReactDOM.createRoot(document.getElementById("main-root"));
+root.render();
+
+function SharedMainScreen() {
+ const [folderData, setFolderData] = useState({});
+ const [linkData, setLinkData] = useState([]);
+
+ useEffect(() => {
+ fetch(ENDPOINTS.SAMPLE.FOLDER)
+ .then((response) => response.json())
+ .then((result) => {
+ return result.folder;
+ })
+ .then((folder) => {
+ setFolderData({
+ id: folder.id,
+ name: folder.name,
+ owner: folder.owner,
+ });
+ return folder.links;
+ })
+ .then((links) => {
+ setLinkData(links);
+ })
+ .catch((error) => {
+ console.error(`데이터 가져오는 중 오류 발생\n${error}`);
+ });
+ }, []);
+
+ return (
+ <>
+
+
+
+
+
+ >
+ );
+}
diff --git a/src/config/api.js b/src/config/api.js
new file mode 100644
index 000000000..898ab77ba
--- /dev/null
+++ b/src/config/api.js
@@ -0,0 +1,10 @@
+const API_BASE_URL = "https://bootcamp-api.codeit.kr/api";
+
+const ENDPOINTS = {
+ SAMPLE: {
+ FOLDER: `${API_BASE_URL}/sample/folder`,
+ USER: `${API_BASE_URL}/sample/user`,
+ }
+};
+
+export default ENDPOINTS;
\ No newline at end of file
diff --git a/src/utility/linkUtil.js b/src/utility/linkUtil.js
new file mode 100644
index 000000000..ff3d83d2d
--- /dev/null
+++ b/src/utility/linkUtil.js
@@ -0,0 +1,5 @@
+function openLinkOnNewTab(url) {
+ window.open(url, '_blank');
+}
+
+export { openLinkOnNewTab}
\ No newline at end of file
diff --git a/src/utility/timeUtil.js b/src/utility/timeUtil.js
new file mode 100644
index 000000000..c03bd8c99
--- /dev/null
+++ b/src/utility/timeUtil.js
@@ -0,0 +1,3 @@
+export function toKRDateString(date){
+ return date.toLocaleDateString("ko-KR").slice(0, -1);
+}
\ No newline at end of file
diff --git a/utility.css b/utility.css
new file mode 100644
index 000000000..ecb9729b6
--- /dev/null
+++ b/utility.css
@@ -0,0 +1,12 @@
+.centered{
+ margin: 0 auto;
+}
+
+.mh_30px{
+ margin-top: 30px;
+ margin-bottom: 30px;
+}
+
+.mt_32px{
+ margin-top: 32px;
+}
\ No newline at end of file
diff --git a/vite.config.js b/vite.config.js
new file mode 100644
index 000000000..1a2b773ef
--- /dev/null
+++ b/vite.config.js
@@ -0,0 +1,11 @@
+// vite.config.js
+/**
+ * Vite의 구성 옵션을 정의하는 곳입니다.
+ * React를 사용하는 경우 JSX를 처리하기 위한 플러그인을 설정할 수 있습니다.
+ */
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+
+export default defineConfig({
+ plugins: [react()]
+});