diff --git a/.storybook/main.ts b/.storybook/main.ts index a567f71..9908be4 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -23,5 +23,28 @@ const config: StorybookConfig = { name: '@storybook/nextjs', options: {}, }, + webpackFinal: async (config) => { + const imageRule = config.module?.rules?.find((rule) => { + const test = (rule as { test: RegExp }).test; + + if (!test) { + return false; + } + if (Array.isArray(test)) { + return test.some((t) => t instanceof RegExp && t.test('.svg')); + } + + return test instanceof RegExp && test.test('.svg'); + }) as { [key: string]: any }; + + imageRule.exclude = /\.svg$/; + + config.module?.rules?.push({ + test: /\.svg$/, + use: ['@svgr/webpack'], + }); + + return config; + }, }; export default config; diff --git a/app/page.tsx b/app/page.tsx index 046a7d3..6e67fa7 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,39 +1,50 @@ +import IconArrowFront from '/public/assets/icon/arrow-front.svg'; + +import { PageContainer } from '@/widgets/pageContainer/ui/PageContainer'; export default function Home() { return ( -
-
-

White

-

Gray 01

-

Gray 02

-

Gray 03

-

Gray 04

-

Gray 05

-

Gray 06

-

Gray 07

-
+ , + center:
메인페이지
, + right: , + }} + > +
+
+

White

+

Gray 01

+

Gray 02

+

Gray 03

+

Gray 04

+

Gray 05

+

Gray 06

+

Gray 07

+
-
-

Red 01

-

Red 02

-

Red 03

+
+

Red 01

+

Red 02

+

Red 03

-
+
-

Yellow 01

-

Yellow 02

-
+

Yellow 01

+

Yellow 02

+
-
-

Ashblue 01

-

Ashblue 02

-

Overlay

+
+

Ashblue 01

+

Ashblue 02

+

Overlay

-
+
-

Mint 01

-

Mint 02

-

Mint 03

+

Mint 01

+

Mint 02

+

Mint 03

+
-
+ ); } diff --git a/global.d.ts b/global.d.ts new file mode 100644 index 0000000..006534e --- /dev/null +++ b/global.d.ts @@ -0,0 +1,4 @@ +declare module '*.svg' { + const content: React.FunctionComponent>; + export default content; +} diff --git a/next.config.mjs b/next.config.mjs index 4678774..dde8ea3 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,4 +1,12 @@ /** @type {import('next').NextConfig} */ -const nextConfig = {}; +const nextConfig = { + webpack: (config) => { + config.module.rules.push({ + test: /\.svg$/, + use: ["@svgr/webpack"], + }); + return config; + }, +}; export default nextConfig; diff --git a/package.json b/package.json index 2421aec..72baeb4 100644 --- a/package.json +++ b/package.json @@ -23,9 +23,7 @@ }, "devDependencies": { "@chromatic-com/storybook": "^1.9.0", - "@eslint/js": "^9.12.0", - "@tanstack/eslint-plugin-query": "^5.59.7", - "@tanstack/react-query-devtools": "^5.59.4", + "@eslint/js": "^9.12.0", "@storybook/addon-a11y": "^8.3.5", "@storybook/addon-designs": "^8.0.3", "@storybook/addon-essentials": "^8.3.5", @@ -38,6 +36,9 @@ "@storybook/nextjs": "^8.3.5", "@storybook/react": "^8.3.5", "@storybook/test": "^8.3.5", + "@svgr/webpack": "^8.1.0", + "@tanstack/eslint-plugin-query": "^5.59.7", + "@tanstack/react-query-devtools": "^5.59.4", "@testing-library/react": "^16.0.1", "@types/node": "^20", "@types/react": "^18", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6e6bac5..ccb6326 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,13 +32,7 @@ importers: version: 1.9.0(react@18.3.1) '@eslint/js': specifier: ^9.12.0 - version: 9.12.0 - '@tanstack/eslint-plugin-query': - specifier: ^5.59.7 - version: 5.59.7(eslint@8.57.0)(typescript@5.6.3) - '@tanstack/react-query-devtools': - specifier: ^5.59.4 - version: 5.59.13(@tanstack/react-query@5.59.13(react@18.3.1))(react@18.3.1) + version: 9.12.0 '@storybook/addon-a11y': specifier: ^8.3.5 version: 8.3.5(storybook@8.3.5) @@ -75,6 +69,15 @@ importers: '@storybook/test': specifier: ^8.3.5 version: 8.3.5(storybook@8.3.5) + '@svgr/webpack': + specifier: ^8.1.0 + version: 8.1.0(typescript@5.6.3) + '@tanstack/eslint-plugin-query': + specifier: ^5.59.7 + version: 5.59.7(eslint@8.57.0)(typescript@5.6.3) + '@tanstack/react-query-devtools': + specifier: ^5.59.4 + version: 5.59.13(@tanstack/react-query@5.59.13(react@18.3.1))(react@18.3.1) '@testing-library/react': specifier: ^16.0.1 version: 16.0.1(@testing-library/dom@10.4.0)(@types/react-dom@18.3.1)(@types/react@18.3.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -581,6 +584,12 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/plugin-transform-react-constant-elements@7.25.7': + resolution: {integrity: sha512-/qXt69Em8HgsjCLu7G3zdIQn7A2QwmYND7Wa0LTp09Na+Zn8L5d0A7wSXrKi18TJRc/Q5S1i1De/SU1LzVkSvA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/plugin-transform-react-display-name@7.25.7': resolution: {integrity: sha512-r0QY7NVU8OnrwE+w2IWiRom0wwsTbjx4+xH2RTd7AVdof3uurXOF+/mXHQDRk+2jIvWgSaCHKMgggfvM4dyUGA==} engines: {node: '>=6.9.0'} @@ -1688,6 +1697,84 @@ packages: peerDependencies: storybook: ^8.3.5 + '@svgr/babel-plugin-add-jsx-attribute@8.0.0': + resolution: {integrity: sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-remove-jsx-attribute@8.0.0': + resolution: {integrity: sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0': + resolution: {integrity: sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0': + resolution: {integrity: sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-svg-dynamic-title@8.0.0': + resolution: {integrity: sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-svg-em-dimensions@8.0.0': + resolution: {integrity: sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-transform-react-native-svg@8.1.0': + resolution: {integrity: sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-plugin-transform-svg-component@8.0.0': + resolution: {integrity: sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==} + engines: {node: '>=12'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/babel-preset@8.1.0': + resolution: {integrity: sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==} + engines: {node: '>=14'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@svgr/core@8.1.0': + resolution: {integrity: sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==} + engines: {node: '>=14'} + + '@svgr/hast-util-to-babel-ast@8.0.0': + resolution: {integrity: sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==} + engines: {node: '>=14'} + + '@svgr/plugin-jsx@8.1.0': + resolution: {integrity: sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==} + engines: {node: '>=14'} + peerDependencies: + '@svgr/core': '*' + + '@svgr/plugin-svgo@8.1.0': + resolution: {integrity: sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==} + engines: {node: '>=14'} + peerDependencies: + '@svgr/core': '*' + + '@svgr/webpack@8.1.0': + resolution: {integrity: sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==} + engines: {node: '>=14'} + '@swc/counter@0.1.3': resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} @@ -1745,6 +1832,10 @@ packages: peerDependencies: '@testing-library/dom': '>=7.21.4' + '@trysound/sax@0.2.0': + resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} + engines: {node: '>=10.13.0'} + '@types/aria-query@5.0.4': resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} @@ -2386,6 +2477,10 @@ packages: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + caniuse-lite@1.0.30001668: resolution: {integrity: sha512-nWLrdxqCdblixUO+27JtGJJE/txpJlyUy5YN1u53wLZkP0emYCo5zgS6QYft7VUYR42LGgi/S5hdLZTrnyIddw==} @@ -2504,6 +2599,10 @@ packages: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + commander@8.3.0: resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} engines: {node: '>= 12'} @@ -2561,6 +2660,15 @@ packages: resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} engines: {node: '>=10'} + cosmiconfig@8.3.6: + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + cosmiconfig@9.0.0: resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} engines: {node: '>=14'} @@ -2601,6 +2709,17 @@ packages: css-select@4.3.0: resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + css-select@5.1.0: + resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} + + css-tree@2.2.1: + resolution: {integrity: sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + + css-tree@2.3.1: + resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + css-what@6.1.0: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} @@ -2613,6 +2732,10 @@ packages: engines: {node: '>=4'} hasBin: true + csso@5.0.5: + resolution: {integrity: sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0, npm: '>=7.0.0'} + cssstyle@4.1.0: resolution: {integrity: sha512-h66W1URKpBS5YMI/V8PyXvTMFT8SupJ1IzoIV8IeBC/ji8WVmrO8dGlTi+2dh6whmdk6BiKJLD/ZBkhWbcg6nA==} engines: {node: '>=18'} @@ -2753,6 +2876,9 @@ packages: dom-serializer@1.4.1: resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + dom-serializer@2.0.0: + resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} + domain-browser@4.23.0: resolution: {integrity: sha512-ArzcM/II1wCCujdCNyQjXrAFwS4mrLh4C7DZWlaI8mdh7h3BfKdNd3bKXITfl2PT9FtfQqaGvhi1vPRQPimjGA==} engines: {node: '>=10'} @@ -2764,9 +2890,16 @@ packages: resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} engines: {node: '>= 4'} + domhandler@5.0.3: + resolution: {integrity: sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==} + engines: {node: '>= 4'} + domutils@2.8.0: resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + domutils@3.1.0: + resolution: {integrity: sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==} + dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} @@ -3812,6 +3945,12 @@ packages: md5.js@1.3.5: resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + mdn-data@2.0.28: + resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} + + mdn-data@2.0.30: + resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==} + media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} @@ -4672,6 +4811,9 @@ packages: resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} engines: {node: '>=18'} + snake-case@3.0.4: + resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -4848,6 +4990,14 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + svg-parser@2.0.4: + resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} + + svgo@3.3.2: + resolution: {integrity: sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==} + engines: {node: '>=14.0.0'} + hasBin: true + symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} @@ -5905,6 +6055,11 @@ snapshots: '@babel/core': 7.25.8 '@babel/helper-plugin-utils': 7.25.7 + '@babel/plugin-transform-react-constant-elements@7.25.7(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@babel/helper-plugin-utils': 7.25.7 + '@babel/plugin-transform-react-display-name@7.25.7(@babel/core@7.25.8)': dependencies: '@babel/core': 7.25.8 @@ -7096,6 +7251,99 @@ snapshots: dependencies: storybook: 8.3.5 + '@svgr/babel-plugin-add-jsx-attribute@8.0.0(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + + '@svgr/babel-plugin-remove-jsx-attribute@8.0.0(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + + '@svgr/babel-plugin-remove-jsx-empty-expression@8.0.0(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + + '@svgr/babel-plugin-replace-jsx-attribute-value@8.0.0(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + + '@svgr/babel-plugin-svg-dynamic-title@8.0.0(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + + '@svgr/babel-plugin-svg-em-dimensions@8.0.0(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + + '@svgr/babel-plugin-transform-react-native-svg@8.1.0(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + + '@svgr/babel-plugin-transform-svg-component@8.0.0(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + + '@svgr/babel-preset@8.1.0(@babel/core@7.25.8)': + dependencies: + '@babel/core': 7.25.8 + '@svgr/babel-plugin-add-jsx-attribute': 8.0.0(@babel/core@7.25.8) + '@svgr/babel-plugin-remove-jsx-attribute': 8.0.0(@babel/core@7.25.8) + '@svgr/babel-plugin-remove-jsx-empty-expression': 8.0.0(@babel/core@7.25.8) + '@svgr/babel-plugin-replace-jsx-attribute-value': 8.0.0(@babel/core@7.25.8) + '@svgr/babel-plugin-svg-dynamic-title': 8.0.0(@babel/core@7.25.8) + '@svgr/babel-plugin-svg-em-dimensions': 8.0.0(@babel/core@7.25.8) + '@svgr/babel-plugin-transform-react-native-svg': 8.1.0(@babel/core@7.25.8) + '@svgr/babel-plugin-transform-svg-component': 8.0.0(@babel/core@7.25.8) + + '@svgr/core@8.1.0(typescript@5.6.3)': + dependencies: + '@babel/core': 7.25.8 + '@svgr/babel-preset': 8.1.0(@babel/core@7.25.8) + camelcase: 6.3.0 + cosmiconfig: 8.3.6(typescript@5.6.3) + snake-case: 3.0.4 + transitivePeerDependencies: + - supports-color + - typescript + + '@svgr/hast-util-to-babel-ast@8.0.0': + dependencies: + '@babel/types': 7.25.8 + entities: 4.5.0 + + '@svgr/plugin-jsx@8.1.0(@svgr/core@8.1.0(typescript@5.6.3))': + dependencies: + '@babel/core': 7.25.8 + '@svgr/babel-preset': 8.1.0(@babel/core@7.25.8) + '@svgr/core': 8.1.0(typescript@5.6.3) + '@svgr/hast-util-to-babel-ast': 8.0.0 + svg-parser: 2.0.4 + transitivePeerDependencies: + - supports-color + + '@svgr/plugin-svgo@8.1.0(@svgr/core@8.1.0(typescript@5.6.3))(typescript@5.6.3)': + dependencies: + '@svgr/core': 8.1.0(typescript@5.6.3) + cosmiconfig: 8.3.6(typescript@5.6.3) + deepmerge: 4.3.1 + svgo: 3.3.2 + transitivePeerDependencies: + - typescript + + '@svgr/webpack@8.1.0(typescript@5.6.3)': + dependencies: + '@babel/core': 7.25.8 + '@babel/plugin-transform-react-constant-elements': 7.25.7(@babel/core@7.25.8) + '@babel/preset-env': 7.25.8(@babel/core@7.25.8) + '@babel/preset-react': 7.25.7(@babel/core@7.25.8) + '@babel/preset-typescript': 7.25.7(@babel/core@7.25.8) + '@svgr/core': 8.1.0(typescript@5.6.3) + '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@5.6.3)) + '@svgr/plugin-svgo': 8.1.0(@svgr/core@8.1.0(typescript@5.6.3))(typescript@5.6.3) + transitivePeerDependencies: + - supports-color + - typescript + '@swc/counter@0.1.3': {} '@swc/helpers@0.5.5': @@ -7161,6 +7409,8 @@ snapshots: dependencies: '@testing-library/dom': 10.4.0 + '@trysound/sax@0.2.0': {} + '@types/aria-query@5.0.4': {} '@types/babel__core@7.20.5': @@ -7955,6 +8205,8 @@ snapshots: camelcase-css@2.0.1: {} + camelcase@6.3.0: {} + caniuse-lite@1.0.30001668: {} case-sensitive-paths-webpack-plugin@2.4.0: {} @@ -8069,6 +8321,8 @@ snapshots: commander@4.1.1: {} + commander@7.2.0: {} + commander@8.3.0: {} common-path-prefix@3.0.0: {} @@ -8113,6 +8367,15 @@ snapshots: path-type: 4.0.0 yaml: 1.10.2 + cosmiconfig@8.3.6(typescript@5.6.3): + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + optionalDependencies: + typescript: 5.6.3 + cosmiconfig@9.0.0(typescript@5.6.3): dependencies: env-paths: 2.2.1 @@ -8185,12 +8448,34 @@ snapshots: domutils: 2.8.0 nth-check: 2.1.1 + css-select@5.1.0: + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 5.0.3 + domutils: 3.1.0 + nth-check: 2.1.1 + + css-tree@2.2.1: + dependencies: + mdn-data: 2.0.28 + source-map-js: 1.2.1 + + css-tree@2.3.1: + dependencies: + mdn-data: 2.0.30 + source-map-js: 1.2.1 + css-what@6.1.0: {} css.escape@1.5.1: {} cssesc@3.0.0: {} + csso@5.0.5: + dependencies: + css-tree: 2.2.1 + cssstyle@4.1.0: dependencies: rrweb-cssom: 0.7.1 @@ -8331,6 +8616,12 @@ snapshots: domhandler: 4.3.1 entities: 2.2.0 + dom-serializer@2.0.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 5.0.3 + entities: 4.5.0 + domain-browser@4.23.0: {} domelementtype@2.3.0: {} @@ -8339,12 +8630,22 @@ snapshots: dependencies: domelementtype: 2.3.0 + domhandler@5.0.3: + dependencies: + domelementtype: 2.3.0 + domutils@2.8.0: dependencies: dom-serializer: 1.4.1 domelementtype: 2.3.0 domhandler: 4.3.1 + domutils@3.1.0: + dependencies: + dom-serializer: 2.0.0 + domelementtype: 2.3.0 + domhandler: 5.0.3 + dot-case@3.0.4: dependencies: no-case: 3.0.4 @@ -9663,6 +9964,10 @@ snapshots: inherits: 2.0.4 safe-buffer: 5.2.1 + mdn-data@2.0.28: {} + + mdn-data@2.0.30: {} + media-typer@0.3.0: {} memfs@3.5.3: @@ -10627,6 +10932,11 @@ snapshots: ansi-styles: 6.2.1 is-fullwidth-code-point: 5.0.0 + snake-case@3.0.4: + dependencies: + dot-case: 3.0.4 + tslib: 2.7.0 + source-map-js@1.2.1: {} source-map-support@0.5.21: @@ -10812,6 +11122,18 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + svg-parser@2.0.4: {} + + svgo@3.3.2: + dependencies: + '@trysound/sax': 0.2.0 + commander: 7.2.0 + css-select: 5.1.0 + css-tree: 2.3.1 + css-what: 6.1.0 + csso: 5.0.5 + picocolors: 1.1.0 + symbol-tree@3.2.4: {} tailwindcss@3.4.13: diff --git a/public/assets/icon/arrow-down-small.svg b/public/assets/icon/arrow-down-small.svg new file mode 100644 index 0000000..e23586e --- /dev/null +++ b/public/assets/icon/arrow-down-small.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/assets/icon/arrow-front.svg b/public/assets/icon/arrow-front.svg new file mode 100644 index 0000000..da93876 --- /dev/null +++ b/public/assets/icon/arrow-front.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/shared/ui/dropdown/index.ts b/src/shared/ui/dropdown/index.ts new file mode 100644 index 0000000..5ecdd1f --- /dev/null +++ b/src/shared/ui/dropdown/index.ts @@ -0,0 +1 @@ +export * from './ui'; diff --git a/src/shared/ui/dropdown/ui/Dropdown.stories.tsx b/src/shared/ui/dropdown/ui/Dropdown.stories.tsx new file mode 100644 index 0000000..0889cbe --- /dev/null +++ b/src/shared/ui/dropdown/ui/Dropdown.stories.tsx @@ -0,0 +1,49 @@ +import { useState } from 'react'; + +import { Meta, StoryObj } from '@storybook/react'; + +import { Dropdown } from '.'; + +import type { IOption } from '.'; + +import ArrowDownSmall from '/public/assets/icon/arrow-down-small.svg'; + +const options: IOption[] = [ + { title: 'Option 1', itemTitle: 'Item 1' }, + { title: 'Option 2', itemTitle: 'Item 2' }, + { title: 'Option 3', itemTitle: 'Item 3' }, +]; + +type Story = StoryObj; + +export default { + title: 'Dropdown', + component: Dropdown, + parameters: { layout: 'centered' }, + tags: ['autodocs'], + args: { + options, + children: , + menuPositionClass: 'top-[40px] left-1/2 -translate-x-1/2', + selectOption: (index: number) => { + console.log(index); + }, + }, +} satisfies Meta; + +export const Default: Story = { + render: (args) => { + const [selectedOptionIndex, setSelectedOptionIndex] = useState(0); + const selectOption = (index: number) => { + setSelectedOptionIndex(index); + }; + return ( + + {args.options[selectedOptionIndex]?.itemTitle} +
+ +
+
+ ); + }, +}; diff --git a/src/shared/ui/dropdown/ui/Dropdown.tsx b/src/shared/ui/dropdown/ui/Dropdown.tsx new file mode 100644 index 0000000..91aae97 --- /dev/null +++ b/src/shared/ui/dropdown/ui/Dropdown.tsx @@ -0,0 +1,54 @@ +'use client'; +import { PropsWithChildren, useState } from 'react'; + +export interface IDropdown { + options: Array; + menuPositionClass: string; + selectOption: (index: number) => void; +} + +export interface IOption { + title: string; + itemTitle: string; +} + +export function Dropdown({ + options, + menuPositionClass, + selectOption, + children, +}: PropsWithChildren) { + const [isOpen, setIsOpen] = useState(false); + + const clickToggle = () => { + setIsOpen((prev) => !prev); + }; + + const clickOption = (index: number) => { + setIsOpen(false); + selectOption(index); + }; + + return ( +
+ + {isOpen && ( +
+ {options.map((option, index) => ( + + ))} +
+ )} +
+ ); +} diff --git a/src/shared/ui/dropdown/ui/index.ts b/src/shared/ui/dropdown/ui/index.ts new file mode 100644 index 0000000..2f29bad --- /dev/null +++ b/src/shared/ui/dropdown/ui/index.ts @@ -0,0 +1 @@ +export * from './Dropdown'; diff --git a/src/shared/ui/header/index.ts b/src/shared/ui/header/index.ts new file mode 100644 index 0000000..5ecdd1f --- /dev/null +++ b/src/shared/ui/header/index.ts @@ -0,0 +1 @@ +export * from './ui'; diff --git a/src/shared/ui/header/ui/Header.tsx b/src/shared/ui/header/ui/Header.tsx new file mode 100644 index 0000000..0f4d7ab --- /dev/null +++ b/src/shared/ui/header/ui/Header.tsx @@ -0,0 +1,15 @@ +export interface IHeader { + left: JSX.Element; + center?: JSX.Element; + right?: JSX.Element; +} + +export function Header({ left, center, right }: IHeader) { + return ( +
+ {left} + {center} + {right} +
+ ); +} diff --git a/src/shared/ui/header/ui/index.ts b/src/shared/ui/header/ui/index.ts new file mode 100644 index 0000000..266dec8 --- /dev/null +++ b/src/shared/ui/header/ui/index.ts @@ -0,0 +1 @@ +export * from './Header'; diff --git a/src/shared/ui/index.ts b/src/shared/ui/index.ts index 4f081a0..0ad19f3 100644 --- a/src/shared/ui/index.ts +++ b/src/shared/ui/index.ts @@ -1,2 +1,4 @@ +export * from './dropdown'; +export * from './header'; export * from './button'; export * from './modal-wrapper'; diff --git a/src/widgets/pageContainer/index.ts b/src/widgets/pageContainer/index.ts new file mode 100644 index 0000000..5ecdd1f --- /dev/null +++ b/src/widgets/pageContainer/index.ts @@ -0,0 +1 @@ +export * from './ui'; diff --git a/src/widgets/pageContainer/ui/PageContainer.tsx b/src/widgets/pageContainer/ui/PageContainer.tsx new file mode 100644 index 0000000..30d43bb --- /dev/null +++ b/src/widgets/pageContainer/ui/PageContainer.tsx @@ -0,0 +1,21 @@ +import { PropsWithChildren } from 'react'; + +import { Header } from '@/shared/ui'; +import type { IHeader } from '@/shared/ui'; + +export interface IPageContainer { + headerProps: IHeader; + hasHeader?: boolean; +} +export function PageContainer({ + headerProps, + hasHeader = true, + children, +}: PropsWithChildren) { + return ( +
+ {hasHeader &&
} +
{children}
+
+ ); +} diff --git a/src/widgets/pageContainer/ui/index.ts b/src/widgets/pageContainer/ui/index.ts new file mode 100644 index 0000000..7a798df --- /dev/null +++ b/src/widgets/pageContainer/ui/index.ts @@ -0,0 +1 @@ +export * from './PageContainer'; diff --git a/tailwind.config.ts b/tailwind.config.ts index 4081835..dcb82b9 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -13,6 +13,7 @@ const config: Config = { content: [ './app/**/*.{ts,tsx}', './src/pages/**/*.{ts,tsx}', + './src/shared/**/*.{ts,tsx}', './src/features/**/*.{ts,tsx}', './src/widgets/**/*.{ts,tsx}', './src/shared/**/*.{ts,tsx}', diff --git a/tsconfig.json b/tsconfig.json index 7b28589..9d5fb99 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,9 +18,10 @@ } ], "paths": { - "@/*": ["./src/*"] + "@/*": ["./src/*"], + "/public/*" : ["./public/*"] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "include": ["global.d.ts", "next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], "exclude": ["node_modules"] } diff --git a/vite.config.ts b/vite.config.ts index d23fced..2d621c7 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,5 +1,5 @@ -import { defineConfig } from 'vitest/config'; import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vitest/config'; export default defineConfig({ plugins: [react()], test: {