diff --git a/.eslintrc.cjs b/.eslintrc.cjs index d463c6f5..302fccc2 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -15,7 +15,8 @@ module.exports = { 'vite.config.ts', 'tailwind.config.js', 'postcss.config.js', - 'vite-env.d.ts' + 'vite-env.d.ts', + '.storybook/preview.ts' ], parser: '@typescript-eslint/parser', parserOptions: { @@ -117,6 +118,8 @@ module.exports = { pascalCase: true } } - ] + ], + 'unicorn/prevent-abbreviations': ['off'], + 'unicorn/prefer-logical-operator-over-ternary': ['off'] } } diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index af3e56b7..4a716f9d 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -4,10 +4,6 @@ ## 스크린샷? -## 장애물? - -## PR 포인트 - ## 참고 사항 ## 궁금한 점 diff --git a/.github/workflows/CodeDeploy.yml b/.github/workflows/CodeDeploy.yml index 18ba3e20..364d8420 100644 --- a/.github/workflows/CodeDeploy.yml +++ b/.github/workflows/CodeDeploy.yml @@ -18,6 +18,14 @@ jobs: with: node-version: '14' + - name: create env file + run: | + touch .env + echo VITE_API_ENDPOINT=${{secrets.VITE_API_ENDPOINT}} >> .env + echo VITE_CLIENT_ID=${{secrets.VITE_CLIENT_ID}} >> .env + echo VITE_CLIENT_SECRET=${{secrets.VITE_CLIENT_SECRET}} >> .env + cat .env + - name: Install dependencies and build run: | npm install diff --git a/.prettierrc b/.prettierrc index b8011af9..61c28325 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,8 +1,10 @@ { - "semi" : false, - "trailingComma" : "none", + "semi": false, + "trailingComma": "none", "arrowParens": "always", "singleQuote": true, - "tabWidth" : 2, - "printWidth" : 80 -} \ No newline at end of file + "tabWidth": 2, + "printWidth": 80, + "bracketSpacing": true, + "jsxBracketSameLine": true +} diff --git a/.storybook/main.ts b/.storybook/main.ts index 659d4405..715ad413 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -6,14 +6,14 @@ const config: StorybookConfig = { '@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-onboarding', - '@storybook/addon-interactions', + '@storybook/addon-interactions' ], framework: { name: '@storybook/react-vite', - options: {}, + options: {} }, docs: { - autodocs: 'tag', - }, + autodocs: 'tag' + } } export default config diff --git a/.storybook/preview.ts b/.storybook/preview.ts deleted file mode 100644 index ff58bbda..00000000 --- a/.storybook/preview.ts +++ /dev/null @@ -1,15 +0,0 @@ -import type { Preview } from "@storybook/react"; - -const preview: Preview = { - parameters: { - actions: { argTypesRegex: "^on[A-Z].*" }, - controls: { - matchers: { - color: /(background|color)$/i, - date: /Date$/i, - }, - }, - }, -}; - -export default preview; diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx new file mode 100644 index 00000000..c38847b9 --- /dev/null +++ b/.storybook/preview.tsx @@ -0,0 +1,51 @@ +import type { Preview } from '@storybook/react' +import { BrowserRouter } from 'react-router-dom' +import '../src/styles/index.css' +import React from 'react' + +const customViewports = { + iPhone13: { + name: 'iPhone 13', + styles: { + width: '390px', + height: '844px' + }, + type: 'mobile' + }, + tablet: { + name: 'iPad Pro 11', + styles: { + width: '834px', + height: '1194px' + }, + type: 'tablet' + } +} + +const preview: Preview = { + parameters: { + layout: 'fullscreen', + actions: { argTypesRegex: '^on[A-Z].*' }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i + } + }, + viewport: { + viewports: customViewports, + defaultViewport: 'iPhone13' + } + }, + decorators: [ + (Story) => ( + +
+ +
+
+ ) + ] +} + +export default preview diff --git a/custom.d.ts b/custom.d.ts new file mode 100644 index 00000000..ec884c5e --- /dev/null +++ b/custom.d.ts @@ -0,0 +1,6 @@ +declare module '*.svg' { + import React = require('react') + export const ReactComponent: React.FC> + const src: string + export default src +} diff --git a/index.html b/index.html index e4b78eae..ed735bad 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,7 @@ Vite + React + TS +
diff --git a/package-lock.json b/package-lock.json index e17b1ca1..788323bc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,8 +8,12 @@ "name": "client_studay", "version": "0.0.0", "dependencies": { + "@tanstack/react-query": "^5.7.2", + "@tanstack/react-query-devtools": "^5.7.2", "@types/node": "^20.8.7", "axios": "^1.5.1", + "class-variance-authority": "^0.7.0", + "clsx": "^2.0.0", "eslint-config-prettier": "^9.0.0", "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "^2.29.0", @@ -18,8 +22,8 @@ "jotai": "^2.4.3", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-query": "^3.39.3", - "react-router-dom": "^6.17.0" + "react-router-dom": "^6.17.0", + "tailwind-merge": "^1.14.0" }, "devDependencies": { "@storybook/addon-essentials": "^7.5.1", @@ -30,6 +34,9 @@ "@storybook/react": "^7.5.1", "@storybook/react-vite": "^7.5.1", "@storybook/testing-library": "^0.2.2", + "@svgr/rollup": "^8.1.0", + "@svgr/webpack": "^8.1.0", + "@types/navermaps": "^3.7.2", "@types/react": "^18.2.15", "@types/react-dom": "^18.2.14", "@typescript-eslint/eslint-plugin": "^6.0.0", @@ -1704,6 +1711,70 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-react-constant-elements": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.22.5.tgz", + "integrity": "sha512-BF5SXoO+nX3h5OhlN78XbbDrBOffv+AxPP2ENaJOVqjWCgBDeOY3WcaUcddutGSfoap+5NEQ/q/4I3WZIvgkXA==", + "dev": true, + "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-display-name": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz", + "integrity": "sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw==", + "dev": true, + "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": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.15.tgz", + "integrity": "sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-module-imports": "^7.22.15", + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/plugin-syntax-jsx": "^7.22.5", + "@babel/types": "^7.22.15" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-development": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz", + "integrity": "sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==", + "dev": true, + "dependencies": { + "@babel/plugin-transform-react-jsx": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-react-jsx-self": { "version": "7.22.5", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.22.5.tgz", @@ -1734,6 +1805,22 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-react-pure-annotations": { + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.22.5.tgz", + "integrity": "sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.22.5", + "@babel/helper-plugin-utils": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-regenerator": { "version": "7.22.10", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.10.tgz", @@ -2056,6 +2143,26 @@ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" } }, + "node_modules/@babel/preset-react": { + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.22.15.tgz", + "integrity": "sha512-Csy1IJ2uEh/PecCBXXoZGAZBeCATTuePzCSB7dLYWS0vOEj6CNpjxIhW4duWwZodBNueH7QO14WbGn8YyeuN9w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.22.5", + "@babel/helper-validator-option": "^7.22.15", + "@babel/plugin-transform-react-display-name": "^7.22.5", + "@babel/plugin-transform-react-jsx": "^7.22.15", + "@babel/plugin-transform-react-jsx-development": "^7.22.5", + "@babel/plugin-transform-react-pure-annotations": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/preset-typescript": { "version": "7.23.2", "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.23.2.tgz", @@ -2222,6 +2329,7 @@ "version": "7.23.2", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", + "dev": true, "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -5221,6 +5329,299 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@svgr/babel-plugin-add-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-b9MIk7yhdS1pMCZM8VeNfUlSKVRhsHZNMl5O9SfaX0l0t5wjdgu4IDzGB8bpnGBBOjGST3rRFVsaaEtI4W6f7g==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-attribute": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz", + "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz", + "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-8.0.0.tgz", + "integrity": "sha512-KVQ+PtIjb1BuYT3ht8M5KbzWBhdAjjUPdlMtpuw/VjT8coTrItWX6Qafl9+ji831JaJcu6PJNKCV0bp01lBNzQ==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-dynamic-title": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-8.0.0.tgz", + "integrity": "sha512-omNiKqwjNmOQJ2v6ge4SErBbkooV2aAWwaPFs2vUY7p7GhVkzRkJ00kILXQvRhA6miHnNpXv7MRnnSjdRjK8og==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-svg-em-dimensions": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-8.0.0.tgz", + "integrity": "sha512-mURHYnu6Iw3UBTbhGwE/vsngtCIbHE43xCRK7kCw4t01xyGqb2Pd+WXekRRoFOBIY29ZoOhUCTEweDMdrjfi9g==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-react-native-svg": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-8.1.0.tgz", + "integrity": "sha512-Tx8T58CHo+7nwJ+EhUwx3LfdNSG9R2OKfaIXXs5soiy5HtgoAEkDay9LIimLOcG8dJQH1wPZp/cnAv6S9CrR1Q==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-plugin-transform-svg-component": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-8.0.0.tgz", + "integrity": "sha512-DFx8xa3cZXTdb/k3kfPeaixecQLgKh5NVBMwD0AQxOzcZawK4oo1Jh9LbrcACUivsCA7TLG8eeWgrDXjTMhRmw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/babel-preset": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-8.1.0.tgz", + "integrity": "sha512-7EYDbHE7MxHpv4sxvnVPngw5fuR6pw79SkcrILHJ/iMpuKySNCl5W1qcwPEpU+LgyRXOaAFgH0KhwD18wwg6ug==", + "dev": true, + "dependencies": { + "@svgr/babel-plugin-add-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-attribute": "8.0.0", + "@svgr/babel-plugin-remove-jsx-empty-expression": "8.0.0", + "@svgr/babel-plugin-replace-jsx-attribute-value": "8.0.0", + "@svgr/babel-plugin-svg-dynamic-title": "8.0.0", + "@svgr/babel-plugin-svg-em-dimensions": "8.0.0", + "@svgr/babel-plugin-transform-react-native-svg": "8.1.0", + "@svgr/babel-plugin-transform-svg-component": "8.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@svgr/core": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/core/-/core-8.1.0.tgz", + "integrity": "sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "camelcase": "^6.2.0", + "cosmiconfig": "^8.1.3", + "snake-case": "^3.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/core/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@svgr/hast-util-to-babel-ast": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-8.0.0.tgz", + "integrity": "sha512-EbDKwO9GpfWP4jN9sGdYwPBU0kdomaPIL2Eu4YwmgP+sJeXT+L7bMwJUBnhzfH8Q2qMBqZ4fJwpCyYsAN3mt2Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.21.3", + "entities": "^4.4.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/plugin-jsx": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-8.1.0.tgz", + "integrity": "sha512-0xiIyBsLlr8quN+WyuxooNW9RJ0Dpr8uOnH/xrCVO8GLUcwHISwj1AG0k+LFzteTkAA0GbX0kj9q6Dk70PTiPA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@svgr/babel-preset": "8.1.0", + "@svgr/hast-util-to-babel-ast": "8.0.0", + "svg-parser": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/plugin-svgo": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-8.1.0.tgz", + "integrity": "sha512-Ywtl837OGO9pTLIN/onoWLmDQ4zFUycI1g76vuKGEz6evR/ZTJlJuz3G/fIkb6OVBJ2g0o6CGJzaEjfmEo3AHA==", + "dev": true, + "dependencies": { + "cosmiconfig": "^8.1.3", + "deepmerge": "^4.3.1", + "svgo": "^3.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + }, + "peerDependencies": { + "@svgr/core": "*" + } + }, + "node_modules/@svgr/rollup": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/rollup/-/rollup-8.1.0.tgz", + "integrity": "sha512-0XR1poYvPQoPpmfDYLEqUGu5ePAQ4pdgN3VFsZBNAeze7qubVpsIY1o1R6PZpKep/DKu33GSm2NhwpCLkMs2Cw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@rollup/pluginutils": "^5.0.2", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, + "node_modules/@svgr/webpack": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-8.1.0.tgz", + "integrity": "sha512-LnhVjMWyMQV9ZmeEy26maJk+8HTIbd59cH4F2MJ439k9DqejRisfFNGAPvRYlKETuh9LrImlS8aKsBgKjMA8WA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.21.3", + "@babel/plugin-transform-react-constant-elements": "^7.21.3", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@svgr/core": "8.1.0", + "@svgr/plugin-jsx": "8.1.0", + "@svgr/plugin-svgo": "8.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/gregberge" + } + }, "node_modules/@swc/core": { "version": "1.3.94", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.94.tgz", @@ -5419,17 +5820,77 @@ "node": ">=10" } }, - "node_modules/@swc/counter": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.2.tgz", - "integrity": "sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==", - "dev": true - }, - "node_modules/@swc/types": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", - "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==", - "dev": true + "node_modules/@swc/counter": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.2.tgz", + "integrity": "sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==", + "dev": true + }, + "node_modules/@swc/types": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", + "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==", + "dev": true + }, + "node_modules/@tanstack/query-core": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.7.2.tgz", + "integrity": "sha512-vPYoNCOI8W+jFLnyEAYQL7/qURE7XzVE/TvkmNSko8LU55jFshee342p4GNFOTsYFgJty7Da5bw4m2P3vaKWMw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/query-devtools": { + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/@tanstack/query-devtools/-/query-devtools-5.4.2.tgz", + "integrity": "sha512-EXdaMXi8CxZuMp97J5mq6wy1RduOfoWFv5vtA1U+hyqb8Wst6M8kkkjDSdFvGZIRpYY4K8mKLlEFHNUZDG5dtw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.7.2.tgz", + "integrity": "sha512-NMsfz0Wd3VPDvSpX9sw2x07r0kf9HwuAlNNHQvwMUHM7EcuVN/LYmlmTe40dWER1c/92Jhc5LODdtW0PyvHsFg==", + "dependencies": { + "@tanstack/query-core": "5.7.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0", + "react-native": "*" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/@tanstack/react-query-devtools": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/@tanstack/react-query-devtools/-/react-query-devtools-5.7.2.tgz", + "integrity": "sha512-yYkzdmlntdJsy+GZzCabQGxxMjhRYayQzxe7OqYYFPnLEFf/eWkbH3cjyTBlGSKqpUN/8T5QS3P1Xur+l9hEng==", + "dependencies": { + "@tanstack/query-devtools": "5.4.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "@tanstack/react-query": "^5.7.2", + "react": "^18.0.0", + "react-dom": "^18.0.0" + } }, "node_modules/@testing-library/dom": { "version": "9.3.3", @@ -5463,6 +5924,15 @@ "@testing-library/dom": ">=7.21.4" } }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "dev": true, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/@types/aria-query": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.3.tgz", @@ -5604,6 +6074,12 @@ "integrity": "sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==", "dev": true }, + "node_modules/@types/geojson": { + "version": "7946.0.12", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.12.tgz", + "integrity": "sha512-uK2z1ZHJyC0nQRbuovXFt4mzXDwf27vQeUWNhfKGwRcWW429GOhP8HxUHlM6TLH4bzmlv/HlEjpvJh3JfmGsAA==", + "dev": true + }, "node_modules/@types/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", @@ -5694,6 +6170,15 @@ "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", "dev": true }, + "node_modules/@types/navermaps": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@types/navermaps/-/navermaps-3.7.2.tgz", + "integrity": "sha512-CV3EvQIyvrpBQsb8IBKSzzVPCgO5scE/eNORSGLkkw69VV44X2hinV5Zyex4YOyewOY3pBK6YednWQAbMdJ+Pg==", + "dev": true, + "dependencies": { + "@types/geojson": "*" + } + }, "node_modules/@types/node": { "version": "20.8.7", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.7.tgz", @@ -6737,6 +7222,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true + }, "node_modules/bplist-parser": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", @@ -6768,21 +7259,6 @@ "node": ">=8" } }, - "node_modules/broadcast-channel": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz", - "integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==", - "dependencies": { - "@babel/runtime": "^7.7.2", - "detect-node": "^2.1.0", - "js-sha3": "0.8.0", - "microseconds": "0.2.0", - "nano-time": "1.0.0", - "oblivious-set": "1.0.0", - "rimraf": "3.0.2", - "unload": "2.2.0" - } - }, "node_modules/browser-assert": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz", @@ -7061,6 +7537,17 @@ "node": ">=8" } }, + "node_modules/class-variance-authority": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.0.tgz", + "integrity": "sha512-jFI8IQw4hczaL4ALINxqLEXQbWcNjoSkloa4IaufXCJr6QawJyw7tuRysRsrE8w2p/4gGaxKIt/hX3qz/IbD1A==", + "dependencies": { + "clsx": "2.0.0" + }, + "funding": { + "url": "https://joebell.co.uk" + } + }, "node_modules/clean-regexp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", @@ -7231,6 +7718,14 @@ "node": ">=0.10.0" } }, + "node_modules/clsx": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.0.0.tgz", + "integrity": "sha512-rQ1+kcj+ttHG0MKVGBUXwayCCF1oh39BF5COIpRzuCEv8Mwjv0XucrI2ExNTOn9IlLifGClWQcU9BrZORvtw6Q==", + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -7456,6 +7951,32 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -7478,6 +7999,47 @@ "node": ">=8" } }, + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -7490,6 +8052,39 @@ "node": ">=4" } }, + "node_modules/csso": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", + "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", + "dev": true, + "dependencies": { + "css-tree": "~2.2.0" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", + "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.28", + "source-map-js": "^1.0.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.28", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", + "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", + "dev": true + }, "node_modules/csstype": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", @@ -7546,6 +8141,15 @@ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==" }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/default-browser": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", @@ -7803,11 +8407,6 @@ "node": ">=8" } }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" - }, "node_modules/detect-node-es": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", @@ -7881,6 +8480,71 @@ "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true }, + "node_modules/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "dev": true, + "dependencies": { + "domelementtype": "^2.3.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", + "dev": true, + "dependencies": { + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/dotenv": { "version": "16.3.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", @@ -8019,6 +8683,18 @@ "node": ">=10.13.0" } }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, "node_modules/envinfo": { "version": "7.10.0", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.10.0.tgz", @@ -10834,11 +11510,6 @@ } } }, - "node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -11407,6 +12078,15 @@ "loose-envify": "cli.js" } }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -11491,15 +12171,6 @@ "react": ">= 0.14.0" } }, - "node_modules/match-sorter": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.1.tgz", - "integrity": "sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw==", - "dependencies": { - "@babel/runtime": "^7.12.5", - "remove-accents": "0.4.2" - } - }, "node_modules/mdast-util-definitions": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", @@ -11523,6 +12194,12 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdn-data": { + "version": "2.0.30", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", + "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", + "dev": true + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -11581,11 +12258,6 @@ "node": ">=8.6" } }, - "node_modules/microseconds": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz", - "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==" - }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -11730,14 +12402,6 @@ "thenify-all": "^1.0.0" } }, - "node_modules/nano-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz", - "integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==", - "dependencies": { - "big-integer": "^1.6.16" - } - }, "node_modules/nanoid": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", @@ -11776,6 +12440,16 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, "node_modules/node-dir": { "version": "0.1.17", "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", @@ -11876,6 +12550,18 @@ "node": ">=8" } }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -12010,11 +12696,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/oblivious-set": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz", - "integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==" - }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -12954,31 +13635,6 @@ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true }, - "node_modules/react-query": { - "version": "3.39.3", - "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz", - "integrity": "sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==", - "dependencies": { - "@babel/runtime": "^7.5.5", - "broadcast-channel": "^3.4.1", - "match-sorter": "^6.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - }, - "react-native": { - "optional": true - } - } - }, "node_modules/react-refresh": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", @@ -13281,7 +13937,8 @@ "node_modules/regenerator-runtime": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" + "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", + "dev": true }, "node_modules/regenerator-transform": { "version": "0.15.2", @@ -13387,11 +14044,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/remove-accents": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz", - "integrity": "sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==" - }, "node_modules/requireindex": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz", @@ -13815,6 +14467,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -14179,6 +14841,45 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/svg-parser": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz", + "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==", + "dev": true + }, + "node_modules/svgo": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.0.2.tgz", + "integrity": "sha512-Z706C1U2pb1+JGP48fbazf3KxHrWOsLme6Rv7imFBn5EnuanDW1GPaA/P1/dvObE670JDePC3mnj0k0B7P0jjQ==", + "dev": true, + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^5.1.0", + "css-tree": "^2.2.1", + "csso": "^5.0.5", + "picocolors": "^1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/svgo" + } + }, + "node_modules/svgo/node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, "node_modules/synchronous-promise": { "version": "2.0.17", "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.17.tgz", @@ -14200,6 +14901,15 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/tailwind-merge": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.14.0.tgz", + "integrity": "sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, "node_modules/tailwindcss": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.4.tgz", @@ -14859,15 +15569,6 @@ "node": ">= 10.0.0" } }, - "node_modules/unload": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz", - "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==", - "dependencies": { - "@babel/runtime": "^7.6.2", - "detect-node": "^2.0.4" - } - }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", diff --git a/package.json b/package.json index e97a2953..384c159d 100644 --- a/package.json +++ b/package.json @@ -14,11 +14,15 @@ "prepare": "husky install" }, "lint-staged": { - "*.{js,ts}": "npm run lint" + "src/*.{js,ts}": "npm run lint" }, "dependencies": { + "@tanstack/react-query": "^5.7.2", + "@tanstack/react-query-devtools": "^5.7.2", "@types/node": "^20.8.7", "axios": "^1.5.1", + "class-variance-authority": "^0.7.0", + "clsx": "^2.0.0", "eslint-config-prettier": "^9.0.0", "eslint-import-resolver-typescript": "^3.6.1", "eslint-plugin-import": "^2.29.0", @@ -27,8 +31,8 @@ "jotai": "^2.4.3", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-query": "^3.39.3", - "react-router-dom": "^6.17.0" + "react-router-dom": "^6.17.0", + "tailwind-merge": "^1.14.0" }, "devDependencies": { "@storybook/addon-essentials": "^7.5.1", @@ -39,6 +43,9 @@ "@storybook/react": "^7.5.1", "@storybook/react-vite": "^7.5.1", "@storybook/testing-library": "^0.2.2", + "@svgr/rollup": "^8.1.0", + "@svgr/webpack": "^8.1.0", + "@types/navermaps": "^3.7.2", "@types/react": "^18.2.15", "@types/react-dom": "^18.2.14", "@typescript-eslint/eslint-plugin": "^6.0.0", @@ -51,9 +58,9 @@ "eslint-plugin-react-refresh": "^0.4.3", "eslint-plugin-storybook": "^0.6.15", "eslint-plugin-unicorn": "^48.0.1", - "postcss": "^8.4.31", "husky": "^8.0.3", "lint-staged": "^15.0.2", + "postcss": "^8.4.31", "storybook": "^7.5.1", "tailwindcss": "^3.3.4", "typescript": "^5.0.2", diff --git a/src/App.tsx b/src/App.tsx index 17d52ab8..74b06dac 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,20 +1,9 @@ import './styles/index.css' +import { RouterProvider } from 'react-router-dom' +import { router } from './routes' function App() { - return ( -
-

{'headline-30 font'}

-

{'headline-25 font'}

-

{'subHead-18 font'}

-

{'subHead-16 font'}

-

{'subHead-13 font'}

-

{'body-18 font'}

-

{'body-16 font'}

-

{'body-15 font'}

-

{'body-14 font'}

-

{'caption-13 font'}

-
- ) + return } export default App diff --git a/src/api/index.ts b/src/api/index.ts deleted file mode 100644 index 0aa079d3..00000000 --- a/src/api/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -import axios from 'axios' - -export const api = axios.create({ - baseURL: 'baseUrl', - timeout: 10_000 -}) diff --git a/src/assets/icon/Abacus.svg b/src/assets/icon/Abacus.svg new file mode 100644 index 00000000..06c9f4f1 --- /dev/null +++ b/src/assets/icon/Abacus.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/icon/Add.svg b/src/assets/icon/Add.svg new file mode 100644 index 00000000..7447fe5d --- /dev/null +++ b/src/assets/icon/Add.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icon/Alarm.svg b/src/assets/icon/Alarm.svg new file mode 100644 index 00000000..30ff5778 --- /dev/null +++ b/src/assets/icon/Alarm.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icon/ArrowDown.svg b/src/assets/icon/ArrowDown.svg new file mode 100644 index 00000000..025eb9af --- /dev/null +++ b/src/assets/icon/ArrowDown.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icon/BackPush.svg b/src/assets/icon/BackPush.svg new file mode 100644 index 00000000..dae901ba --- /dev/null +++ b/src/assets/icon/BackPush.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icon/Close.svg b/src/assets/icon/Close.svg new file mode 100644 index 00000000..a5b78d7d --- /dev/null +++ b/src/assets/icon/Close.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icon/Computer.svg b/src/assets/icon/Computer.svg new file mode 100644 index 00000000..f175efd9 --- /dev/null +++ b/src/assets/icon/Computer.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icon/Delete.svg b/src/assets/icon/Delete.svg new file mode 100644 index 00000000..d96cf023 --- /dev/null +++ b/src/assets/icon/Delete.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icon/Edit.svg b/src/assets/icon/Edit.svg new file mode 100644 index 00000000..16b6ee20 --- /dev/null +++ b/src/assets/icon/Edit.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/icon/English.svg b/src/assets/icon/English.svg new file mode 100644 index 00000000..7224fafa --- /dev/null +++ b/src/assets/icon/English.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icon/Etc.svg b/src/assets/icon/Etc.svg new file mode 100644 index 00000000..818b1a39 --- /dev/null +++ b/src/assets/icon/Etc.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icon/Filter.svg b/src/assets/icon/Filter.svg new file mode 100644 index 00000000..c3e86045 --- /dev/null +++ b/src/assets/icon/Filter.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icon/Gps.svg b/src/assets/icon/Gps.svg new file mode 100644 index 00000000..c7686ff3 --- /dev/null +++ b/src/assets/icon/Gps.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/assets/icon/Home.svg b/src/assets/icon/Home.svg new file mode 100644 index 00000000..01beff13 --- /dev/null +++ b/src/assets/icon/Home.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icon/Info.svg b/src/assets/icon/Info.svg new file mode 100644 index 00000000..80a3aa64 --- /dev/null +++ b/src/assets/icon/Info.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icon/Korean.svg b/src/assets/icon/Korean.svg new file mode 100644 index 00000000..6bcfc03d --- /dev/null +++ b/src/assets/icon/Korean.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icon/LikeBlank.svg b/src/assets/icon/LikeBlank.svg new file mode 100644 index 00000000..1572a7df --- /dev/null +++ b/src/assets/icon/LikeBlank.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icon/LikeFilled.svg b/src/assets/icon/LikeFilled.svg new file mode 100644 index 00000000..c0970934 --- /dev/null +++ b/src/assets/icon/LikeFilled.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icon/Logo.svg b/src/assets/icon/Logo.svg new file mode 100644 index 00000000..806cf1b4 --- /dev/null +++ b/src/assets/icon/Logo.svg @@ -0,0 +1,56 @@ + +image/svg+xml \ No newline at end of file diff --git a/src/assets/icon/Logout.svg b/src/assets/icon/Logout.svg new file mode 100644 index 00000000..0664d104 --- /dev/null +++ b/src/assets/icon/Logout.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icon/MapPin.svg b/src/assets/icon/MapPin.svg new file mode 100644 index 00000000..5fea1ab3 --- /dev/null +++ b/src/assets/icon/MapPin.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icon/Math.svg b/src/assets/icon/Math.svg new file mode 100644 index 00000000..905106ec --- /dev/null +++ b/src/assets/icon/Math.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icon/Music.svg b/src/assets/icon/Music.svg new file mode 100644 index 00000000..6e34de68 --- /dev/null +++ b/src/assets/icon/Music.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icon/MyList.svg b/src/assets/icon/MyList.svg new file mode 100644 index 00000000..525d056a --- /dev/null +++ b/src/assets/icon/MyList.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icon/Science.svg b/src/assets/icon/Science.svg new file mode 100644 index 00000000..256185cd --- /dev/null +++ b/src/assets/icon/Science.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icon/Search.svg b/src/assets/icon/Search.svg new file mode 100644 index 00000000..a631e23f --- /dev/null +++ b/src/assets/icon/Search.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icon/SearchMap.svg b/src/assets/icon/SearchMap.svg new file mode 100644 index 00000000..7c9cf58c --- /dev/null +++ b/src/assets/icon/SearchMap.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icon/SideBar.svg b/src/assets/icon/SideBar.svg new file mode 100644 index 00000000..01713773 --- /dev/null +++ b/src/assets/icon/SideBar.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/icon/Social.svg b/src/assets/icon/Social.svg new file mode 100644 index 00000000..c1e486de --- /dev/null +++ b/src/assets/icon/Social.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icon/Spinner.svg b/src/assets/icon/Spinner.svg new file mode 100644 index 00000000..fb6591db --- /dev/null +++ b/src/assets/icon/Spinner.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/assets/icon/Synthesis.svg b/src/assets/icon/Synthesis.svg new file mode 100644 index 00000000..87228a12 --- /dev/null +++ b/src/assets/icon/Synthesis.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icon/Time.svg b/src/assets/icon/Time.svg new file mode 100644 index 00000000..015e19ab --- /dev/null +++ b/src/assets/icon/Time.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icon/Timetable.svg b/src/assets/icon/Timetable.svg new file mode 100644 index 00000000..7b87cd9c --- /dev/null +++ b/src/assets/icon/Timetable.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/assets/icon/User.svg b/src/assets/icon/User.svg new file mode 100644 index 00000000..fcee7aaa --- /dev/null +++ b/src/assets/icon/User.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icon/Write.svg b/src/assets/icon/Write.svg new file mode 100644 index 00000000..5a1ff4a1 --- /dev/null +++ b/src/assets/icon/Write.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icon/index.tsx b/src/assets/icon/index.tsx new file mode 100644 index 00000000..122e567f --- /dev/null +++ b/src/assets/icon/index.tsx @@ -0,0 +1,35 @@ +export { ReactComponent as Alarm } from './Alarm.svg' +export { ReactComponent as Abacus } from './Abacus.svg' +export { ReactComponent as Add } from './Add.svg' +export { ReactComponent as ArrowDown } from './ArrowDown.svg' +export { ReactComponent as BackPush } from './BackPush.svg' +export { ReactComponent as Close } from './Close.svg' +export { ReactComponent as Computer } from './Computer.svg' +export { ReactComponent as Delete } from './Delete.svg' +export { ReactComponent as Edit } from './Edit.svg' +export { ReactComponent as English } from './English.svg' +export { ReactComponent as Etc } from './Etc.svg' +export { ReactComponent as Filter } from './Filter.svg' +export { ReactComponent as Gps } from './Gps.svg' +export { ReactComponent as Home } from './Home.svg' +export { ReactComponent as Info } from './Info.svg' +export { ReactComponent as Korean } from './Korean.svg' +export { ReactComponent as LikeBlank } from './LikeBlank.svg' +export { ReactComponent as LikeFilled } from './LikeFilled.svg' +export { ReactComponent as Logout } from './Logout.svg' +export { ReactComponent as MapPin } from './MapPin.svg' +export { ReactComponent as Math } from './Math.svg' +export { ReactComponent as Music } from './Music.svg' +export { ReactComponent as MyList } from './MyList.svg' +export { ReactComponent as Science } from './Science.svg' +export { ReactComponent as Search } from './Search.svg' +export { ReactComponent as SearchMap } from './SearchMap.svg' +export { ReactComponent as SideBar } from './SideBar.svg' +export { ReactComponent as Social } from './Social.svg' +export { ReactComponent as Synthesis } from './Synthesis.svg' +export { ReactComponent as Time } from './Time.svg' +export { ReactComponent as Timetable } from './Timetable.svg' +export { ReactComponent as User } from './User.svg' +export { ReactComponent as Write } from './Write.svg' +export { ReactComponent as Spinner } from './Spinner.svg' +export { ReactComponent as Logo } from './Logo.svg' diff --git a/src/assets/img/logo100.png b/src/assets/img/logo100.png new file mode 100644 index 00000000..2aae49f5 Binary files /dev/null and b/src/assets/img/logo100.png differ diff --git a/src/assets/img/logo150.png b/src/assets/img/logo150.png new file mode 100644 index 00000000..61e25f9e Binary files /dev/null and b/src/assets/img/logo150.png differ diff --git a/src/assets/img/logo50.png b/src/assets/img/logo50.png new file mode 100644 index 00000000..5c9197bf Binary files /dev/null and b/src/assets/img/logo50.png differ diff --git a/src/components/BottomSheet/BottomSheetContent.tsx b/src/components/BottomSheet/BottomSheetContent.tsx new file mode 100644 index 00000000..4ff2a3cf --- /dev/null +++ b/src/components/BottomSheet/BottomSheetContent.tsx @@ -0,0 +1,23 @@ +interface BottomSheetContentProps { + expanded: boolean + number: string + address: string +} +const BottomSheetContent = ({ + expanded, + number, + address +}: BottomSheetContentProps) => { + return ( +
+
+ {address} +
+ {number} +
+ {expanded &&
{'펼쳤을 때 나오는 어쩌구 '}
} +
+ ) +} + +export default BottomSheetContent diff --git a/src/components/BottomSheet/BottomSheetHeader.tsx b/src/components/BottomSheet/BottomSheetHeader.tsx new file mode 100644 index 00000000..ccb6a5a6 --- /dev/null +++ b/src/components/BottomSheet/BottomSheetHeader.tsx @@ -0,0 +1,24 @@ +import { useState } from 'react' +import { LikeBlank, LikeFilled } from '@/assets/icon' +const BottomSheetHeader = ({ title }: { title: string }) => { + const [liked, setLiked] = useState(false) + //TODO: 좋아요 API 로직 추가 + return ( +
+

{title}

+ {liked ? ( + setLiked(!liked)} + /> + ) : ( + setLiked(!liked)} + /> + )} +
+ ) +} + +export default BottomSheetHeader diff --git a/src/components/Loading/Loading.tsx b/src/components/Loading/Loading.tsx new file mode 100644 index 00000000..f6ea56aa --- /dev/null +++ b/src/components/Loading/Loading.tsx @@ -0,0 +1,13 @@ +import { Spinner } from '@/assets/icon' +const Loading = () => { + return ( +
+ +
+ ) +} + +export default Loading diff --git a/src/components/common/Button.stories.ts b/src/components/common/Button.stories.ts deleted file mode 100644 index 4c786732..00000000 --- a/src/components/common/Button.stories.ts +++ /dev/null @@ -1,43 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react' -import { Button } from './Button' -const meta = { - title: 'Example/Button', - component: Button, - parameters: { - layout: 'centered' - }, - tags: ['autodocs'], - argTypes: { - backgroundColor: { control: 'color' } - } -} satisfies Meta - -export default meta -type Story = StoryObj - -export const Primary: Story = { - args: { - primary: true, - label: 'Button' - } -} - -export const Secondary: Story = { - args: { - label: 'Button' - } -} - -export const Large: Story = { - args: { - size: 'large', - label: 'Button' - } -} - -export const Small: Story = { - args: { - size: 'small', - label: 'Button' - } -} diff --git a/src/components/common/Button.tsx b/src/components/common/Button.tsx deleted file mode 100644 index c6cf4788..00000000 --- a/src/components/common/Button.tsx +++ /dev/null @@ -1,49 +0,0 @@ -interface ButtonProperties { - /** - * Is this the principal call to action on the page? - */ - primary?: boolean - /** - * What background color to use - */ - backgroundColor?: string - /** - * How large should the button be? - */ - size?: 'small' | 'medium' | 'large' - /** - * Button contents - */ - label: string - /** - * Optional click handler - */ - onClick?: () => void -} - -/** - * Primary UI component for user interaction - */ -export const Button = ({ - primary = false, - size = 'medium', - backgroundColor, - label, - ...properties -}: ButtonProperties) => { - const mode = primary - ? 'storybook-button--primary' - : 'storybook-button--secondary' - return ( - - ) -} diff --git a/src/components/common/accordion/Accordion.stories.tsx b/src/components/common/accordion/Accordion.stories.tsx new file mode 100644 index 00000000..096386d9 --- /dev/null +++ b/src/components/common/accordion/Accordion.stories.tsx @@ -0,0 +1,67 @@ +import type { Meta, StoryObj } from '@storybook/react' +import { ArrowDown } from '@/assets/icon' +import { Accordion } from '@/components/common/accordion/Accordion' +import ListRow from '@/components/common/listRow/ListRow' + +const meta: Meta = { + component: Accordion, + tags: ['autodocs'], + title: 'components/Accordion', + argTypes: { + title: { + control: 'text', + required: true + } + }, + render: ({ ...args }) => ( + + {'체르니 마스터반'} + } + rightElement={ +
+ {'50명 정원'} +
+ } + hasBorder={true} + className={'bg-white-100'} + /> + {'금액'} + } + rightElement={ +
+ {'300,000원'} +
+ } + hasBorder={true} + className={'bg-white-100'} + /> + + } + rightElement={} + /> + ) +} + +export default meta +type Story = StoryObj +export const Default: Story = { + args: { + title: '샤론음악학원', + rightElement: , + content: ( +
+
{'안녕'}
+
{'잘가'}
+
+ ) + } +} diff --git a/src/components/common/accordion/Accordion.tsx b/src/components/common/accordion/Accordion.tsx new file mode 100644 index 00000000..7e41f341 --- /dev/null +++ b/src/components/common/accordion/Accordion.tsx @@ -0,0 +1,78 @@ +import { forwardRef, ReactNode, useState } from 'react' +import ListRow from '@/components/common/listRow/ListRow' + +export interface AccordionProps { + title: string + content: ReactNode + contentHeight?: number + initialState?: boolean + rightElement?: ReactNode + onAccordionOpened?: () => void + onAccordionClosed?: () => void +} +/** + * @param title : 제목 + * @param content: 아코디언 내용 + * @param contentHeight 컨텐츠 높이 지정되면 애니메이션 적용 + * @param initialState 초기 오픈 상태 + * @param rightElement : 오른쪽 (핸들러 왼쪽)에 뱃지 같은거 넣을겨 + */ + +export const Accordion = forwardRef( + ( + { + title, + content, + onAccordionOpened, + onAccordionClosed, + contentHeight, + initialState = false, + rightElement + }: AccordionProps, + ref + ) => { + const [isOpen, setIsOpen] = useState(initialState) + + const handleAccordion = () => { + if (isOpen) { + setIsOpen((prev) => !prev) + onAccordionClosed && onAccordionClosed() + } else { + setIsOpen((prev) => !prev) + onAccordionOpened && onAccordionOpened() + } + } + + return ( +
+ + +
+ {content} +
+
+ ) + } +) diff --git a/src/components/common/bottomsheet/BottomSheet.stories.tsx b/src/components/common/bottomsheet/BottomSheet.stories.tsx new file mode 100644 index 00000000..89ca403b --- /dev/null +++ b/src/components/common/bottomsheet/BottomSheet.stories.tsx @@ -0,0 +1,22 @@ +// Button.stories.ts|tsx + +import type { Meta, StoryObj } from '@storybook/react' + +import BottomSheet from './BottomSheet' + +const meta: Meta = { + title: 'Components/BottomSheet', + component: BottomSheet, + argTypes: { + title: { + control: 'text' + } + } +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + render: (args) => +} diff --git a/src/components/common/bottomsheet/BottomSheet.tsx b/src/components/common/bottomsheet/BottomSheet.tsx new file mode 100644 index 00000000..6bfb1953 --- /dev/null +++ b/src/components/common/bottomsheet/BottomSheet.tsx @@ -0,0 +1,49 @@ +import { useState } from 'react' +import BottomSheetContent from '@/components/BottomSheet/BottomSheetContent' +import BottomSheetHeader from '@/components/BottomSheet/BottomSheetHeader' + +/** + * @param title BottomSheet에 들어갈 Title을 입력합니다. + */ + +//TODO: 추후 BottomSheet 안의 내용은 client-side 상태관리 이용하여 정보 받아 사용할 예정. 이에 따라 title props도 사라질 수 있음 +interface BottomSheetProps { + title: string + address: string + number: string +} +const BottomSheet = ({ + title = '학원명 입력', + address, + number +}: BottomSheetProps) => { + const [expanded, setExpanded] = useState(false) + return ( +
+
setExpanded(!expanded)} + > +
+
+
+ + +
+
+ ) +} + +export default BottomSheet diff --git a/src/components/common/button/Button.stories.tsx b/src/components/common/button/Button.stories.tsx new file mode 100644 index 00000000..68956845 --- /dev/null +++ b/src/components/common/button/Button.stories.tsx @@ -0,0 +1,80 @@ +import type { Meta, StoryObj } from '@storybook/react' +import Button from './Button' +const meta = { + title: 'Components/Button', + component: Button, + parameters: { + layout: 'centered' + }, + tags: ['autodocs'], + argTypes: { + label: { + control: 'text' + }, + buttonType: { + control: 'select', + options: [ + 'Plain-blue', + 'Plain-red', + 'Round-blue-500', + 'Round-blue-700', + 'Square', + 'Floating' + ] + }, + width: { + control: 'select', + options: ['SW', 'MW', 'LW', 'XLW'] + } + } +} satisfies Meta + +export default meta +type Story = StoryObj + +export const FloatButton: Story = { + args: { + label: '+', + buttonType: 'Floating' + } +} + +export const PlainBlueButton: Story = { + args: { + label: 'Plain', + buttonType: 'Plain-blue', + fullWidth: true, + onClick: () => alert('plain clicked!') + } +} + +export const PlainRedButton: Story = { + args: { + label: 'Plain', + buttonType: 'Plain-red', + onClick: () => alert('plain clicked!') + } +} +export const RoundBlue500Button: Story = { + args: { + label: 'Round', + buttonType: 'Round-blue-500', + onClick: () => alert('round clicked!') + } +} + +export const RoundBlue700Button: Story = { + args: { + label: 'Round', + buttonType: 'Round-blue-700', + onClick: () => alert('round clicked!') + } +} + +export const SquareButton: Story = { + args: { + label: 'Square', + buttonType: 'Square', + onClick: () => alert('square clicked!') + } +} diff --git a/src/components/common/button/Button.tsx b/src/components/common/button/Button.tsx new file mode 100644 index 00000000..a0d80a26 --- /dev/null +++ b/src/components/common/button/Button.tsx @@ -0,0 +1,71 @@ +import type { ButtonProps } from './ButtonType' +import { + BUTTON_BG_COLOR, + BUTTON_BORDER_COLOR, + BUTTON_HEIGHT, + BUTTON_RADIUS, + BUTTON_TEXT_COLOR, + BUTTON_WIDTH, + FONT_STYLE +} from './constants' +import cn from '@/libs/utils/cn' +const Button = ({ + className, + label, + buttonType, + fullWidth = false, + width = 'XLW', + height = 'MH', + ...props +}: ButtonProps) => { + const btnClass = ` + outline-none + ${ + buttonType === 'Floating' + ? `${BUTTON_RADIUS['max']} ${ + fullWidth ? BUTTON_WIDTH['FULL'] : BUTTON_WIDTH[width] + } ${BUTTON_HEIGHT[height]} ${'text-1xl'} ${ + BUTTON_TEXT_COLOR['white0'] + } ${BUTTON_BG_COLOR['blue500']}` + : buttonType === 'Square' + ? `${BUTTON_RADIUS['min']} ${ + fullWidth ? BUTTON_WIDTH['FULL'] : BUTTON_WIDTH[width] + } ${BUTTON_HEIGHT[height]} ${BUTTON_TEXT_COLOR['white0']} ${ + BUTTON_BG_COLOR['blue500'] + }` + : buttonType === 'Plain-blue' + ? `${BUTTON_RADIUS['middle']} ${ + fullWidth ? BUTTON_WIDTH['FULL'] : BUTTON_WIDTH[width] + } ${BUTTON_HEIGHT[height]} ${BUTTON_BG_COLOR['white0']} ${ + BUTTON_TEXT_COLOR['blue500'] + } ${BUTTON_BORDER_COLOR['blue500']}` + : buttonType === 'Plain-red' + ? `${BUTTON_RADIUS['middle']} ${ + fullWidth ? BUTTON_WIDTH['FULL'] : BUTTON_WIDTH[width] + } ${BUTTON_HEIGHT[height]} ${BUTTON_BG_COLOR['white0']} ${ + BUTTON_TEXT_COLOR['red600'] + } ${BUTTON_BORDER_COLOR['red600']}` + : buttonType === 'Round-blue-500' + ? `${BUTTON_RADIUS['middle']} ${ + fullWidth ? BUTTON_WIDTH['FULL'] : BUTTON_WIDTH[width] + } ${BUTTON_HEIGHT[height]} ${BUTTON_BG_COLOR['blue500']} ${ + BUTTON_TEXT_COLOR['white0'] + }` + : buttonType === 'Round-blue-700' + ? `${BUTTON_RADIUS['middle']} ${ + fullWidth ? BUTTON_WIDTH['FULL'] : BUTTON_WIDTH[width] + } ${BUTTON_HEIGHT[height]} ${BUTTON_BG_COLOR['blue700']} ${ + BUTTON_TEXT_COLOR['white0'] + }` + : '' + } + ${FONT_STYLE['NSK']} + ` + return ( + + ) +} + +export default Button diff --git a/src/components/common/button/ButtonType.ts b/src/components/common/button/ButtonType.ts new file mode 100644 index 00000000..bf277f78 --- /dev/null +++ b/src/components/common/button/ButtonType.ts @@ -0,0 +1,29 @@ +import { ReactNode } from 'react' + +export type ButtonTextColor = 'blue500' | 'white0' | 'red600' +export type ButtonBgColor = 'blue500' | 'blue700' | 'white0' +export type ButtonBorderColor = 'blue500' | 'red600' +export type ButtonType = + | 'Plain-blue' + | 'Plain-red' + | 'Round-blue-500' + | 'Round-blue-700' + | 'Square' + | 'Floating' +export type ButtonBorderRadius = 'min' | 'middle' | 'max' +export type ButtonWidth = 'SW' | 'MW' | 'LW' | 'XLW' +export type ButtonHeight = 'SH' | 'MH' | 'LH' + +export interface ButtonProps + extends React.ButtonHTMLAttributes { + label: ReactNode + buttonType: ButtonType + textColor?: ButtonTextColor + bgColor?: ButtonBgColor + borderColor?: ButtonBorderColor + borderRadius?: ButtonBorderRadius + width?: ButtonWidth + height?: ButtonHeight + fullWidth?: boolean + onClick?: () => void +} diff --git a/src/components/common/button/constants.ts b/src/components/common/button/constants.ts new file mode 100644 index 00000000..30ac078c --- /dev/null +++ b/src/components/common/button/constants.ts @@ -0,0 +1,40 @@ +export const FONT_STYLE = { + NSK: 'font-nsk' +} + +export const BUTTON_RADIUS = { + min: 'rounded-none', + middle: 'rounded-[12px]', + max: 'rounded-full' +} + +export const BUTTON_BORDER_COLOR = { + red600: 'border border-red-600', + blue500: 'border border-blue-500' +} + +export const BUTTON_BG_COLOR = { + white0: 'bg-white-0', + blue500: 'bg-blue-500', + blue700: 'bg-blue-700' +} + +export const BUTTON_WIDTH = { + SW: 'w-[60px]', + MW: 'w-[124px]', + LW: 'w-[343px]', + XLW: 'w-[390px]', + FULL: 'w-full' +} + +export const BUTTON_HEIGHT = { + SH: 'h-[43px]', + MH: 'h-[56px]', + LH: 'h-[60px]' +} + +export const BUTTON_TEXT_COLOR = { + white0: 'text-white-0', + blue500: 'text-blue-500', + red600: 'text-red-600' +} diff --git a/src/components/common/calender/Calender.stories.tsx b/src/components/common/calender/Calender.stories.tsx new file mode 100644 index 00000000..b9b2c60a --- /dev/null +++ b/src/components/common/calender/Calender.stories.tsx @@ -0,0 +1,20 @@ +import type { Meta, StoryObj } from '@storybook/react' +import Calender from './Calender.tsx' + +const meta: Meta = { + component: Calender, + title: 'Components/Calender', + tags: ['autodocs'], + argTypes: { + onClick: { + description: '일자를 클릭했을때 실행할 함수를 넣어주세요!', + control: { type: 'function' } + } + } +} + +export default meta +type Story = StoryObj +export const Default: Story = { + ...meta +} diff --git a/src/components/common/calender/Calender.tsx b/src/components/common/calender/Calender.tsx new file mode 100644 index 00000000..e92267f2 --- /dev/null +++ b/src/components/common/calender/Calender.tsx @@ -0,0 +1,153 @@ +import { useCallback, useEffect, useState } from 'react' +import { defaultDate, getDays } from '../../../libs/utils/date.ts' +import { + CalenderType, + DaysInfo, + DayType, + MonthType +} from '../../../types/date.ts' +import CalenderProps from './CalenderType.ts' +import { DECEMBER, JANUARY, WEEK, WeekStyle } from './constants.ts' + +const Calender = ({ onClick }: CalenderProps) => { + const [defaultYear, defaultMonth, defaultDays, days] = defaultDate() + const [calenderState, setCalenderState] = useState({ + nowYear: defaultYear, + nowMonth: defaultMonth, + nowDays: defaultDays, + toDay: days + }) + const { nowYear, nowMonth, nowDays, toDay } = calenderState + + const handleDayClick = useCallback( + (dayInfo: DaysInfo) => { + console.log(dayInfo.month, nowMonth) + console.log(dayInfo) + + if (dayInfo.month === nowMonth) { + setCalenderState({ + ...calenderState, + toDay: dayInfo.day + }) + } else { + const { year, month, day } = dayInfo + const days = getDays(year, month) + setCalenderState({ + nowYear: year, + nowMonth: month, + nowDays: days, + toDay: day + }) + } + + onClick(dayInfo) + }, + [calenderState] + ) + + const nextMonth = () => { + let nextMonth = nowMonth + 1 + let nextYear = nowYear + + if (nextMonth > DECEMBER) { + nextYear += 1 + nextMonth = JANUARY + } + + const nextDays = getDays(nextYear, nextMonth as MonthType) + + setCalenderState({ + nowYear: nextYear, + nowMonth: nextMonth as MonthType, + nowDays: nextDays, + toDay: 1 as DayType + }) + } + + const previousMonth = () => { + let previousYear = nowYear + let previousMonth = nowMonth - 1 + + if (previousMonth < JANUARY) { + previousMonth = DECEMBER + previousYear -= 1 + } + + const previousDays = getDays(previousYear, previousMonth as MonthType) + + setCalenderState({ + nowYear: previousYear, + nowMonth: previousMonth as MonthType, + nowDays: previousDays, + toDay: 1 as DayType + }) + } + + useEffect(() => { + console.log('여기서 api콜을 해주세요~') + }, [calenderState]) + + return ( +
+
+
+ {'<'} +
+
{`${nowYear}년 ${nowMonth}월`}
+
+ {'>'} +
+
+ +
+ {WEEK.map((daysOfWeek, index) => ( +
+ {daysOfWeek} +
+ ))} +
+
+ {nowDays.map((week, index) => ( +
+ {week.map((daysInfo, index) => ( +
handleDayClick(daysInfo)} + > + {daysInfo.day} +
+ ))} +
+ ))} +
+
+ ) +} + +export default Calender diff --git a/src/components/common/calender/CalenderType.ts b/src/components/common/calender/CalenderType.ts new file mode 100644 index 00000000..347b7b57 --- /dev/null +++ b/src/components/common/calender/CalenderType.ts @@ -0,0 +1,7 @@ +import { DaysInfo } from '../../../types/date.ts' + +interface CalenderProps { + onClick: (daysInfo: DaysInfo) => void +} + +export default CalenderProps diff --git a/src/components/common/calender/constants.ts b/src/components/common/calender/constants.ts new file mode 100644 index 00000000..b6f4024d --- /dev/null +++ b/src/components/common/calender/constants.ts @@ -0,0 +1,14 @@ +import { MonthType } from '../../../types/date.ts' + +export const WEEK = ['SUN', 'MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT'] +export const defaultWeek = [0, 0, 0, 0, 0, 0, 0] +export const WeekStyle = { + WEEKDAY: + 'w-full h-[40px] text-center justify-center items-center leading-[40px] cursor-pointer font-nsk caption-13 font-bold mr-[15px]', + SUN: 'text-red-500', + SAT: 'text-blue-500', + OPACITY: 'opacity-20' +} + +export const DECEMBER = 12 as MonthType +export const JANUARY = 1 as MonthType diff --git a/src/components/common/header/Header.stories.tsx b/src/components/common/header/Header.stories.tsx new file mode 100644 index 00000000..df5f1a01 --- /dev/null +++ b/src/components/common/header/Header.stories.tsx @@ -0,0 +1,57 @@ +import type { Meta, StoryObj } from '@storybook/react' +import Header from './Header' +const meta = { + title: 'Component/Header', + component: Header, + parameters: { + layout: 'centered' + }, + tags: ['autodocs'], + argTypes: { + headerType: { + control: 'select', + options: ['BackPush', 'Logo', 'Close', 'CloseWithTitle'] + }, + pageTitle: { + control: 'text' + }, + rightElement: { + control: 'text' + } + } +} satisfies Meta + +export default meta +type Story = StoryObj + +export const BackPushHeader: Story = { + args: { + headerType: 'BackPush' + } +} + +export const LogoHeader: Story = { + args: { + headerType: 'Logo', + pageTitle: 'pageName', + rightElement: ( + <> + {'👏'} + {'👏'} + + ) + } +} + +export const CloseHeader: Story = { + args: { + headerType: 'Close' + } +} + +export const CloseWithTitleHeader: Story = { + args: { + headerType: 'CloseWithTitle', + pageTitle: 'pageName' + } +} diff --git a/src/components/common/header/Header.tsx b/src/components/common/header/Header.tsx new file mode 100644 index 00000000..f87b6f55 --- /dev/null +++ b/src/components/common/header/Header.tsx @@ -0,0 +1,65 @@ +import type { HeaderProps } from './HeaderType' +import { useNavigate } from 'react-router-dom' +import Icon from '../icon/Icon' +const Header = ({ + headerType, + pageTitle = 'pageTitle', + onClick +}: HeaderProps) => { + const navigate = useNavigate() + return ( +
+
+ {headerType === 'BackPush' ? ( + alert('뒤로가기')}> + + + ) : headerType === 'Logo' ? ( + <> +
+ navigate('/')} + /> + + {pageTitle} + +
+
+
alert('알림보기!')}> + +
+ alert('사이드 바 열기')}> + + +
+ + ) : headerType === 'Close' ? ( + navigate(-1)}> + + + ) : headerType === 'CloseWithTitle' ? ( +
+ navigate(-1)}> + + + {pageTitle} +
+ ) : ( + '' + )} +
+
+ ) +} + +export default Header diff --git a/src/components/common/header/HeaderType.ts b/src/components/common/header/HeaderType.ts new file mode 100644 index 00000000..1554dece --- /dev/null +++ b/src/components/common/header/HeaderType.ts @@ -0,0 +1,9 @@ +import { ReactNode } from 'react' + +type HeaderType = 'BackPush' | 'Logo' | 'Close' | 'CloseWithTitle' +export interface HeaderProps { + headerType: HeaderType + pageTitle?: string + rightElement?: ReactNode + onClick?: () => void +} diff --git a/src/components/common/icon/Icon.stories.tsx b/src/components/common/icon/Icon.stories.tsx new file mode 100644 index 00000000..baa48d7e --- /dev/null +++ b/src/components/common/icon/Icon.stories.tsx @@ -0,0 +1,293 @@ +import type { Meta, StoryObj } from '@storybook/react' +import Icon from './Icon' + +const meta: Meta = { + component: Icon, + tags: ['autodocs'], + title: 'components/Icon', + argTypes: { + icon: { + control: 'select' + }, + classStyle: { + control: 'text' + } + } +} + +export default meta +type Story = StoryObj + +export const Abacus: Story = { + args: { + icon: 'Abacus' + } +} + +export const Alarm: Story = { + args: { + icon: 'Alarm' + } +} + +export const ArrowDown: Story = { + args: { + icon: 'ArrowDown', + classStyle: '' + }, + parameters: { + docs: { + description: { + story: `stroke 값을 지정하면 색이 변합니다. ex. className={'stroke-black'}` + } + } + } +} + +export const Add: Story = { + args: { + icon: 'Add' + } +} + +export const BackPush: Story = { + args: { + icon: 'BackPush' + } +} + +export const Close: Story = { + args: { + icon: 'Close' + } +} + +export const Computer: Story = { + args: { + icon: 'Computer', + classStyle: 'fill-blue-500' + }, + parameters: { + docs: { + description: { + story: `fill 값을 지정하면 색이 변합니다. ex. className={'fill-blue-500'}` + } + } + } +} +export const Delete: Story = { + args: { + icon: 'Delete' + } +} +export const Edit: Story = { + args: { + icon: 'Edit' + } +} +export const English: Story = { + args: { + icon: 'English' + } +} +export const Etc: Story = { + args: { + icon: 'Etc' + } +} +export const Filter: Story = { + args: { + icon: 'Filter' + } +} +export const Gps: Story = { + args: { + icon: 'Gps' + } +} +export const Home: Story = { + args: { + icon: 'Home' + }, + parameters: { + docs: { + description: { + story: 'fill 값을 지정하면 색이 변합니다.' + } + } + } +} +export const Info: Story = { + args: { + icon: 'Info' + }, + parameters: { + docs: { + description: { + story: 'fill, stroke 값을 지정하면 색이 변합니다.' + } + } + } +} +export const LikeBlank: Story = { + args: { + icon: 'LikeBlank' + } +} +export const Korean: Story = { + args: { + icon: 'Korean' + }, + parameters: { + docs: { + description: { + story: 'stroke 값을 지정하면 색이 변합니다.' + } + } + } +} +export const LikeFilled: Story = { + args: { + icon: 'LikeFilled' + } +} +export const Logout: Story = { + args: { + icon: 'Logout' + } +} +export const MapPin: Story = { + args: { + icon: 'MapPin' + } +} +export const Music: Story = { + args: { + icon: 'Music' + }, + parameters: { + docs: { + description: { + story: 'stroke 값을 지정하면 색이 변합니다.' + } + } + } +} +export const MyList: Story = { + args: { + icon: 'MyList' + } +} +export const Science: Story = { + args: { + icon: 'Science' + }, + parameters: { + docs: { + description: { + story: 'stroke 값을 지정하면 색이 변합니다.' + } + } + } +} +export const Search: Story = { + args: { + icon: 'Search' + }, + parameters: { + docs: { + description: { + story: 'stroke 값을 지정하면 색이 변합니다.' + } + } + } +} +export const Math: Story = { + args: { + icon: 'Math' + }, + parameters: { + docs: { + description: { + story: 'stroke 값을 지정하면 색이 변합니다.' + } + } + } +} +export const SearchMap: Story = { + args: { + icon: 'SearchMap' + }, + parameters: { + docs: { + description: { + story: 'fill 값을 지정하면 색이 변합니다.' + } + } + } +} +export const SideBar: Story = { + args: { + icon: 'SideBar' + } +} + +export const Social: Story = { + args: { + icon: 'Social' + }, + parameters: { + docs: { + description: { + story: 'fill 값을 지정하면 색이 변합니다.' + } + } + } +} +export const Synthesis: Story = { + args: { + icon: 'Synthesis' + }, + parameters: { + docs: { + description: { + story: 'fill 값을 지정하면 색이 변합니다.' + } + } + } +} +export const Timetable: Story = { + args: { + icon: 'Timetable' + }, + parameters: { + docs: { + description: { + story: 'fill, stroke 값을 지정하면 색이 변합니다.' + } + } + } +} +export const Write: Story = { + args: { + icon: 'Write' + }, + parameters: { + docs: { + description: { + story: 'fill 값을 지정하면 색이 변합니다.' + } + } + } +} +export const Time: Story = { + args: { + icon: 'Time' + } +} + +export const User: Story = { + args: { + icon: 'User' + } +} diff --git a/src/components/common/icon/Icon.tsx b/src/components/common/icon/Icon.tsx new file mode 100644 index 00000000..08ba4a90 --- /dev/null +++ b/src/components/common/icon/Icon.tsx @@ -0,0 +1,15 @@ +import Icons from './Icons' +export type IconType = keyof typeof Icons + +export interface IconProps { + icon: IconType + classStyle?: string + onClick?: () => void +} + +const Icon = ({ icon, classStyle, onClick }: IconProps) => { + const SvgIcon = Icons[icon] + return +} + +export default Icon diff --git a/src/components/common/icon/Icons.tsx b/src/components/common/icon/Icons.tsx new file mode 100644 index 00000000..dd3797aa --- /dev/null +++ b/src/components/common/icon/Icons.tsx @@ -0,0 +1,74 @@ +import { + Alarm, + Etc, + Abacus, + Add, + ArrowDown, + BackPush, + Close, + Computer, + Delete, + Edit, + English, + Filter, + Gps, + Home, + Info, + Korean, + LikeBlank, + LikeFilled, + Logout, + MapPin, + Math, + Music, + MyList, + Science, + Search, + SearchMap, + SideBar, + Social, + Synthesis, + Time, + Timetable, + User, + Write, + Logo +} from '@/assets/icon' +const Icons = { + Abacus, + Add, + Alarm, + ArrowDown, + BackPush, + Close, + Computer, + Delete, + Edit, + English, + Etc, + Filter, + Gps, + Home, + Info, + Korean, + LikeBlank, + LikeFilled, + Logout, + MapPin, + Math, + Music, + MyList, + Science, + Search, + SearchMap, + SideBar, + Social, + Synthesis, + Time, + Timetable, + User, + Write, + Logo +} + +export default Icons diff --git a/src/components/common/index.tsx b/src/components/common/index.tsx new file mode 100644 index 00000000..9a6b9b9c --- /dev/null +++ b/src/components/common/index.tsx @@ -0,0 +1,6 @@ +export * from './selectweek/SelectWeek' +export * from './modal/Modal' +export * from './listRow/ListRow' +export * from './label/Label' +export * from './icon/Icon' +export * from './button/Button' diff --git a/src/components/common/informationBox/Information.stories.tsx b/src/components/common/informationBox/Information.stories.tsx new file mode 100644 index 00000000..20536230 --- /dev/null +++ b/src/components/common/informationBox/Information.stories.tsx @@ -0,0 +1,46 @@ +import type { Meta, StoryObj } from '@storybook/react' +import InformationBox from './InformationBox' + +const meta = { + title: 'Components/InformationBox', + component: InformationBox, + parameters: { + layout: 'centered' + }, + tags: ['autodocs'], + argTypes: { + image: { + control: 'text' + }, + mainTitle: { + control: 'text' + }, + subTitle: { + control: 'text' + }, + description: { + control: 'text' + } + } +} satisfies Meta + +export default meta +type Story = StoryObj + +export const defaultInformationBox: Story = { + args: { + mainTitle: '김길동', + subTitle: '중학교 3학년', + description: '안녕하세요! 제 아들 김길동입니다.' + } +} + +export const profileInformationBox: Story = { + args: { + image: + 'https://static.vecteezy.com/system/resources/thumbnails/005/545/335/small/user-sign-icon-person-symbol-human-avatar-isolated-on-white-backogrund-vector.jpg', + mainTitle: '홍길동', + subTitle: '고등학교 1학년', + description: '안녕하세요! 고1 홍길동입니다' + } +} diff --git a/src/components/common/informationBox/InformationBox.tsx b/src/components/common/informationBox/InformationBox.tsx new file mode 100644 index 00000000..deb2df5f --- /dev/null +++ b/src/components/common/informationBox/InformationBox.tsx @@ -0,0 +1,40 @@ +import type { InformationBoxProps } from './InformationBoxType' +import Icon from '../icon/Icon' +import Profile from '../profile/Profile' + +// CHECK + +const InformationBox = ({ + mainTitle, + subTitle, + description, + onClick // CHECK : description은 글자 수 설정을 해놓으면 좋을 것 같습니다! +}: InformationBoxProps) => { + return ( +
+
+ +
+

{mainTitle}

+

{subTitle}

+

+ {description} +

+ + + +
+
+
+ ) +} + +export default InformationBox diff --git a/src/components/common/informationBox/InformationBoxType.ts b/src/components/common/informationBox/InformationBoxType.ts new file mode 100644 index 00000000..1aca78e3 --- /dev/null +++ b/src/components/common/informationBox/InformationBoxType.ts @@ -0,0 +1,8 @@ +import { ComponentProps } from 'react' + +export interface InformationBoxProps extends ComponentProps<'div'> { + image?: string + mainTitle: string + subTitle: string + description: string +} diff --git a/src/components/common/inputbox/input/Input.stories.tsx b/src/components/common/inputbox/input/Input.stories.tsx new file mode 100644 index 00000000..70400659 --- /dev/null +++ b/src/components/common/inputbox/input/Input.stories.tsx @@ -0,0 +1,38 @@ +import type { Meta, StoryObj } from '@storybook/react' +import Input from '@/components/common/inputbox/input/Input' + +const meta: Meta = { + component: Input, + tags: ['autodocs'], + title: 'components/Input', + argTypes: { + inputType: { + control: 'select', + options: ['Default', 'Select'] + }, + fullWidth: { + control: 'boolean' + }, + value: { control: 'text' }, + placeholder: { control: 'text' } + } +} + +export default meta +type Story = StoryObj + +export const DefaultInput: Story = { + args: { + inputType: 'Default', + fullWidth: true, + placeholder: '값을 입력해주세요' + } +} + +export const SearchInput: Story = { + args: { + inputType: 'Search', + fullWidth: true, + placeholder: '값을 입력해주세요' + } +} diff --git a/src/components/common/inputbox/input/Input.tsx b/src/components/common/inputbox/input/Input.tsx new file mode 100644 index 00000000..487ec9b0 --- /dev/null +++ b/src/components/common/inputbox/input/Input.tsx @@ -0,0 +1,74 @@ +import type { InputProps } from './InputType' +import { forwardRef, useState } from 'react' +import Icon from '../../icon/Icon' + +const Input = forwardRef( + ( + { + inputType = 'Default', + fullWidth = false, + width, + height, + name, + placeholder = '', + errorMessage, + ...props + }: InputProps, + ref + ) => { + const [inputValue, setInputValue] = useState('') + const [searchInputValue, setSearchInputValue] = useState('') + return inputType === 'Default' ? ( + <> + +

+ {errorMessage} +

+ + ) : inputType === 'Search' ? ( + <> +
+ + { + setSearchInputValue(e.target.value) + }} + ref={ref} + {...props} + /> +
+

+ {errorMessage} +

+ + ) : ( + '' + ) + } +) + +export default Input diff --git a/src/components/common/inputbox/input/InputType.ts b/src/components/common/inputbox/input/InputType.ts new file mode 100644 index 00000000..b20fbce1 --- /dev/null +++ b/src/components/common/inputbox/input/InputType.ts @@ -0,0 +1,11 @@ +import { ComponentProps } from 'react' + +type InputType = 'Default' | 'Search' +export interface InputProps extends ComponentProps<'input'> { + inputType: InputType + fullWidth?: boolean + typo?: string + errorMessage?: string + placeholder?: string + onChange?: (e: React.ChangeEvent) => void +} diff --git a/src/components/common/inputbox/select/Select.stories.tsx b/src/components/common/inputbox/select/Select.stories.tsx new file mode 100644 index 00000000..2755c685 --- /dev/null +++ b/src/components/common/inputbox/select/Select.stories.tsx @@ -0,0 +1,35 @@ +import type { Meta, StoryObj } from '@storybook/react' +import Select from '@/components/common/inputbox/select/Select' + +const meta: Meta = { + component: Select, + tags: ['autodocs'], + title: 'components/Select', + argTypes: { + selectType: { + control: 'select', + options: ['Box', 'Single'] + }, + fullWidth: { + control: 'boolean' + }, + value: { control: 'text' } + } +} + +export default meta +type Story = StoryObj + +export const SingleSelect: Story = { + args: { + selectType: 'Single', + fullWidth: true + } +} + +export const BoxSelect: Story = { + args: { + selectType: 'Box', + fullWidth: true + } +} diff --git a/src/components/common/inputbox/select/Select.tsx b/src/components/common/inputbox/select/Select.tsx new file mode 100644 index 00000000..5b9574f9 --- /dev/null +++ b/src/components/common/inputbox/select/Select.tsx @@ -0,0 +1,87 @@ +import type { SelectProps } from './SelectType' +import { forwardRef, useState } from 'react' +import Icon from '../../icon/Icon' + +const Select = forwardRef( + ( + { + selectType = 'Single', + fullWidth = true, + name, + width, + height, + value = selectType === 'Single' ? '' : 'false', + errorMessage, + options, + ...props + }: SelectProps, + ref + ) => { + const [boxSelectedValue, setBoxSelectedValue] = useState(false) + return selectType === 'Single' ? ( +
+ +
+ +
+

{errorMessage}

+
+ ) : ( + // selectedType : Box + <> +
+

{'반복'}

+ +
+ +
+
+

{errorMessage}

+ + ) + } +) + +export default Select diff --git a/src/components/common/inputbox/select/SelectType.ts b/src/components/common/inputbox/select/SelectType.ts new file mode 100644 index 00000000..352bc741 --- /dev/null +++ b/src/components/common/inputbox/select/SelectType.ts @@ -0,0 +1,13 @@ +import { ComponentProps } from 'react' + +type SelectType = 'Single' | 'Box' +export interface SelectProps extends ComponentProps<'select'> { + selectType: SelectType + value: string + options: string[] + fullWidth?: boolean + width?: number + height?: number + errorMessage?: string + onChange?: (e: React.ChangeEvent) => void +} diff --git a/src/components/common/label/Label.stories.tsx b/src/components/common/label/Label.stories.tsx new file mode 100644 index 00000000..b4453685 --- /dev/null +++ b/src/components/common/label/Label.stories.tsx @@ -0,0 +1,54 @@ +import type { Meta, StoryObj } from '@storybook/react' + +import Label from './Label' + +const meta: Meta = { + title: 'Components/Label', + component: Label, + argTypes: { + label: { + control: 'text' + }, + color: { + control: 'select', + options: ['default', 'selected', 'disabled'] + }, + icon: { + control: 'select', + options: [ + 'Abacus', + 'Computer', + 'English', + 'Etc', + 'Korean', + 'Math', + 'Music', + 'Science', + 'Music', + 'Social', + 'Synthesis', + 'Write' + ] + } + } +} + +export default meta +type Story = StoryObj + +export const Medium: Story = { + render: (args) => ( +