diff --git a/.eslintrc.cjs b/.eslintrc.cjs index a92fb0b..9432eb9 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,42 +1,40 @@ /** @type {import("eslint").Linter.Config} */ const config = { - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": true + parser: "@typescript-eslint/parser", + parserOptions: { + project: true, }, - "plugins": [ - "@typescript-eslint" - ], - "extends": [ + plugins: ["@typescript-eslint"], + extends: [ "next/core-web-vitals", "plugin:@typescript-eslint/recommended-type-checked", - "plugin:@typescript-eslint/stylistic-type-checked" + "plugin:@typescript-eslint/stylistic-type-checked", ], - "rules": { + rules: { "@typescript-eslint/array-type": "off", "@typescript-eslint/consistent-type-definitions": "off", + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-unsafe-assignment": "off", + "@typescript-eslint/no-unsafe-return": "off", + "@typescript-eslint/no-unsafe-member-access": "off", + "@typescript-eslint/no-unsafe-argument": "off", + "@typescript-eslint/no-unused-vars": "off", "@typescript-eslint/consistent-type-imports": [ "warn", { - "prefer": "type-imports", - "fixStyle": "inline-type-imports" - } - ], - "@typescript-eslint/no-unused-vars": [ - "warn", - { - "argsIgnorePattern": "^_" - } + prefer: "type-imports", + fixStyle: "inline-type-imports", + }, ], "@typescript-eslint/require-await": "off", "@typescript-eslint/no-misused-promises": [ "error", { - "checksVoidReturn": { - "attributes": false - } - } - ] - } -} -module.exports = config; \ No newline at end of file + checksVoidReturn: { + attributes: false, + }, + }, + ], + }, +}; +module.exports = config; diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..33a32bc --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "editor.formatOnSave": true, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "prettier.requireConfig": true, + "[prisma]": { + "editor.defaultFormatter": "Prisma.prisma" + } +} diff --git a/README.md b/README.md index 7d19300..dc6861d 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## Stack -- Next.js +- Next.js + Typescript - Tailwind CSS - Ant Design (Design System) @@ -25,7 +25,35 @@ ## Sample pages -- /empty : to understand design pattern -- /home : default page with header and footer -- /pageWithModal -- /pageWithForm +- /sample/empty : to understand design pattern +- /sample/home : default page with header and footer +- /sample/pageWithModal +- /sample/pageWithForm + +## Your Mission + +- [Figma Link - My Figma Design](https://www.figma.com/design/woh625WWLkXky7J5aqsD3P/Cyrus-Tabji---NamuSoft-Test?node-id=0-1&node-type=canvas&t=7jqCK5SIZWAuhBpy-0) +- No questions allowed before your mission is done + - This is part of our process + - You can ask question after your misssion is completed +- Use ESLint required +- Step 1. + - Request your github account to be invited +- Step 2. + - Analyze the given code pattern + - Understand the structure and functionality of the code +- Step 3. + - Create a folder with a short name under the `/app` directory. + - Example: `/app/david` + - make your own branch from dev + - git checkout dev + - (dev) git checkout -b david + - (david) git push origin david +- Step 4. + - Create one Pull Request (PR) for each route + - /app/david/testPage1 + - branchName : david_testPage1 + - Create a PR when your work is done + - /app/david/testPage2 + - branchName : david_testPage2 + - Create a PR when your work is done diff --git a/next.config.js b/next.config.js index ec7f804..a995ba9 100644 --- a/next.config.js +++ b/next.config.js @@ -20,7 +20,7 @@ const config = { return [ { source: "/", - destination: "/home", + destination: "/sample/home", permanent: false, }, ]; diff --git a/package-lock.json b/package-lock.json index 4279c30..a43cf46 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,13 +8,16 @@ "name": "front-example", "version": "0.1.0", "dependencies": { + "@ant-design/cssinjs": "^1.20.0", "@svgr/webpack": "^8.1.0", "@t3-oss/env-nextjs": "^0.10.1", + "antd": "^5.18.0", "geist": "^1.3.0", "next": "^14.2.1", "react": "^18.3.0", "react-dom": "^18.3.0", "ts-node": "^10.9.2", + "valtio": "^1.13.2", "zod": "^3.23.3" }, "devDependencies": { @@ -57,6 +60,71 @@ "node": ">=6.0.0" } }, + "node_modules/@ant-design/colors": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.0.2.tgz", + "integrity": "sha512-7KJkhTiPiLHSu+LmMJnehfJ6242OCxSlR3xHVBecYxnMW8MS/878NXct1GqYARyL59fyeFdKRxXTfvR9SnDgJg==", + "dependencies": { + "@ctrl/tinycolor": "^3.6.1" + } + }, + "node_modules/@ant-design/cssinjs": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.20.0.tgz", + "integrity": "sha512-uG3iWzJxgNkADdZmc6W0Ci3iQAUOvLMcM8SnnmWq3r6JeocACft4ChnY/YWvI2Y+rG/68QBla/O+udke1yH3vg==", + "dependencies": { + "@babel/runtime": "^7.11.1", + "@emotion/hash": "^0.8.0", + "@emotion/unitless": "^0.7.5", + "classnames": "^2.3.1", + "csstype": "^3.1.3", + "rc-util": "^5.35.0", + "stylis": "^4.0.13" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/icons": { + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.3.7.tgz", + "integrity": "sha512-bCPXTAg66f5bdccM4TT21SQBDO1Ek2gho9h3nO9DAKXJP4sq+5VBjrQMSxMVXSB3HyEz+cUbHQ5+6ogxCOpaew==", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.11.2", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/icons-svg": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", + "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==" + }, + "node_modules/@ant-design/react-slick": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.1.2.tgz", + "integrity": "sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==", + "dependencies": { + "@babel/runtime": "^7.10.4", + "classnames": "^2.2.5", + "json2mq": "^0.2.0", + "resize-observer-polyfill": "^1.5.1", + "throttle-debounce": "^5.0.0" + }, + "peerDependencies": { + "react": ">=16.9.0" + } + }, "node_modules/@babel/code-frame": { "version": "7.24.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.6.tgz", @@ -1935,6 +2003,24 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" + }, + "node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -2349,6 +2435,129 @@ "node": ">=14" } }, + "node_modules/@rc-component/async-validator": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@rc-component/async-validator/-/async-validator-5.0.4.tgz", + "integrity": "sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==", + "dependencies": { + "@babel/runtime": "^7.24.4" + }, + "engines": { + "node": ">=14.x" + } + }, + "node_modules/@rc-component/color-picker": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-1.5.3.tgz", + "integrity": "sha512-+tGGH3nLmYXTalVe0L8hSZNs73VTP5ueSHwUlDC77KKRaN7G4DS4wcpG5DTDzdcV/Yas+rzA6UGgIyzd8fS4cw==", + "dependencies": { + "@babel/runtime": "^7.23.6", + "@ctrl/tinycolor": "^3.6.1", + "classnames": "^2.2.6", + "rc-util": "^5.38.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/context": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz", + "integrity": "sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/mini-decimal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz", + "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==", + "dependencies": { + "@babel/runtime": "^7.18.0" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@rc-component/mutate-observer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz", + "integrity": "sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz", + "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/tour": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.15.0.tgz", + "integrity": "sha512-h6hyILDwL+In9GAgRobwRWihLqqsD7Uft3fZGrJ7L4EiyCoxbnNYwzPXDfz7vNDhWeVyvAWQJj9fJCzpI4+b4g==", + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/portal": "^1.0.0-9", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/trigger": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.2.0.tgz", + "integrity": "sha512-QarBCji02YE9aRFhZgRZmOpXBj0IZutRippsVBv85sxvG4FGk/vRxwAlkn3MS9zK5mwbETd86mAVg2tKqTkdJA==", + "dependencies": { + "@babel/runtime": "^7.23.2", + "@rc-component/portal": "^1.1.0", + "classnames": "^2.3.2", + "rc-motion": "^2.0.0", + "rc-resize-observer": "^1.3.1", + "rc-util": "^5.38.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, "node_modules/@rushstack/eslint-patch": { "version": "1.10.3", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz", @@ -2711,13 +2920,13 @@ "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "dev": true + "devOptional": true }, "node_modules/@types/react": { "version": "18.3.3", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", - "dev": true, + "devOptional": true, "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -2991,6 +3200,69 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/antd": { + "version": "5.18.0", + "resolved": "https://registry.npmjs.org/antd/-/antd-5.18.0.tgz", + "integrity": "sha512-xAvqvioW34npeZb8/JLZmCh5mcHU5MLiA0IYWAlpLAVmSgjs3p0tNzbU6a7Yx+y7o7E8PHtlchWfO3yBLQ15FQ==", + "dependencies": { + "@ant-design/colors": "^7.0.2", + "@ant-design/cssinjs": "^1.19.1", + "@ant-design/icons": "^5.3.7", + "@ant-design/react-slick": "~1.1.2", + "@babel/runtime": "^7.24.5", + "@ctrl/tinycolor": "^3.6.1", + "@rc-component/color-picker": "~1.5.3", + "@rc-component/mutate-observer": "^1.1.0", + "@rc-component/tour": "~1.15.0", + "@rc-component/trigger": "^2.2.0", + "classnames": "^2.5.1", + "copy-to-clipboard": "^3.3.3", + "dayjs": "^1.11.10", + "qrcode.react": "^3.1.0", + "rc-cascader": "~3.26.0", + "rc-checkbox": "~3.3.0", + "rc-collapse": "~3.7.3", + "rc-dialog": "~9.4.0", + "rc-drawer": "~7.2.0", + "rc-dropdown": "~4.2.0", + "rc-field-form": "~2.2.0", + "rc-image": "~7.8.0", + "rc-input": "~1.5.1", + "rc-input-number": "~9.1.0", + "rc-mentions": "~2.13.1", + "rc-menu": "~9.14.0", + "rc-motion": "^2.9.1", + "rc-notification": "~5.6.0", + "rc-pagination": "~4.0.4", + "rc-picker": "~4.5.0", + "rc-progress": "~4.0.0", + "rc-rate": "~2.13.0", + "rc-resize-observer": "^1.4.0", + "rc-segmented": "~2.3.0", + "rc-select": "~14.14.0", + "rc-slider": "~10.6.2", + "rc-steps": "~6.0.1", + "rc-switch": "~4.1.0", + "rc-table": "~7.45.7", + "rc-tabs": "~15.1.0", + "rc-textarea": "~1.7.0", + "rc-tooltip": "~6.2.0", + "rc-tree": "~5.8.7", + "rc-tree-select": "~5.21.0", + "rc-upload": "~4.5.2", + "rc-util": "^5.41.0", + "scroll-into-view-if-needed": "^3.1.0", + "throttle-debounce": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ant-design" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", @@ -3066,6 +3338,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/array-tree-filter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz", + "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==" + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -3488,6 +3765,11 @@ "node": ">= 6" } }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -3520,6 +3802,11 @@ "node": ">= 6" } }, + "node_modules/compute-scroll-into-view": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz", + "integrity": "sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==" + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -3531,6 +3818,14 @@ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==" }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, "node_modules/core-js-compat": { "version": "3.37.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", @@ -3670,8 +3965,7 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/damerau-levenshtein": { "version": "1.0.8", @@ -3730,6 +4024,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/dayjs": { + "version": "1.11.11", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.11.tgz", + "integrity": "sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg==" + }, "node_modules/debug": { "version": "4.3.5", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", @@ -3803,6 +4102,14 @@ "node": ">=6" } }, + "node_modules/derive-valtio": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/derive-valtio/-/derive-valtio-0.1.0.tgz", + "integrity": "sha512-OCg2UsLbXK7GmmpzMXhYkdO64vhJ1ROUUGaTFyHjVwEdMEcTTRj7W1TxLbSBxdY8QLBPCcp66MTyaSy0RpO17A==", + "peerDependencies": { + "valtio": "*" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -5735,6 +6042,14 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, + "node_modules/json2mq": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", + "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", + "dependencies": { + "string-convert": "^0.2.0" + } + }, "node_modules/json5": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", @@ -6660,6 +6975,11 @@ "react-is": "^16.13.1" } }, + "node_modules/proxy-compare": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/proxy-compare/-/proxy-compare-2.6.0.tgz", + "integrity": "sha512-8xuCeM3l8yqdmbPoYeLbrAXCBWu19XEYc5/F28f5qOaoAIMyfmBUkl5axiK+x9olUvRlcekvnm98AP9RDngOIw==" + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -6669,6 +6989,14 @@ "node": ">=6" } }, + "node_modules/qrcode.react": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.1.0.tgz", + "integrity": "sha512-oyF+Urr3oAMUG/OiOuONL3HXM+53wvuH3mtIWQrYmsXoAq0DkvZp2RYUWFSMFtbdOpuS++9v+WAkzNVkMlNW6Q==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -6689,6 +7017,583 @@ } ] }, + "node_modules/rc-cascader": { + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.26.0.tgz", + "integrity": "sha512-L1dml383TPSJD1I11YwxuVbmqaJY64psZqFp1ETlgl3LEOwDu76Cyl11fw5dmjJhMlUWwM5dECQfqJgfebhUjg==", + "dependencies": { + "@babel/runtime": "^7.12.5", + "array-tree-filter": "^2.1.0", + "classnames": "^2.3.1", + "rc-select": "~14.14.0", + "rc-tree": "~5.8.1", + "rc-util": "^5.37.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-checkbox": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.3.0.tgz", + "integrity": "sha512-Ih3ZaAcoAiFKJjifzwsGiT/f/quIkxJoklW4yKGho14Olulwn8gN7hOBve0/WGDg5o/l/5mL0w7ff7/YGvefVw==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.3.2", + "rc-util": "^5.25.2" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-collapse": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.7.3.tgz", + "integrity": "sha512-60FJcdTRn0X5sELF18TANwtVi7FtModq649H11mYF1jh83DniMoM4MqY627sEKRCTm4+WXfGDcB7hY5oW6xhyw==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.3.4", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dialog": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.4.0.tgz", + "integrity": "sha512-AScCexaLACvf8KZRqCPz12BJ8olszXOS4lKlkMyzDQHS1m0zj1KZMYgmMCh39ee0Dcv8kyrj8mTqxuLyhH+QuQ==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/portal": "^1.0.0-8", + "classnames": "^2.2.6", + "rc-motion": "^2.3.0", + "rc-util": "^5.21.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-drawer": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-7.2.0.tgz", + "integrity": "sha512-9lOQ7kBekEJRdEpScHvtmEtXnAsy+NGDXiRWc2ZVC7QXAazNVbeT4EraQKYwCME8BJLa8Bxqxvs5swwyOepRwg==", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@rc-component/portal": "^1.1.1", + "classnames": "^2.2.6", + "rc-motion": "^2.6.1", + "rc-util": "^5.38.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dropdown": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.2.0.tgz", + "integrity": "sha512-odM8Ove+gSh0zU27DUj5cG1gNKg7mLWBYzB5E4nNLrLwBmYEgYP43vHKDGOVZcJSVElQBI0+jTQgjnq0NfLjng==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.6", + "rc-util": "^5.17.0" + }, + "peerDependencies": { + "react": ">=16.11.0", + "react-dom": ">=16.11.0" + } + }, + "node_modules/rc-field-form": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-2.2.1.tgz", + "integrity": "sha512-uoNqDoR7A4tn4QTSqoWPAzrR7ZwOK5I+vuZ/qdcHtbKx+ZjEsTg7QXm2wk/jalDiSksAQmATxL0T5LJkRREdIA==", + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/async-validator": "^5.0.3", + "rc-util": "^5.32.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-image": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.8.1.tgz", + "integrity": "sha512-Y7/ALO8kgAddl9WBHUQDcff7Yfcd1T2ALS/JPlRqkau8wcua48k99glv/CcgChy4xwUXCUdO1cM2l1NqtoZZHw==", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/portal": "^1.0.2", + "classnames": "^2.2.6", + "rc-dialog": "~9.4.0", + "rc-motion": "^2.6.2", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-input": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.5.1.tgz", + "integrity": "sha512-+nOzQJDeIfIpNP/SgY45LXSKbuMlp4Yap2y8c+ZpU7XbLmNzUd6+d5/S75sA/52jsVE6S/AkhkkDEAOjIu7i6g==", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.18.1" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-input-number": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.1.0.tgz", + "integrity": "sha512-NqJ6i25Xn/AgYfVxynlevIhX3FuKlMwIFpucGG1h98SlK32wQwDK0zhN9VY32McOmuaqzftduNYWWooWz8pXQA==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/mini-decimal": "^1.0.1", + "classnames": "^2.2.5", + "rc-input": "~1.5.0", + "rc-util": "^5.40.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-mentions": { + "version": "2.13.2", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.13.2.tgz", + "integrity": "sha512-gJCF6MDax/2wl2CzvJEN9yyQKYDzGKA2hmmymQiEPiYUNUOk6UKvQFSB3TBfAi57vxntPMJZGfxNtda1BDb4kA==", + "dependencies": { + "@babel/runtime": "^7.22.5", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.6", + "rc-input": "~1.5.0", + "rc-menu": "~9.14.0", + "rc-textarea": "~1.7.0", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-menu": { + "version": "9.14.0", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.14.0.tgz", + "integrity": "sha512-La3LBCDMLMs9Q/8mTGbnscb+ZeJ26ebkLz9xJFHd2SD8vfsCKl1Z/k3mwbxyKL01lB40fel1s9Nn9LAv/nmVJQ==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^2.0.0", + "classnames": "2.x", + "rc-motion": "^2.4.3", + "rc-overflow": "^1.3.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-motion": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.1.tgz", + "integrity": "sha512-QD4bUqByjVQs7PhUT1d4bNxvtTcK9ETwtg7psbDfo6TmYalH/1hhjj4r2hbhW7g5OOEqYHhfwfj4noIvuOVRtQ==", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.39.3" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-notification": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.6.0.tgz", + "integrity": "sha512-TGQW5T7waOxLwgJG7fXcw8l7AQiFOjaZ7ISF5PrU526nunHRNcTMuzKihQHaF4E/h/KfOCDk3Mv8eqzbu2e28w==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.9.0", + "rc-util": "^5.20.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-overflow": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.3.2.tgz", + "integrity": "sha512-nsUm78jkYAoPygDAcGZeC2VwIg/IBGSodtOY3pMof4W3M9qRJgqaDYm03ZayHlde3I6ipliAxbN0RUcGf5KOzw==", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.37.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-pagination": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-4.0.4.tgz", + "integrity": "sha512-GGrLT4NgG6wgJpT/hHIpL9nELv27A1XbSZzECIuQBQTVSf4xGKxWr6I/jhpRPauYEWEbWVw22ObG6tJQqwJqWQ==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.3.2", + "rc-util": "^5.38.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-picker": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.5.0.tgz", + "integrity": "sha512-suqz9bzuhBQlf7u+bZd1bJLPzhXpk12w6AjQ9BTPTiFwexVZgUKViG1KNLyfFvW6tCUZZK0HmCCX7JAyM+JnCg==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.1", + "rc-overflow": "^1.3.2", + "rc-resize-observer": "^1.4.0", + "rc-util": "^5.38.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "date-fns": ">= 2.x", + "dayjs": ">= 1.x", + "luxon": ">= 3.x", + "moment": ">= 2.x", + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + }, + "peerDependenciesMeta": { + "date-fns": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + } + } + }, + "node_modules/rc-progress": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-4.0.0.tgz", + "integrity": "sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-util": "^5.16.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-rate": { + "version": "2.13.0", + "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.13.0.tgz", + "integrity": "sha512-oxvx1Q5k5wD30sjN5tqAyWTvJfLNNJn7Oq3IeS4HxWfAiC4BOXMITNAsw7u/fzdtO4MS8Ki8uRLOzcnEuoQiAw==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.0.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-resize-observer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.4.0.tgz", + "integrity": "sha512-PnMVyRid9JLxFavTjeDXEXo65HCRqbmLBw9xX9gfC4BZiSzbLXKzW3jPz+J0P71pLbD5tBMTT+mkstV5gD0c9Q==", + "dependencies": { + "@babel/runtime": "^7.20.7", + "classnames": "^2.2.1", + "rc-util": "^5.38.0", + "resize-observer-polyfill": "^1.5.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-segmented": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.3.0.tgz", + "integrity": "sha512-I3FtM5Smua/ESXutFfb8gJ8ZPcvFR+qUgeeGFQHBOvRiRKyAk4aBE5nfqrxXx+h8/vn60DQjOt6i4RNtrbOobg==", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-motion": "^2.4.4", + "rc-util": "^5.17.0" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-select": { + "version": "14.14.0", + "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.14.0.tgz", + "integrity": "sha512-Uo2wulrjoPPRLCPd7zlK4ZFVJxlTN//yp1xWP/U+TUOQCyXrT+Duvq/Si5OzVcmQyWAUSbsplc2OwNNhvbOeKQ==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^2.1.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-overflow": "^1.3.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-slider": { + "version": "10.6.2", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-10.6.2.tgz", + "integrity": "sha512-FjkoFjyvUQWcBo1F3RgSglky3ar0+qHLM41PlFVYB4Bj3RD8E/Mv7kqMouLFBU+3aFglMzzctAIWRwajEuueSw==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.36.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-steps": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-6.0.1.tgz", + "integrity": "sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==", + "dependencies": { + "@babel/runtime": "^7.16.7", + "classnames": "^2.2.3", + "rc-util": "^5.16.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-switch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-4.1.0.tgz", + "integrity": "sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==", + "dependencies": { + "@babel/runtime": "^7.21.0", + "classnames": "^2.2.1", + "rc-util": "^5.30.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-table": { + "version": "7.45.7", + "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.45.7.tgz", + "integrity": "sha512-wi9LetBL1t1csxyGkMB2p3mCiMt+NDexMlPbXHvQFmBBAsMxrgNSAPwUci2zDLUq9m8QdWc1Nh8suvrpy9mXrg==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/context": "^1.4.0", + "classnames": "^2.2.5", + "rc-resize-observer": "^1.1.0", + "rc-util": "^5.37.0", + "rc-virtual-list": "^3.14.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tabs": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-15.1.0.tgz", + "integrity": "sha512-xTNz4Km1025emtkv1q7xKhjPwAtXr/wycuXVTAcFJg+DKhnPDDbnwbA9KRW0SawAVOGvVEj8ZrBlU0u0FGLrbg==", + "dependencies": { + "@babel/runtime": "^7.11.2", + "classnames": "2.x", + "rc-dropdown": "~4.2.0", + "rc-menu": "~9.14.0", + "rc-motion": "^2.6.2", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.34.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-textarea": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.7.0.tgz", + "integrity": "sha512-UxizYJkWkmxP3zofXgc487QiGyDmhhheDLLjIWbFtDmiru1ls30KpO8odDaPyqNUIy9ugj5djxTEuezIn6t3Jg==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-input": "~1.5.0", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tooltip": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.2.0.tgz", + "integrity": "sha512-iS/3iOAvtDh9GIx1ulY7EFUXUtktFccNLsARo3NPgLf0QW9oT0w3dA9cYWlhqAKmD+uriEwdWz1kH0Qs4zk2Aw==", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.3.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tree": { + "version": "5.8.7", + "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.8.7.tgz", + "integrity": "sha512-cpsIQZ4nNYwpj6cqPRt52e/69URuNdgQF9wZ10InmEf8W3+i0A41OVmZWwHuX9gegQSqj+DPmaDkZFKQZ+ZV1w==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.1" + }, + "engines": { + "node": ">=10.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-tree-select": { + "version": "5.21.0", + "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.21.0.tgz", + "integrity": "sha512-w+9qEu6zh0G3wt9N/hzWNSnqYH1i9mH1Nqxo0caxLRRFXF5yZWYmpCDoDTMdQM1Y4z3Q5yj08qyrPH/d4AtumA==", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-select": "~14.14.0", + "rc-tree": "~5.8.1", + "rc-util": "^5.16.1" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-upload": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.5.2.tgz", + "integrity": "sha512-QO3ne77DwnAPKFn0bA5qJM81QBjQi0e0NHdkvpFyY73Bea2NfITiotqJqVjHgeYPOJu5lLVR32TNGP084aSoXA==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "classnames": "^2.2.5", + "rc-util": "^5.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util": { + "version": "5.41.0", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.41.0.tgz", + "integrity": "sha512-xtlCim9RpmVv0Ar2Nnc3WfJCxjQkTf3xHPWoFdjp1fSs2NirQwqiQrfqdU9HUe0kdfb168M/T8Dq0IaX50xeKg==", + "dependencies": { + "@babel/runtime": "^7.18.3", + "react-is": "^18.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==" + }, + "node_modules/rc-virtual-list": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.14.2.tgz", + "integrity": "sha512-rA+W5xryhklJAcmswNyuKB3ZGeB855io+yOFQK5u/RXhjdshGblfKpNkQr4/9fBhZns0+uiL/0/s6IP2krtSmg==", + "dependencies": { + "@babel/runtime": "^7.20.0", + "classnames": "^2.2.6", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.36.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", @@ -6842,6 +7747,11 @@ "jsesc": "bin/jsesc" } }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -7010,6 +7920,14 @@ "loose-envify": "^1.1.0" } }, + "node_modules/scroll-into-view-if-needed": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", + "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", + "dependencies": { + "compute-scroll-into-view": "^3.0.2" + } + }, "node_modules/semver": { "version": "7.6.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", @@ -7139,6 +8057,11 @@ "node": ">=10.0.0" } }, + "node_modules/string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==" + }, "node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", @@ -7347,6 +8270,11 @@ } } }, + "node_modules/stylis": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz", + "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==" + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -7502,6 +8430,14 @@ "node": ">=0.8" } }, + "node_modules/throttle-debounce": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.0.tgz", + "integrity": "sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==", + "engines": { + "node": ">=12.22" + } + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -7522,6 +8458,11 @@ "node": ">=8.0" } }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" + }, "node_modules/ts-api-utils": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", @@ -7807,6 +8748,14 @@ "punycode": "^2.1.0" } }, + "node_modules/use-sync-external-store": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", + "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -7818,6 +8767,31 @@ "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" }, + "node_modules/valtio": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/valtio/-/valtio-1.13.2.tgz", + "integrity": "sha512-Qik0o+DSy741TmkqmRfjq+0xpZBXi/Y6+fXZLn0xNF1z/waFMbE3rkivv5Zcf9RrMUp6zswf2J7sbh2KBlba5A==", + "dependencies": { + "derive-valtio": "0.1.0", + "proxy-compare": "2.6.0", + "use-sync-external-store": "1.2.0" + }, + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + } + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 46cd3e2..6bacad6 100644 --- a/package.json +++ b/package.json @@ -7,16 +7,20 @@ "build": "next build", "dev": "next dev", "lint": "next lint", - "start": "next start" + "start": "next start", + "autogen": "node --loader ts-node/esm autogen.ts" }, "dependencies": { + "@ant-design/cssinjs": "^1.20.0", "@svgr/webpack": "^8.1.0", "@t3-oss/env-nextjs": "^0.10.1", + "antd": "^5.18.0", "geist": "^1.3.0", "next": "^14.2.1", "react": "^18.3.0", "react-dom": "^18.3.0", "ts-node": "^10.9.2", + "valtio": "^1.13.2", "zod": "^3.23.3" }, "devDependencies": { diff --git a/prettier.config.js b/prettier.config.js index b2d59b4..f68681b 100644 --- a/prettier.config.js +++ b/prettier.config.js @@ -1,6 +1,38 @@ /** @type {import('prettier').Config & import('prettier-plugin-tailwindcss').PluginOptions} */ const config = { plugins: ["prettier-plugin-tailwindcss"], + jsxSingleQuote: true, + arrowParens: "always", + bracketSameLine: false, + bracketSpacing: true, + configPath: "", + disableLanguages: [], + documentSelectors: [], + embeddedLanguageFormatting: "auto", + enable: true, + enableDebugLogs: false, + endOfLine: "lf", + htmlWhitespaceSensitivity: "css", + ignorePath: ".prettierignore", + insertPragma: false, + jsxBracketSameLine: false, + packageManager: "npm", + prettierPath: "", + printWidth: 80, + proseWrap: "preserve", + quoteProps: "as-needed", + requireConfig: false, + requirePragma: false, + resolveGlobalModules: false, + semi: true, + singleAttributePerLine: false, + singleQuote: false, + tabWidth: 2, + trailingComma: "es5", + useEditorConfig: true, + useTabs: false, + vueIndentScriptAndStyle: false, + withNodeModules: false, }; export default config; diff --git a/public/svgs/arrowLeft.svg b/public/svgs/arrowLeft.svg index 3619f4c..0e3b890 100644 --- a/public/svgs/arrowLeft.svg +++ b/public/svgs/arrowLeft.svg @@ -1,4 +1,4 @@ - diff --git a/src/app/empty/container/EmptyContainer.tsx b/src/app/empty/container/EmptyContainer.tsx deleted file mode 100644 index 42ccc4b..0000000 --- a/src/app/empty/container/EmptyContainer.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { EmptyTemplate } from "~/components/Templates/Empty/EmptyTemplate"; - -export const EmptyContainer = () => { - const emptyTemplateProps: React.ComponentProps = { - emptyFirstModuleProps: { title: "EmptyFirstModule" }, - emptySecontModuleProps: { title: "EmptySecontModule" }, - emptyThirdModuleProps: { title: "EmptyThirdModule" }, - }; - - return ; -}; diff --git a/src/app/globalLayout.tsx b/src/app/globalLayout.tsx new file mode 100644 index 0000000..c93b8ff --- /dev/null +++ b/src/app/globalLayout.tsx @@ -0,0 +1,23 @@ +"use client"; + +import SnapshotModal from "~/components/Atoms/Modal/SnapshotModal"; +import { RootStyleRegistry } from "./RootStyleRegistry"; +import SnapshotDrawerAtom from "~/components/Atoms/DrawerAtom/SnapshotDrawerAtom"; +import { SnapshotToastAtom } from "~/components/Atoms/ToastAtom/SnapshotToastAtom"; + +export default function GlobalLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + <> +
+ {children} +
+ + + + + ); +} diff --git a/src/app/home/container/HomeContainer.tsx b/src/app/home/container/HomeContainer.tsx deleted file mode 100644 index e7bfe39..0000000 --- a/src/app/home/container/HomeContainer.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { HomeTemplate } from "~/components/Templates/Home/HomeTemplate"; - -export const HomeContainer = () => { - const homeTemplateProps: React.ComponentProps = { - homeHeaderModuleProps: { title: "HomeHeaderModule" }, - homeContentModuleProps: { - title: "HomeContentModule", - sampleLinks: ["/empty", "/pageWithModal"], - sampleNumbers: Array.from({ length: 100 }, (_, i) => i + 1), - }, - homeFooterModuleProps: { title: "HomeFooterModule" }, - }; - - return ; -}; diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 6245b11..3a8a114 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,7 +1,7 @@ import "~/styles/globals.css"; import { GeistSans } from "geist/font/sans"; -import { RootStyleRegistry } from "./RootStyleRegistry"; +import GlobalLayout from "./globalLayout"; export const metadata = { title: "Frontend Sample", @@ -18,7 +18,9 @@ export default function RootLayout({
- {children} + {children} +
+
diff --git a/src/app/sample/empty/container/EmptyContainer.tsx b/src/app/sample/empty/container/EmptyContainer.tsx new file mode 100644 index 0000000..53ee966 --- /dev/null +++ b/src/app/sample/empty/container/EmptyContainer.tsx @@ -0,0 +1,30 @@ +"use client"; +import { useRouter } from "next/navigation"; +import { EmptyTemplate } from "~/components/Templates/Empty/EmptyTemplate"; + +export const EmptyContainer = () => { + const router = useRouter(); + + const emptyTemplateProps: React.ComponentProps = { + emptyHeaderModuleProps: { + headerProps: { + title: "Empty", + onClickLeftIcon: () => { + console.log("Left icon clicked"); + router.back(); + }, + onClickRightIcon: () => console.log("Right icon clicked"), + }, + }, + emptyContentModuleProps: { + moduleProps: "Empty Content Module", + componentProps: { title: "EmptyContentComponent" }, + atomProps: { title: "EmptyContentAtom" }, + }, + emptyFooterModuleProps: { + footerProps: { title: "EmptyFooterModule" }, + }, + }; + + return ; +}; diff --git a/src/app/empty/page.tsx b/src/app/sample/empty/page.tsx similarity index 100% rename from src/app/empty/page.tsx rename to src/app/sample/empty/page.tsx diff --git a/src/app/sample/home/container/HomeContainer.tsx b/src/app/sample/home/container/HomeContainer.tsx new file mode 100644 index 0000000..205dda8 --- /dev/null +++ b/src/app/sample/home/container/HomeContainer.tsx @@ -0,0 +1,34 @@ +import { message } from "antd"; +import { HomeTemplate } from "~/components/Templates/Home/HomeTemplate"; + +export const HomeContainer = () => { + const headerLeftIconClicked = () => { + void message.info("can't go back"); + }; + + const headerRightIconClicked = () => { + void message.info("can't go Settings"); + }; + + const homeTemplateProps: React.ComponentProps = { + homeHeaderModuleProps: { + headerProps: { + title: "Sample Home", + onClickLeftIcon: headerLeftIconClicked, + onClickRightIcon: headerRightIconClicked, + }, + }, + homeContentModuleProps: { + sampleLinks: [ + "/sample/empty", + "/sample/pageWithModal", + "/sample/pageWithDrawer", + "/sample/pageWithToast", + "/sample/pageWithForm", + ], + }, + homeFooterModuleProps: { title: "HomeFooterModule" }, + }; + + return ; +}; diff --git a/src/app/home/page.tsx b/src/app/sample/home/page.tsx similarity index 100% rename from src/app/home/page.tsx rename to src/app/sample/home/page.tsx diff --git a/src/app/sample/pageWithDrawer/container/PageWithDrawerContainer.tsx b/src/app/sample/pageWithDrawer/container/PageWithDrawerContainer.tsx new file mode 100644 index 0000000..6fea1e3 --- /dev/null +++ b/src/app/sample/pageWithDrawer/container/PageWithDrawerContainer.tsx @@ -0,0 +1,37 @@ +import { useState } from "react"; +import { PageWithDrawerTemplate } from "~/components/Templates/PageWithDrawer/PageWithDrawerTemplate"; +import DrawerStore from "~/store/DrawerStore"; + +export const PageWithDrawerContainer = () => { + const [isDrawerOpen, setIsDrawerOpen] = useState(false); + + const pagewithdrawerTemplateProps: React.ComponentProps< + typeof PageWithDrawerTemplate + > = { + pageWithDrawerHeaderModuleProps: { + headerProps: { + title: "PageWithDrawerHeaderModule", + }, + }, + pageWithDrawerExamplesModuleProps: { + onOpenSnapshotDrawer: () => { + DrawerStore.open("TitleAndContent", { + TitleAndContent: { + title: "Snapshot Drawer Title", + description: "Snapshot Drawer Description", + }, + }); + }, + drawerProps: { + drawerProps: { + isDrawerOpen, + setIsDrawerOpen, + }, + title: "Drawer Title", + description: "Drawer Description", + }, + }, + }; + + return ; +}; diff --git a/src/app/sample/pageWithDrawer/page.tsx b/src/app/sample/pageWithDrawer/page.tsx new file mode 100644 index 0000000..053972d --- /dev/null +++ b/src/app/sample/pageWithDrawer/page.tsx @@ -0,0 +1,8 @@ +"use client"; +import { PageWithDrawerContainer } from "./container/PageWithDrawerContainer"; + +const PageWithDrawer = () => { + return ; +}; + +export default PageWithDrawer; diff --git a/src/app/sample/pageWithForm/container/PageWithFormContainer.tsx b/src/app/sample/pageWithForm/container/PageWithFormContainer.tsx new file mode 100644 index 0000000..ad0587a --- /dev/null +++ b/src/app/sample/pageWithForm/container/PageWithFormContainer.tsx @@ -0,0 +1,22 @@ +import { useRouter } from "next/navigation"; +import { useState } from "react"; +import { PageWithFormTemplate } from "~/components/Templates/PageWithForm/PageWithFormTemplate"; + +export const PageWithFormContainer = () => { + const router = useRouter(); + const [formData, setFormData] = useState({}); + + const pagewithformTemplateProps: React.ComponentProps< + typeof PageWithFormTemplate + > = { + pageWithFormHeaderModuleProps: { + title: "PageWithFormHeaderModule", + onClickLeftIcon: () => router.back(), + }, + pageWithFormFormModuleProps: { + setFormData, + }, + }; + + return ; +}; diff --git a/src/app/sample/pageWithForm/page.tsx b/src/app/sample/pageWithForm/page.tsx new file mode 100644 index 0000000..a6d515a --- /dev/null +++ b/src/app/sample/pageWithForm/page.tsx @@ -0,0 +1,8 @@ +"use client"; +import { PageWithFormContainer } from "./container/PageWithFormContainer"; + +const PageWithForm = () => { + return ; +}; + +export default PageWithForm; diff --git a/src/app/sample/pageWithModal/container/PageWithModalContainer.tsx b/src/app/sample/pageWithModal/container/PageWithModalContainer.tsx new file mode 100644 index 0000000..9480f14 --- /dev/null +++ b/src/app/sample/pageWithModal/container/PageWithModalContainer.tsx @@ -0,0 +1,37 @@ +import { useRouter } from "next/navigation"; +import { useState } from "react"; +import { PageWithModalTemplate } from "~/components/Templates/PageWithModal/PageWithModalTemplate"; +import ModalStore from "~/store/ModalStore"; + +export const PageWithModalContainer = () => { + const router = useRouter(); + const [isCustomModalOpen, setIsCustomModalOpen] = useState(false); + + const pagewithmodalTemplateProps: React.ComponentProps< + typeof PageWithModalTemplate + > = { + pageWithModalHeaderModuleProps: { + title: "PageWithModalHeaderModule", + onClickLeftIcon: () => router.back(), + }, + pageWithModalContentModuleProps: { + onOpenSnapshotModal: () => + ModalStore.open("TitleAndContent", { + TitleAndContent: { + title: "Modal Title", + description: "Modal Content", + }, + }), + modalProps: { + modalProps: { + isModalOpen: isCustomModalOpen, + setModalOpen: setIsCustomModalOpen, + }, + title: "Custom Modal Title", + description: "Custom Modal Description", + }, + }, + }; + + return ; +}; diff --git a/src/app/sample/pageWithModal/page.tsx b/src/app/sample/pageWithModal/page.tsx new file mode 100644 index 0000000..e8690ea --- /dev/null +++ b/src/app/sample/pageWithModal/page.tsx @@ -0,0 +1,8 @@ +"use client"; +import { PageWithModalContainer } from "./container/PageWithModalContainer"; + +const PageWithModal = () => { + return ; +}; + +export default PageWithModal; diff --git a/src/app/sample/pageWithToast/container/PageWithToastContainer.tsx b/src/app/sample/pageWithToast/container/PageWithToastContainer.tsx new file mode 100644 index 0000000..983eea0 --- /dev/null +++ b/src/app/sample/pageWithToast/container/PageWithToastContainer.tsx @@ -0,0 +1,27 @@ +"use client"; + +import { useRouter } from "next/navigation"; +import { PageWithToastTemplate } from "~/components/Templates/PageWithToast/PageWithToastTemplate"; +import ToastStore from "~/store/ToastStore"; + +export const PageWithToastContainer = () => { + const router = useRouter(); + + const pagewithtoastTemplateProps: React.ComponentProps< + typeof PageWithToastTemplate + > = { + pageWithToastHeaderModuleProps: { + headerProps: { + title: "PageWithToastHeaderModule", + onClickLeftIcon: () => router.back(), + }, + }, + pageWithToastExampleModuleProps: { + onClickToastButton: () => { + ToastStore.info("This is a toast message."); + }, + }, + }; + + return ; +}; diff --git a/src/app/sample/pageWithToast/page.tsx b/src/app/sample/pageWithToast/page.tsx new file mode 100644 index 0000000..be2106f --- /dev/null +++ b/src/app/sample/pageWithToast/page.tsx @@ -0,0 +1,8 @@ +"use client"; +import { PageWithToastContainer } from "./container/PageWithToastContainer"; + +const PageWithToast = () => { + return ; +}; + +export default PageWithToast; diff --git a/src/components/Atoms/DrawerAtom/DrawerAtom.tsx b/src/components/Atoms/DrawerAtom/DrawerAtom.tsx new file mode 100644 index 0000000..506ed56 --- /dev/null +++ b/src/components/Atoms/DrawerAtom/DrawerAtom.tsx @@ -0,0 +1,83 @@ +import { + memo, + type PropsWithChildren, + useCallback, + useEffect, + useRef, + useState, +} from "react"; +import ReactDOM from "react-dom"; +import { DrawerContainerAtom } from "../DrawerContainerAtom/DrawerContainerAtom"; + +type Props = { + isDrawerOpen: boolean; + setIsDrawerOpen: (value: boolean) => void; + containerClassName?: string; +}; + +const DrawerAtom = (props: PropsWithChildren) => { + const [modalContainer, setModalContainer] = useState( + null, + ); + const [isAnimating, setIsAnimating] = useState(false); + const wasOpenRef = useRef(props.isDrawerOpen); + + const onClose = useCallback(() => { + props.setIsDrawerOpen(false); + setIsAnimating(true); + }, []); + + useEffect(() => { + const container = document.createElement("div"); + const modalRoot = document.getElementById("custom-drawer"); + if (modalRoot) { + modalRoot?.appendChild(container); + setModalContainer(container); + } + + return () => { + if (modalRoot) { + modalRoot?.removeChild(container); + } + }; + }, []); + + useEffect(() => { + if (wasOpenRef.current !== props.isDrawerOpen) { + if (props.isDrawerOpen) { + setIsAnimating(false); + } else { + setIsAnimating(true); + const timeoutId = setTimeout(() => { + setIsAnimating(false); + }, 300); + return () => clearTimeout(timeoutId); + } + } + wasOpenRef.current = props.isDrawerOpen; + }, [props.isDrawerOpen]); + + return ( + modalContainer && + (props.isDrawerOpen || isAnimating) && + ReactDOM.createPortal( + <> +
+
onClose()} + /> + + {props.children} + +
+ , + modalContainer, + ) + ); +}; + +export default memo(DrawerAtom); diff --git a/src/components/Atoms/DrawerAtom/SnapshotDrawerAtom.tsx b/src/components/Atoms/DrawerAtom/SnapshotDrawerAtom.tsx new file mode 100644 index 0000000..4961ccd --- /dev/null +++ b/src/components/Atoms/DrawerAtom/SnapshotDrawerAtom.tsx @@ -0,0 +1,53 @@ +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { useSnapshot } from "valtio"; +import DrawerStore from "~/store/DrawerStore"; +import { TitleAndContentDrawer } from "~/views/drawer/TitleAndContentDrawer"; + +export default function SnapshotDrawerAtom() { + const { open, view } = useSnapshot(DrawerStore.state); + const [isAnimating, setIsAnimating] = useState(false); + const wasOpenRef = useRef(open); + + const onClose = useCallback(() => { + DrawerStore.close(); + setIsAnimating(true); + }, []); + + useEffect(() => { + if (wasOpenRef.current !== open) { + if (open) { + setIsAnimating(false); + } else { + setIsAnimating(true); + const timeoutId = setTimeout(() => { + setIsAnimating(false); + }, 300); + return () => clearTimeout(timeoutId); + } + } + wasOpenRef.current = open; + }, [open]); + + const componentView = useMemo(() => { + switch (view) { + case "TitleAndContent": + return ; + default: + return null; + } + }, [view]); + + return ( + <> + {open || isAnimating ? ( +
+
onClose()} + /> + {componentView} +
+ ) : null} + + ); +} diff --git a/src/components/Atoms/DrawerContainerAtom/DrawerContainerAtom.tsx b/src/components/Atoms/DrawerContainerAtom/DrawerContainerAtom.tsx new file mode 100644 index 0000000..b64eb9e --- /dev/null +++ b/src/components/Atoms/DrawerContainerAtom/DrawerContainerAtom.tsx @@ -0,0 +1,21 @@ +import cn from "classnames"; +import { type PropsWithChildren } from "react"; + +type Props = { + isOpen: boolean; + style?: React.CSSProperties; + className?: string; +}; + +export const DrawerContainerAtom = (props: PropsWithChildren) => { + return ( +
+ {props.children} +
+ ); +}; diff --git a/src/components/Atoms/EmptyContentAtom/EmptyContentAtom.tsx b/src/components/Atoms/EmptyContentAtom/EmptyContentAtom.tsx new file mode 100644 index 0000000..6000fbe --- /dev/null +++ b/src/components/Atoms/EmptyContentAtom/EmptyContentAtom.tsx @@ -0,0 +1,7 @@ +type Props = { + // Add props here + }; + +export const EmptyContentAtom = (props: Props) => { + return (
EmptyContentAtom
); +}; \ No newline at end of file diff --git a/src/components/Atoms/HeaderAtom/HeaderAtom.tsx b/src/components/Atoms/HeaderAtom/HeaderAtom.tsx index b73624a..414c1a8 100644 --- a/src/components/Atoms/HeaderAtom/HeaderAtom.tsx +++ b/src/components/Atoms/HeaderAtom/HeaderAtom.tsx @@ -1,31 +1,36 @@ import { SettingOutlined } from "@ant-design/icons"; import SVGAtom from "../SVGAtom/SVGAtom"; -import { Header } from "antd/es/layout/layout"; type Props = { title: string; + onClickLeftIcon?: () => void; + onClickRightIcon?: () => void; }; export const HeaderAtom = (props: Props) => { return ( -
+
{/* Sample using custom svg */} -
console.log("svg clicked")} - > - -
+ {props.onClickLeftIcon && ( +
+ +
+ )} -
{props.title}
+
{props.title}
{/* Sample using Antd icon */} -
console.log("Antd icon clicked")} - > - -
+ {props.onClickRightIcon && ( +
console.log("Antd icon clicked")} + > + +
+ )}
); }; diff --git a/src/components/Atoms/Modal/Modal.tsx b/src/components/Atoms/Modal/Modal.tsx new file mode 100644 index 0000000..b5dbaf8 --- /dev/null +++ b/src/components/Atoms/Modal/Modal.tsx @@ -0,0 +1,64 @@ +import { + memo, + type PropsWithChildren, + useCallback, + useEffect, + useState, +} from "react"; +import ReactDOM from "react-dom"; +import { ModalContainer } from "../ModalContainer/ModalContainer"; + +type Props = { + isModalOpen: boolean; + setModalOpen: (value: boolean) => void; + containerClassName?: string; +}; + +const Modal = (props: PropsWithChildren) => { + const [modalContainer, setModalContainer] = useState( + null, + ); + + useEffect(() => { + const container = document.createElement("div"); + const modalRoot = document.getElementById("custom-modal"); + if (modalRoot) { + modalRoot?.appendChild(container); + setModalContainer(container); + } + + return () => { + if (modalRoot) { + modalRoot?.removeChild(container); + } + }; + }, []); + + const onClose = useCallback(() => { + if (props.isModalOpen) { + props.setModalOpen(false); + } + }, [props.isModalOpen]); + + return ( + modalContainer && + ReactDOM.createPortal( + <> + {props.isModalOpen ? ( +
+
+ + {props.children} + +
+ ) : null} + , + modalContainer, + ) + ); +}; + +export default memo(Modal); diff --git a/src/components/Atoms/Modal/SnapshotModal.tsx b/src/components/Atoms/Modal/SnapshotModal.tsx new file mode 100644 index 0000000..44ddd07 --- /dev/null +++ b/src/components/Atoms/Modal/SnapshotModal.tsx @@ -0,0 +1,37 @@ +import { useCallback, useMemo } from "react"; +import { useSnapshot } from "valtio"; +import ModalStore from "~/store/ModalStore"; +import { TitleAndContentModal } from "~/views/modal/TitleAndContentModal"; + +export default function SnapshotModal() { + const { open, view } = useSnapshot(ModalStore.state); + + const onClose = useCallback(() => { + if (open) { + ModalStore.close(); + } + }, [open]); + + const componentView = useMemo(() => { + switch (view) { + case "TitleAndContent": + return ; + default: + return null; + } + }, [view]); + + return ( + <> + {open ? ( +
+
+ {componentView} +
+ ) : null} + + ); +} diff --git a/src/components/Atoms/ModalContainer/ModalContainer.tsx b/src/components/Atoms/ModalContainer/ModalContainer.tsx new file mode 100644 index 0000000..4f9a392 --- /dev/null +++ b/src/components/Atoms/ModalContainer/ModalContainer.tsx @@ -0,0 +1,21 @@ +import cn from "classnames"; +import { type PropsWithChildren } from "react"; + +type Props = { + style?: React.CSSProperties; + className?: string; +}; + +export const ModalContainer = (props: PropsWithChildren) => { + return ( +
+ {props.children} +
+ ); +}; diff --git a/src/components/Atoms/SVGAtom/SVGAtom.tsx b/src/components/Atoms/SVGAtom/SVGAtom.tsx index 656c783..039c94e 100644 --- a/src/components/Atoms/SVGAtom/SVGAtom.tsx +++ b/src/components/Atoms/SVGAtom/SVGAtom.tsx @@ -12,7 +12,6 @@ type Props = { }; const SVGAtom = (props: Props) => { - console.log(svgs); return React.createElement(svgs[props.iconName], { width: props.width ?? null, height: props.height ?? null, diff --git a/src/components/Atoms/ToastAtom/SnapshotToastAtom.tsx b/src/components/Atoms/ToastAtom/SnapshotToastAtom.tsx new file mode 100644 index 0000000..2419c96 --- /dev/null +++ b/src/components/Atoms/ToastAtom/SnapshotToastAtom.tsx @@ -0,0 +1,29 @@ +import { useMemo } from "react"; +import { useSnapshot } from "valtio"; +import ToastStore from "~/store/ToastStore"; +import { InfoToast } from "~/views/toast/InfoToast"; + +export const SnapshotToastAtom = () => { + const { queue } = useSnapshot(ToastStore.state); + + const renderToastList = useMemo(() => { + return queue.map((toast, index) => { + switch (toast.view) { + case "info": + return ; + default: + return null; + } + }); + }, [queue]); + + return ( + <> + {queue.length === 0 ? null : ( +
+ {renderToastList} +
+ )} + + ); +}; diff --git a/src/components/Components/EmptyContentComponent/EmptyContentComponent.tsx b/src/components/Components/EmptyContentComponent/EmptyContentComponent.tsx new file mode 100644 index 0000000..0c36994 --- /dev/null +++ b/src/components/Components/EmptyContentComponent/EmptyContentComponent.tsx @@ -0,0 +1,7 @@ +type Props = { + // Add props here + }; + +export const EmptyContentComponent = (props: Props) => { + return (
EmptyContentComponent
); +}; \ No newline at end of file diff --git a/src/components/Components/LinkList/LinkList.tsx b/src/components/Components/LinkList/LinkList.tsx index 7e31a7e..1a35afe 100644 --- a/src/components/Components/LinkList/LinkList.tsx +++ b/src/components/Components/LinkList/LinkList.tsx @@ -7,7 +7,7 @@ type Props = { export const LinkList = (props: Props) => { return (
- [Links] + [Sample Pages] {props.links.map((link) => (
{link} diff --git a/src/components/Components/NumberList/NumberList.tsx b/src/components/Components/NumberList/NumberList.tsx index 16f2a7f..e2cbb7b 100644 --- a/src/components/Components/NumberList/NumberList.tsx +++ b/src/components/Components/NumberList/NumberList.tsx @@ -3,5 +3,12 @@ type Props = { }; export const NumberList = (props: Props) => { - return props.numbers.map((number) =>
{number}
); + return ( +
+ [Numbers] + {props.numbers.map((number) => ( +
{number}
+ ))} +
+ ); }; diff --git a/src/components/Components/PageWithDrawerExamplesDrawer/PageWithDrawerExamplesDrawer.tsx b/src/components/Components/PageWithDrawerExamplesDrawer/PageWithDrawerExamplesDrawer.tsx new file mode 100644 index 0000000..22c2e4e --- /dev/null +++ b/src/components/Components/PageWithDrawerExamplesDrawer/PageWithDrawerExamplesDrawer.tsx @@ -0,0 +1,22 @@ +import { Button } from "antd"; +import DrawerAtom from "~/components/Atoms/DrawerAtom/DrawerAtom"; + +type Props = { + drawerProps: React.ComponentProps; + title: string; + description: string; +}; + +export const PageWithDrawerExamplesDrawer = (props: Props) => { + return ( + +
+

{props.title}

+

{props.description}

+ +
+
+ ); +}; diff --git a/src/components/Components/PageWithModalContentCustomModal/PageWithModalContentCustomModal.tsx b/src/components/Components/PageWithModalContentCustomModal/PageWithModalContentCustomModal.tsx new file mode 100644 index 0000000..edd9a9b --- /dev/null +++ b/src/components/Components/PageWithModalContentCustomModal/PageWithModalContentCustomModal.tsx @@ -0,0 +1,22 @@ +import { Button } from "antd"; +import Modal from "~/components/Atoms/Modal/Modal"; + +type Props = { + modalProps: React.ComponentProps; + title: string; + description: string; +}; + +export const PageWithModalContentCustomModal = (props: Props) => { + return ( + +
+

{props.title}

+

{props.description}

+ +
+
+ ); +}; diff --git a/src/components/Modules/Empty/EmptyContentModule.tsx b/src/components/Modules/Empty/EmptyContentModule.tsx new file mode 100644 index 0000000..d3d5bd1 --- /dev/null +++ b/src/components/Modules/Empty/EmptyContentModule.tsx @@ -0,0 +1,18 @@ +import { EmptyContentAtom } from "~/components/Atoms/EmptyContentAtom/EmptyContentAtom"; +import { EmptyContentComponent } from "~/components/Components/EmptyContentComponent/EmptyContentComponent"; + +type Props = { + moduleProps: string; + componentProps: React.ComponentProps; + atomProps: React.ComponentProps; +}; + +export const EmptyContentModule = (props: Props) => { + return ( +
+

{props.moduleProps}

+ + +
+ ); +}; diff --git a/src/components/Modules/Empty/EmptyFirstModule.tsx b/src/components/Modules/Empty/EmptyFirstModule.tsx deleted file mode 100644 index f1043be..0000000 --- a/src/components/Modules/Empty/EmptyFirstModule.tsx +++ /dev/null @@ -1,7 +0,0 @@ -type Props = { - title: string; -}; - -export const EmptyFirstModule = (props: Props) => { - return
{props.title}
; -}; diff --git a/src/components/Modules/Empty/EmptyFooterModule.tsx b/src/components/Modules/Empty/EmptyFooterModule.tsx new file mode 100644 index 0000000..9084931 --- /dev/null +++ b/src/components/Modules/Empty/EmptyFooterModule.tsx @@ -0,0 +1,9 @@ +import { FooterAtom } from "~/components/Atoms/FooterAtom/FooterAtom"; + +type Props = { + footerProps: React.ComponentProps; +}; + +export const EmptyFooterModule = (props: Props) => { + return ; +}; diff --git a/src/components/Modules/Empty/EmptyHeaderModule.tsx b/src/components/Modules/Empty/EmptyHeaderModule.tsx new file mode 100644 index 0000000..16b48f3 --- /dev/null +++ b/src/components/Modules/Empty/EmptyHeaderModule.tsx @@ -0,0 +1,9 @@ +import { HeaderAtom } from "~/components/Atoms/HeaderAtom/HeaderAtom"; + +type Props = { + headerProps: React.ComponentProps; +}; + +export const EmptyHeaderModule = (props: Props) => { + return ; +}; diff --git a/src/components/Modules/Empty/EmptySecontModule.tsx b/src/components/Modules/Empty/EmptySecontModule.tsx deleted file mode 100644 index a6850b3..0000000 --- a/src/components/Modules/Empty/EmptySecontModule.tsx +++ /dev/null @@ -1,7 +0,0 @@ -type Props = { - title: string; -}; - -export const EmptySecontModule = (props: Props) => { - return
{props.title}
; -}; diff --git a/src/components/Modules/Empty/EmptyThirdModule.tsx b/src/components/Modules/Empty/EmptyThirdModule.tsx deleted file mode 100644 index 72dc8a1..0000000 --- a/src/components/Modules/Empty/EmptyThirdModule.tsx +++ /dev/null @@ -1,7 +0,0 @@ -type Props = { - title: string; -}; - -export const EmptyThirdModule = (props: Props) => { - return
{props.title}
; -}; diff --git a/src/components/Modules/Home/HomeContentModule.tsx b/src/components/Modules/Home/HomeContentModule.tsx index dc05ef6..c6e8de5 100644 --- a/src/components/Modules/Home/HomeContentModule.tsx +++ b/src/components/Modules/Home/HomeContentModule.tsx @@ -1,22 +1,13 @@ import { LinkList } from "~/components/Components/LinkList/LinkList"; -import { NumberList } from "~/components/Components/NumberList/NumberList"; type Props = { - title: string; sampleLinks: string[]; - sampleNumbers: number[]; }; export const HomeContentModule = (props: Props) => { return ( -
-
{props.title}
- -
- -
- - +
+
); }; diff --git a/src/components/Modules/Home/HomeHeaderModule.tsx b/src/components/Modules/Home/HomeHeaderModule.tsx index 17ddec9..f81e17c 100644 --- a/src/components/Modules/Home/HomeHeaderModule.tsx +++ b/src/components/Modules/Home/HomeHeaderModule.tsx @@ -1,9 +1,9 @@ import { HeaderAtom } from "~/components/Atoms/HeaderAtom/HeaderAtom"; type Props = { - title: string; + headerProps: React.ComponentProps; }; export const HomeHeaderModule = (props: Props) => { - return ; + return ; }; diff --git a/src/components/Modules/HomeDescription/HomeDescriptionModule.tsx b/src/components/Modules/HomeDescription/HomeDescriptionModule.tsx new file mode 100644 index 0000000..9a68f3a --- /dev/null +++ b/src/components/Modules/HomeDescription/HomeDescriptionModule.tsx @@ -0,0 +1,74 @@ +export const HomeDescriptionModule = () => { + return ( +
+ {/* + 우리가 해외 개발자에게 원하는 최소 능력 + 1. 우리의 페이지 구성 규칙을 이해하고, 이 규칙을 따라 요청 페이지를 제작하는 것 + 2. 페이지 내부의 구성 요소들 중 변동성이 있는 요소 혹은 비즈니스 로직이 들어가는 요소를 Container에서 핸들링 할 수 있게 하는 것 + 3. 각 코드파일 별 convention을 지키는 것 + 4. Sample Link를 통해 보여준 기초 컴포넌트들을 이해하고 사용할 수 있는 것 + 우리가 해외 개발자에게 원하는 최대 능력 + 1. 우리의 페이지 구성 규칙의 미흡함을 발견하고, 이를 개선하여 결과물에 반영하는 것(이 경우 주석을 통한 설명을 작성해야 함) + 2. Sample 코드에서 제공하는 기초 컴포넌트의 미흡함을 발견하고, 이를 개선하여 결과물에 반영하는 것(이 경우 주석을 통한 설명을 작성해야 함) + 예시 페이지들의 역할 간단 설명 + 1. Empty: 페이지 구성 규칙, props 사용 규칙, 기초 layout을 확인할 수 있는 페이지 + 2. PageWithModal: 기초 컴포넌트인 Modal 컴포넌트의 사용법을 확인할 수 있는 페이지 + 3. PageWithForm: 기초 컴포넌트인 Form 컴포넌트의 사용법을 확인할 수 있는 페이지 + + translate korean description to English and make markdown + */} +
+ Simple explanation of the roles of sample pages +
    +
  1. + Empty: A page where you can check the page configuration rules, prop + usage rules, and basic layout +
  2. +
  3. + PageWithModal: A page where you can check how to use the basic + component, Modal component +
  4. +
  5. + PageWithForm: A page where you can check how to use the basic + component, Form component +
  6. +
+
+ +
+ Minimum ability we want from developers +
    +
  1. + Understanding our page configuration rules and creating a requested + page following these rules +
  2. +
  3. + Handling volatile elements or elements containing business logic in + the *Container.tsx file +
  4. +
  5. Following the convention for each code file
  6. +
  7. + Understanding and using basic components shown through the Sample + Link +
  8. +
+
+ +
+ Maximum ability we want from developers +
    +
  1. + Finding the inadequacies of our page configuration rules and + improving them to reflect the results (In this case, you must write + an explanation through comments) +
  2. +
  3. + Finding the inadequacies of the basic components provided in the + Sample code and improving them to reflect the results (In this case, + you must write an explanation through comments) +
  4. +
+
+
+ ); +}; diff --git a/src/components/Modules/PageWithDrawer/PageWithDrawerDescriptionModule.tsx b/src/components/Modules/PageWithDrawer/PageWithDrawerDescriptionModule.tsx new file mode 100644 index 0000000..e24c874 --- /dev/null +++ b/src/components/Modules/PageWithDrawer/PageWithDrawerDescriptionModule.tsx @@ -0,0 +1,38 @@ +export const PageWithDrawerDescriptionModule = () => { + return ( +
+ Drawer Components + {/* + 다양한 상황에서 사용하기 위해 Ant Design의 Drawer 컴포넌트가 아닌 커스텀 모달 컴포넌트를 만들어 사용합니다 + 만들어진 컴포넌트를 재사용하거나 보강하여 사용하면 됩니다 + + - SnapshotDrawer: Drawer 내부에 들어가는 요소들이 정적이거나 반복되는 경우 사용하는 모달, views/drawer 폴더에 사전 지정하여 사용 + - Drawer: 동적인 상태처리가 필요한 경우 사용하는 컴포넌트, 각 페이지 내부에서 정의하여 사용 + + 위 두 가지 상황에서 사용할 수 있도록 컴포넌트를 분리해두었으니 + 컴포넌트를 보강하는 경우, 앞서 설명한 원칙이 위배되지 않는 선에서 진행해주세요 + + translate above description to English and make markdown + */} +

+ {`To use in various situations, create a custom Drawer component instead of the Ant Design Drawer component.\nYou can reuse the created component or enhance it for use.`} +

+ +
+
+ SnapshotDrawer +

+ {`Use when the elements inside the Drawer are static or repetitive, and predefine in the views/drawer folder for use.`} +

+
+ +
+ Drawer +

+ {`Use when dynamic state processing is required, define within each page for use.`} +

+
+
+
+ ); +}; diff --git a/src/components/Modules/PageWithDrawer/PageWithDrawerExamplesModule.tsx b/src/components/Modules/PageWithDrawer/PageWithDrawerExamplesModule.tsx new file mode 100644 index 0000000..18a734f --- /dev/null +++ b/src/components/Modules/PageWithDrawer/PageWithDrawerExamplesModule.tsx @@ -0,0 +1,34 @@ +import { Button } from "antd"; +import { PageWithDrawerExamplesDrawer } from "~/components/Components/PageWithDrawerExamplesDrawer/PageWithDrawerExamplesDrawer"; + +type Props = { + onOpenSnapshotDrawer: () => void; + drawerProps: React.ComponentProps; +}; + +export const PageWithDrawerExamplesModule = (props: Props) => { + return ( +
+
+ +
+ +
+ + +
+
+ ); +}; diff --git a/src/components/Modules/PageWithDrawer/PageWithDrawerHeaderModule.tsx b/src/components/Modules/PageWithDrawer/PageWithDrawerHeaderModule.tsx new file mode 100644 index 0000000..f390882 --- /dev/null +++ b/src/components/Modules/PageWithDrawer/PageWithDrawerHeaderModule.tsx @@ -0,0 +1,9 @@ +import { HeaderAtom } from "~/components/Atoms/HeaderAtom/HeaderAtom"; + +type Props = { + headerProps: React.ComponentProps; +}; + +export const PageWithDrawerHeaderModule = (props: Props) => { + return ; +}; diff --git a/src/components/Modules/PageWithForm/PageWithFormFormModule.tsx b/src/components/Modules/PageWithForm/PageWithFormFormModule.tsx new file mode 100644 index 0000000..d9607f6 --- /dev/null +++ b/src/components/Modules/PageWithForm/PageWithFormFormModule.tsx @@ -0,0 +1,119 @@ +import { + Form, + Radio, + Select, + TreeSelect, + Cascader, + DatePicker, + InputNumber, + Switch, + Button, + Slider, + ColorPicker, + Input, + message, +} from "antd"; +const { RangePicker } = DatePicker; +const { TextArea } = Input; + +type Props = { + setFormData: (data: any) => void; +}; + +export const PageWithFormFormModule = (props: Props) => { + const [form] = Form.useForm(); + + const onFinish = (values: any) => { + void message.info(JSON.stringify(values)); + }; + + return ( +
{ + props.setFormData((prevData: any) => + changedFields.reduce( + (acc, { name, value }) => ({ ...acc, [name[0]]: value }), + prevData, + ), + ); + }} + layout="horizontal" + style={{ maxWidth: 600 }} + onFinish={onFinish} + > + + + Apple + Pear + + + + + + + + + + + + + + + + + + + + + + + + +