From 4756752ff761b396a48b7d2605d2eee7a0381c6b Mon Sep 17 00:00:00 2001 From: eeseung Date: Wed, 28 Jun 2023 14:27:25 +0900 Subject: [PATCH 01/13] feat: init project --- .eslintrc.json | 15 + .gitignore | 4 + .prettierrc | 12 + index.html | 9 + package.json | 16 + src/App.js | 5 + src/DocumentList.js | 37 ++ src/main.js | 38 ++ yarn.lock | 1269 +++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 1405 insertions(+) create mode 100644 .eslintrc.json create mode 100644 .gitignore create mode 100644 .prettierrc create mode 100644 index.html create mode 100644 package.json create mode 100644 src/App.js create mode 100644 src/DocumentList.js create mode 100644 src/main.js create mode 100644 yarn.lock diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..a14a39d8 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,15 @@ +{ + "env": { + "browser": true, + "es2021": true + }, + "extends": ["airbnb-base", "prettier"], + "plugins": ["prettier"], + "parserOptions": { + "ecmaVersion": 12, + "sourceType": "module" + }, + "rules": { + "prettier/prettier": ["error"] + } +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..18dd99cd --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules +.DS_Store +.eslintcache +.vscode diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..025d8aed --- /dev/null +++ b/.prettierrc @@ -0,0 +1,12 @@ +{ + "printWidth": 120, + "tabWidth": 2, + "semi": true, + "singleQuote": true, + "quoteProps": "as-needed", + "trailingComma": "es5", + "bracketSpacing": true, + "endOfLine": "lf", + "useTabs": false, + "arrowParens": "always" +} diff --git a/index.html b/index.html new file mode 100644 index 00000000..a5c953d0 --- /dev/null +++ b/index.html @@ -0,0 +1,9 @@ + + + Notion + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 00000000..402a2d24 --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "name": "fedc4-5_project_notion_vanillajs", + "version": "1.0.0", + "main": "index.js", + "repository": "https://github.com/prgrms-fe-devcourse/FEDC4-5_Project_Notion_VanillaJS.git", + "author": "eeseung ", + "license": "MIT", + "devDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-config-airbnb-base": "^15.0.0", + "eslint-config-prettier": "^8.8.0", + "eslint-plugin-import": "^2.25.2", + "eslint-plugin-prettier": "^4.2.1", + "prettier": "2.8.8" + } +} diff --git a/src/App.js b/src/App.js new file mode 100644 index 00000000..1557c64b --- /dev/null +++ b/src/App.js @@ -0,0 +1,5 @@ +import DocumentList from './DocumentList.js'; + +export default function App({ $target, initialState }) { + new DocumentList({ $target, initialState }); +} diff --git a/src/DocumentList.js b/src/DocumentList.js new file mode 100644 index 00000000..c9620f75 --- /dev/null +++ b/src/DocumentList.js @@ -0,0 +1,37 @@ +export default function DocumentList({ $target, initialState }) { + const $documentList = document.createElement('div'); + + $target.appendChild($documentList); + + this.state = initialState; + + this.setState = (nextState) => { + this.state = nextState; + this.render(); + }; + + const renderDocuments = (documents) => { + return ` + + `; + }; + + this.render = () => { + $documentList.innerHTML = ` + ${renderDocuments(this.state)} + `; + }; + + this.render(); +} diff --git a/src/main.js b/src/main.js new file mode 100644 index 00000000..2ff3a8f3 --- /dev/null +++ b/src/main.js @@ -0,0 +1,38 @@ +import App from './App.js'; + +const $app = document.querySelector('#app'); + +const DUMMY_DATA = [ + { + id: 1, // Document id + title: '노션을 만들자', // Document title + documents: [ + { + id: 2, + title: '블라블라', + documents: [ + { + id: 3, + title: '함냐함냐', + documents: [], + }, + { + id: 5, + title: '흠냐흠냐', + documents: [], + }, + ], + }, + ], + }, + { + id: 4, + title: 'hello!', + documents: [], + }, +]; + +new App({ + $target: $app, + initialState: DUMMY_DATA, +}); diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000..1d57608c --- /dev/null +++ b/yarn.lock @@ -0,0 +1,1269 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@eslint-community/eslint-utils@^4.2.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.4.0": + version "4.5.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.1.tgz#cdd35dce4fa1a89a4fd42b1599eb35b3af408884" + integrity sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ== + +"@eslint/eslintrc@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.3.tgz#4910db5505f4d503f27774bf356e3704818a0331" + integrity sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.5.2" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@8.43.0": + version "8.43.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.43.0.tgz#559ca3d9ddbd6bf907ad524320a0d14b85586af0" + integrity sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg== + +"@humanwhocodes/config-array@^0.11.10": + version "0.11.10" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2" + integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.8.0: + version "8.9.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.9.0.tgz#78a16e3b2bcc198c10822786fa6679e245db5b59" + integrity sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ== + +ajv@^6.10.0, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + +array-includes@^3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f" + integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + get-intrinsic "^1.1.3" + is-string "^1.0.7" + +array.prototype.flat@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2" + integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" + +array.prototype.flatmap@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183" + integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + es-shim-unscopables "^1.0.0" + +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +confusing-browser-globals@^1.0.10: + version "1.0.11" + resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81" + integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA== + +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +debug@^4.1.1, debug@^4.3.2: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +es-abstract@^1.19.0, es-abstract@^1.20.4: + version "1.21.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" + integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== + dependencies: + array-buffer-byte-length "^1.0.0" + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.2.0" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.10" + is-weakref "^1.0.2" + object-inspect "^1.12.3" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.4.3" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.7" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.9" + +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + +es-shim-unscopables@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" + integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + dependencies: + has "^1.0.3" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-config-airbnb-base@^15.0.0: + version "15.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz#6b09add90ac79c2f8d723a2580e07f3925afd236" + integrity sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig== + dependencies: + confusing-browser-globals "^1.0.10" + object.assign "^4.1.2" + object.entries "^1.1.5" + semver "^6.3.0" + +eslint-config-prettier@^8.8.0: + version "8.8.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz#bfda738d412adc917fd7b038857110efe98c9348" + integrity sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA== + +eslint-import-resolver-node@^0.3.7: + version "0.3.7" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7" + integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA== + dependencies: + debug "^3.2.7" + is-core-module "^2.11.0" + resolve "^1.22.1" + +eslint-module-utils@^2.7.4: + version "2.8.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49" + integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw== + dependencies: + debug "^3.2.7" + +eslint-plugin-import@^2.25.2: + version "2.27.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65" + integrity sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow== + dependencies: + array-includes "^3.1.6" + array.prototype.flat "^1.3.1" + array.prototype.flatmap "^1.3.1" + debug "^3.2.7" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.7" + eslint-module-utils "^2.7.4" + has "^1.0.3" + is-core-module "^2.11.0" + is-glob "^4.0.3" + minimatch "^3.1.2" + object.values "^1.1.6" + resolve "^1.22.1" + semver "^6.3.0" + tsconfig-paths "^3.14.1" + +eslint-plugin-prettier@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" + integrity sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-scope@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b" + integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" + integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== + +"eslint@^7.32.0 || ^8.2.0": + version "8.43.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.43.0.tgz#3e8c6066a57097adfd9d390b8fc93075f257a094" + integrity sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.4.0" + "@eslint/eslintrc" "^2.0.3" + "@eslint/js" "8.43.0" + "@humanwhocodes/config-array" "^0.11.10" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.0" + eslint-visitor-keys "^3.4.1" + espree "^9.5.2" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.1" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" + text-table "^0.2.0" + +espree@^9.5.2: + version "9.5.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.2.tgz#e994e7dc33a082a7a82dceaf12883a829353215b" + integrity sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw== + dependencies: + acorn "^8.8.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.3.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0" + integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^3.1.0: + version "3.2.7" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" + integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== + +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +function.prototype.name@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" + integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + es-abstract "^1.19.0" + functions-have-names "^1.2.2" + +functions-have-names@^1.2.2, functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^13.19.0: + version "13.20.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" + integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== + dependencies: + type-fest "^0.20.2" + +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +ignore@^5.2.0: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +internal-slot@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" + integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== + dependencies: + get-intrinsic "^1.2.0" + has "^1.0.3" + side-channel "^1.0.4" + +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" + integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + is-typed-array "^1.1.10" + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-core-module@^2.11.0: + version "2.12.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" + integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== + dependencies: + has "^1.0.3" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-glob@^4.0.0, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" + +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typed-array@^1.1.10, is-typed-array@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json5@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== + dependencies: + minimist "^1.2.0" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0, minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +object-inspect@^1.12.3, object-inspect@^1.9.0: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.2, object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + +object.entries@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.6.tgz#9737d0e5b8291edd340a3e3264bb8a3b00d5fa23" + integrity sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +object.values@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d" + integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@2.8.8: + version "2.8.8" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" + integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== + +punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +regexp.prototype.flags@^1.4.3: + version "1.5.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb" + integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + functions-have-names "^1.2.3" + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve@^1.22.1: + version "1.22.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + dependencies: + is-core-module "^2.11.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + +semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +string.prototype.trim@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533" + integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +string.prototype.trimend@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533" + integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +string.prototype.trimstart@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4" + integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + es-abstract "^1.20.4" + +strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +tsconfig-paths@^3.14.1: + version "3.14.2" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088" + integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-typed-array@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6" + integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + is-typed-array "^1.1.10" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +word-wrap@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From c35c1d3878d4375c34f87cdc5ec00938f601c7ed Mon Sep 17 00:00:00 2001 From: eeseung Date: Mon, 3 Jul 2023 18:19:26 +0900 Subject: [PATCH 02/13] =?UTF-8?q?feat:=20DocumentList,=20CreateButton=20?= =?UTF-8?q?=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * NotionPage 추가 * API 연동 --- src/App.js | 6 +- src/DocumentList.js | 37 ------------ src/api.js | 20 +++++++ src/components/CreateButton.js | 16 ++++++ src/components/DocumentList.js | 64 +++++++++++++++++++++ src/main.js | 37 +----------- src/pages/NotionPage.js | 100 +++++++++++++++++++++++++++++++++ 7 files changed, 205 insertions(+), 75 deletions(-) delete mode 100644 src/DocumentList.js create mode 100644 src/api.js create mode 100644 src/components/CreateButton.js create mode 100644 src/components/DocumentList.js create mode 100644 src/pages/NotionPage.js diff --git a/src/App.js b/src/App.js index 1557c64b..591f66f5 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,5 @@ -import DocumentList from './DocumentList.js'; +import NotionPage from './pages/NotionPage.js'; -export default function App({ $target, initialState }) { - new DocumentList({ $target, initialState }); +export default function App({ $target }) { + new NotionPage({ $target }); } diff --git a/src/DocumentList.js b/src/DocumentList.js deleted file mode 100644 index c9620f75..00000000 --- a/src/DocumentList.js +++ /dev/null @@ -1,37 +0,0 @@ -export default function DocumentList({ $target, initialState }) { - const $documentList = document.createElement('div'); - - $target.appendChild($documentList); - - this.state = initialState; - - this.setState = (nextState) => { - this.state = nextState; - this.render(); - }; - - const renderDocuments = (documents) => { - return ` -
    - ${documents - .map( - (document) => - `
  • - ${document.title} - - ${document.documents && renderDocuments(document.documents)} -
  • ` - ) - .join('')} -
- `; - }; - - this.render = () => { - $documentList.innerHTML = ` - ${renderDocuments(this.state)} - `; - }; - - this.render(); -} diff --git a/src/api.js b/src/api.js new file mode 100644 index 00000000..52bf61c9 --- /dev/null +++ b/src/api.js @@ -0,0 +1,20 @@ +export const API_END_POINT = 'https://kdt-frontend.programmers.co.kr'; + +export const request = async (url, options = {}) => { + try { + const res = await fetch(`${API_END_POINT}${url}`, { + ...options, + headers: { + 'Content-Type': 'application/json', + 'x-username': 'eeseung', + }, + }); + + if (res.ok) { + return await res.json(); + } + throw new Error('API 호출 오류'); + } catch (e) { + alert(e.message); + } +}; diff --git a/src/components/CreateButton.js b/src/components/CreateButton.js new file mode 100644 index 00000000..0c3601ad --- /dev/null +++ b/src/components/CreateButton.js @@ -0,0 +1,16 @@ +export default function CreateButton({ $target, initialState, onClick }) { + const $button = document.createElement('button'); + $target.appendChild($button); + + this.state = initialState; + + this.render = () => { + $button.textContent = this.state.text; + }; + + $button.addEventListener('click', () => { + onClick(); + }); + + this.render(); +} diff --git a/src/components/DocumentList.js b/src/components/DocumentList.js new file mode 100644 index 00000000..69da4df4 --- /dev/null +++ b/src/components/DocumentList.js @@ -0,0 +1,64 @@ +export default function DocumentList({ $target, initialState, onCreate, onDelete, onSelect }) { + const $documentList = document.createElement('div'); + $target.appendChild($documentList); + + this.state = initialState; + + this.setState = (nextState) => { + this.state = nextState; + this.render(); + }; + + const renderDocuments = (documents, depth) => { + return ` +
    + ${ + documents.length > 0 + ? documents + .map( + (document) => + `
  • +
    + +
    ${document.title.length === 0 ? '제목 없음' : document.title}
    +
    + + +
    +
    + ${document.documents.length > 0 ? renderDocuments(document.documents, depth + 1) : ''} +
  • ` + ) + .join('') + : '페이지 없음' + } +
+ `; + }; + + this.render = () => { + $documentList.innerHTML = ` + ${renderDocuments(this.state.documents, 0)} + `; + }; + + $documentList.addEventListener('click', (e) => { + const $li = e.target.closest('.document-item'); + + if ($li) { + const { id } = $li.dataset; + const { className } = e.target; + + if (className === 'toggle') { + } else if (className === 'create') { + onCreate(parseInt(id)); + } else if (className === 'delete') { + onDelete(parseInt(id)); + } else { + onSelect(parseInt(id)); + } + } + }); + + this.render(); +} diff --git a/src/main.js b/src/main.js index 2ff3a8f3..c0d871ad 100644 --- a/src/main.js +++ b/src/main.js @@ -1,38 +1,5 @@ import App from './App.js'; -const $app = document.querySelector('#app'); +const $target = document.querySelector('#app'); -const DUMMY_DATA = [ - { - id: 1, // Document id - title: '노션을 만들자', // Document title - documents: [ - { - id: 2, - title: '블라블라', - documents: [ - { - id: 3, - title: '함냐함냐', - documents: [], - }, - { - id: 5, - title: '흠냐흠냐', - documents: [], - }, - ], - }, - ], - }, - { - id: 4, - title: 'hello!', - documents: [], - }, -]; - -new App({ - $target: $app, - initialState: DUMMY_DATA, -}); +new App({ $target }); diff --git a/src/pages/NotionPage.js b/src/pages/NotionPage.js new file mode 100644 index 00000000..1b279a8c --- /dev/null +++ b/src/pages/NotionPage.js @@ -0,0 +1,100 @@ +import { request } from '../api.js'; +import DocumentList from '../components/DocumentList.js'; +import CreateButton from '../components/CreateButton.js'; + +export default function NotionPage({ $target }) { + const $sidebarContainer = document.createElement('div'); + $sidebarContainer.classList.add('sidebar'); + $target.appendChild($sidebarContainer); + + this.state = { + documents: [], + selectedDocumentId: null, + }; + + const documentList = new DocumentList({ + $target: $sidebarContainer, + initialState: { + documents: this.state.documents, + }, + onCreate: async (documentId) => { + const createdDocument = await request('/documents', { + method: 'POST', + body: JSON.stringify({ title: '', parent: documentId }), + }); + + this.setState({ + ...this.state, + selectedDocumentId: createdDocument.id, + }); + + const documents = await request('/documents'); + this.setState({ + ...this.state, + documents, + }); + }, + onDelete: async (documentId) => { + await request(`/documents/${documentId}`, { + method: 'DELETE', + }); + + const documents = await request('/documents'); + this.setState({ + ...this.state, + documents, + selectedDocumentId: + documentId === this.state.selectedDocumentId + ? documents[0]?.id ?? document.id + : this.state.selectedDocumentId, + }); + }, + onSelect: async (documentId) => { + if (documentId !== this.state.selectedDocumentId) { + this.setState({ + ...this.state, + selectedDocumentId: documentId, + }); + } + }, + }); + + new CreateButton({ + $target: $sidebarContainer, + initialState: { + text: '페이지 추가', + }, + onClick: async () => { + const createdDocument = await request('/documents', { + method: 'POST', + body: JSON.stringify({ title: '', parent: null }), + }); + const documents = await request('/documents'); + + this.setState({ + ...this.state, + documents, + selectedDocumentId: createdDocument.id, + }); + }, + }); + + this.setState = (nextState) => { + this.state = nextState; + + documentList.setState({ + documents: this.state.documents, + }); + }; + + const init = async () => { + const documents = await request('/documents'); + + this.setState({ + ...this.state, + documents, + }); + }; + + init(); +} From 6f6e40e7c23274e628331e2cda8208033638db54 Mon Sep 17 00:00:00 2001 From: eeseung Date: Tue, 4 Jul 2023 15:30:10 +0900 Subject: [PATCH 03/13] =?UTF-8?q?feat:=20Editor=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * local storage 추가 --- index.html | 2 +- src/App.js | 8 ++- src/components/Editor.js | 44 +++++++++++++ src/pages/NotionPage.js | 135 +++++++++++++++++++++++++++++---------- src/utils/storage.js | 18 ++++++ 5 files changed, 171 insertions(+), 36 deletions(-) create mode 100644 src/components/Editor.js create mode 100644 src/utils/storage.js diff --git a/index.html b/index.html index a5c953d0..d8100bc8 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ Notion -
+
diff --git a/src/App.js b/src/App.js index 591f66f5..3e6fcdb5 100644 --- a/src/App.js +++ b/src/App.js @@ -1,5 +1,11 @@ import NotionPage from './pages/NotionPage.js'; export default function App({ $target }) { - new NotionPage({ $target }); + new NotionPage({ + $target, + initialState: { + documents: [], + documentId: null, + }, + }); } diff --git a/src/components/Editor.js b/src/components/Editor.js new file mode 100644 index 00000000..aab67781 --- /dev/null +++ b/src/components/Editor.js @@ -0,0 +1,44 @@ +export default function Editor({ $target, initialState, onEditing }) { + const $editor = document.createElement('div'); + $target.appendChild($editor); + + let isInitialize = false; + + this.state = initialState; + + this.setState = (nextState) => { + this.state = nextState; + + $editor.querySelector('[name=title]').value = this.state.title; + $editor.querySelector('[name=content]').value = this.state.content; + + this.render(); + }; + + this.render = () => { + if (!isInitialize) { + $editor.innerHTML = ` + + + `; + isInitialize = true; + } + }; + + this.render(); + + $editor.addEventListener('keyup', (e) => { + const { target } = e; + const name = target.getAttribute('name'); + + if (this.state[name] !== undefined) { + const nextState = { + ...this.state, + [name]: target.value, + }; + + this.setState(nextState); + onEditing(this.state); + } + }); +} diff --git a/src/pages/NotionPage.js b/src/pages/NotionPage.js index 1b279a8c..b9521d2b 100644 --- a/src/pages/NotionPage.js +++ b/src/pages/NotionPage.js @@ -1,61 +1,59 @@ import { request } from '../api.js'; +import { getItem, setItem, removeItem } from '../utils/storage.js'; import DocumentList from '../components/DocumentList.js'; import CreateButton from '../components/CreateButton.js'; +import Editor from '../components/Editor.js'; -export default function NotionPage({ $target }) { +export default function NotionPage({ $target, initialState }) { const $sidebarContainer = document.createElement('div'); + const $notionContainer = document.createElement('div'); + $sidebarContainer.classList.add('sidebar'); $target.appendChild($sidebarContainer); + $target.appendChild($notionContainer); - this.state = { - documents: [], - selectedDocumentId: null, - }; + this.state = initialState; + + let documentLocalSaveKey = `temp-document-${this.state.documentId}`; + let timer = null; + const doc = getItem(documentLocalSaveKey, { + title: '', + content: '', + }); const documentList = new DocumentList({ $target: $sidebarContainer, initialState: { documents: this.state.documents, }, - onCreate: async (documentId) => { + onCreate: async (id) => { const createdDocument = await request('/documents', { method: 'POST', - body: JSON.stringify({ title: '', parent: documentId }), - }); - - this.setState({ - ...this.state, - selectedDocumentId: createdDocument.id, + body: JSON.stringify({ title: '', parent: id }), }); + await fetchDocuments(); - const documents = await request('/documents'); this.setState({ ...this.state, - documents, + documentId: createdDocument.id, }); }, - onDelete: async (documentId) => { - await request(`/documents/${documentId}`, { + onDelete: async (id) => { + await request(`/documents/${id}`, { method: 'DELETE', }); + await fetchDocuments(); - const documents = await request('/documents'); this.setState({ ...this.state, - documents, - selectedDocumentId: - documentId === this.state.selectedDocumentId - ? documents[0]?.id ?? document.id - : this.state.selectedDocumentId, + documentId: id === this.state.documentId ? this.state.documents[0]?.id ?? null : this.state.documentId, }); }, - onSelect: async (documentId) => { - if (documentId !== this.state.selectedDocumentId) { - this.setState({ - ...this.state, - selectedDocumentId: documentId, - }); - } + onSelect: (id) => { + this.setState({ + ...this.state, + documentId: id, + }); }, }); @@ -69,25 +67,62 @@ export default function NotionPage({ $target }) { method: 'POST', body: JSON.stringify({ title: '', parent: null }), }); - const documents = await request('/documents'); + await fetchDocuments(); this.setState({ ...this.state, - documents, - selectedDocumentId: createdDocument.id, + documentId: createdDocument.id, }); }, }); - this.setState = (nextState) => { + const editor = new Editor({ + $target: $notionContainer, + initialState: doc, + onEditing: (document) => { + if (timer !== null) { + clearTimeout(timer); + } + timer = setTimeout(async () => { + setItem(documentLocalSaveKey, { + ...document, + tempSaveDate: new Date(), + }); + + await request(`/documents/${this.state.documentId}`, { + method: 'PUT', + body: JSON.stringify(document), + }); + removeItem(documentLocalSaveKey); + + await fetchDocument(); + await fetchDocuments(); + }, 2000); + }, + }); + + this.setState = async (nextState) => { + if (this.state.documentId !== nextState.documentId) { + documentLocalSaveKey = `temp-document-${nextState.documentId}`; + this.state = nextState; + await fetchDocument(); + return; + } + this.state = nextState; documentList.setState({ documents: this.state.documents, }); + editor.setState( + this.state.document || { + title: '', + content: '', + } + ); }; - const init = async () => { + const fetchDocuments = async () => { const documents = await request('/documents'); this.setState({ @@ -96,5 +131,37 @@ export default function NotionPage({ $target }) { }); }; + const fetchDocument = async () => { + const { documentId } = this.state; + + if (documentId) { + const document = await request(`/documents/${documentId}`); + + const tempDocument = getItem(documentLocalSaveKey, { + title: '', + content: '', + }); + + if (tempDocument.tempSaveDate && tempDocument.tempSaveDate > document.updatedAt) { + if (confirm('저장되지 않은 임시 데이터가 있습니다. 불러올까요?')) { + this.setState({ + ...this.state, + document: tempDocument, + }); + return; + } + } + + this.setState({ + ...this.state, + document, + }); + } + }; + + const init = async () => { + await fetchDocuments(); + }; + init(); } diff --git a/src/utils/storage.js b/src/utils/storage.js new file mode 100644 index 00000000..5523516f --- /dev/null +++ b/src/utils/storage.js @@ -0,0 +1,18 @@ +const storage = window.localStorage; + +export const getItem = (key, defaultValue) => { + try { + const storedValue = storage.getItem(key); + return storedValue ? JSON.parse(storedValue) : defaultValue; + } catch (e) { + return defaultValue; + } +}; + +export const setItem = (key, value) => { + storage.setItem(key, JSON.stringify(value)); +}; + +export const removeItem = (key) => { + storage.removeItem(key); +}; From 56d74a7fab3408db4d2cceda3161c62aa7e3edde Mon Sep 17 00:00:00 2001 From: eeseung Date: Tue, 4 Jul 2023 16:14:54 +0900 Subject: [PATCH 04/13] =?UTF-8?q?feat:=20=EB=9D=BC=EC=9A=B0=ED=8C=85=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 24 +++++++++++++++++++++++- src/components/DocumentList.js | 14 ++++++++------ src/pages/NotionPage.js | 22 ++++------------------ src/utils/router.js | 26 ++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 25 deletions(-) create mode 100644 src/utils/router.js diff --git a/src/App.js b/src/App.js index 3e6fcdb5..7bf8b92f 100644 --- a/src/App.js +++ b/src/App.js @@ -1,11 +1,33 @@ import NotionPage from './pages/NotionPage.js'; +import { initRouter } from './utils/router.js'; export default function App({ $target }) { - new NotionPage({ + const notionPage = new NotionPage({ $target, initialState: { documents: [], documentId: null, }, }); + + this.route = () => { + const { pathname } = window.location; + + if (pathname === '/') { + notionPage.setState({ + ...notionPage.state, + documentId: null, + }); + } else if (pathname.indexOf('/documents/') === 0) { + const [, , documentId] = pathname.split('/'); + notionPage.setState({ + ...notionPage.state, + documentId, + }); + } + }; + + this.route(); + + initRouter(() => this.route()); } diff --git a/src/components/DocumentList.js b/src/components/DocumentList.js index 69da4df4..80458295 100644 --- a/src/components/DocumentList.js +++ b/src/components/DocumentList.js @@ -1,4 +1,6 @@ -export default function DocumentList({ $target, initialState, onCreate, onDelete, onSelect }) { +import { push } from '../utils/router.js'; + +export default function DocumentList({ $target, initialState, onCreate, onDelete }) { const $documentList = document.createElement('div'); $target.appendChild($documentList); @@ -26,11 +28,11 @@ export default function DocumentList({ $target, initialState, onCreate, onDelete - ${document.documents.length > 0 ? renderDocuments(document.documents, depth + 1) : ''} + ${renderDocuments(document.documents, depth + 1)} ` ) .join('') - : '페이지 없음' + : '' } `; @@ -51,11 +53,11 @@ export default function DocumentList({ $target, initialState, onCreate, onDelete if (className === 'toggle') { } else if (className === 'create') { - onCreate(parseInt(id)); + onCreate(id); } else if (className === 'delete') { - onDelete(parseInt(id)); + onDelete(id); } else { - onSelect(parseInt(id)); + push(`/documents/${id}`); } } }); diff --git a/src/pages/NotionPage.js b/src/pages/NotionPage.js index b9521d2b..000d3020 100644 --- a/src/pages/NotionPage.js +++ b/src/pages/NotionPage.js @@ -1,5 +1,6 @@ import { request } from '../api.js'; import { getItem, setItem, removeItem } from '../utils/storage.js'; +import { push } from '../utils/router.js'; import DocumentList from '../components/DocumentList.js'; import CreateButton from '../components/CreateButton.js'; import Editor from '../components/Editor.js'; @@ -33,10 +34,7 @@ export default function NotionPage({ $target, initialState }) { }); await fetchDocuments(); - this.setState({ - ...this.state, - documentId: createdDocument.id, - }); + push(`/documents/${createdDocument.id}`); }, onDelete: async (id) => { await request(`/documents/${id}`, { @@ -44,16 +42,7 @@ export default function NotionPage({ $target, initialState }) { }); await fetchDocuments(); - this.setState({ - ...this.state, - documentId: id === this.state.documentId ? this.state.documents[0]?.id ?? null : this.state.documentId, - }); - }, - onSelect: (id) => { - this.setState({ - ...this.state, - documentId: id, - }); + push(`/documents/${id === this.state.documentId ? this.state.documents[0]?.id ?? null : this.state.documentId}`); }, }); @@ -69,10 +58,7 @@ export default function NotionPage({ $target, initialState }) { }); await fetchDocuments(); - this.setState({ - ...this.state, - documentId: createdDocument.id, - }); + push(`/documents/${createdDocument.id}`); }, }); diff --git a/src/utils/router.js b/src/utils/router.js new file mode 100644 index 00000000..a295896a --- /dev/null +++ b/src/utils/router.js @@ -0,0 +1,26 @@ +const ROUTE_CHANGE_EVENT_NAME = 'route-change'; + +export const initRouter = (onRoute) => { + window.addEventListener(ROUTE_CHANGE_EVENT_NAME, (e) => { + const { nextUrl } = e.detail; + + if (nextUrl) { + history.pushState(null, null, nextUrl); + onRoute(); + } + }); + + window.addEventListener('popstate', () => { + onRoute(); + }); +}; + +export const push = (nextUrl) => { + window.dispatchEvent( + new CustomEvent(ROUTE_CHANGE_EVENT_NAME, { + detail: { + nextUrl: nextUrl, + }, + }) + ); +}; From b33b96d0e9c6d48aa411fd1170543e6c0696091f Mon Sep 17 00:00:00 2001 From: eeseung Date: Tue, 4 Jul 2023 16:55:04 +0900 Subject: [PATCH 05/13] =?UTF-8?q?feat:=20NotionPage=20=EB=A3=A8=ED=8A=B8?= =?UTF-8?q?=20url=20=EC=A1=B0=EA=B1=B4=EB=B6=80=20=EB=A0=8C=EB=8D=94?= =?UTF-8?q?=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/NotionPage.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/pages/NotionPage.js b/src/pages/NotionPage.js index 000d3020..f220f626 100644 --- a/src/pages/NotionPage.js +++ b/src/pages/NotionPage.js @@ -11,7 +11,6 @@ export default function NotionPage({ $target, initialState }) { $sidebarContainer.classList.add('sidebar'); $target.appendChild($sidebarContainer); - $target.appendChild($notionContainer); this.state = initialState; @@ -91,7 +90,10 @@ export default function NotionPage({ $target, initialState }) { if (this.state.documentId !== nextState.documentId) { documentLocalSaveKey = `temp-document-${nextState.documentId}`; this.state = nextState; + await fetchDocument(); + this.render(); + return; } @@ -145,6 +147,15 @@ export default function NotionPage({ $target, initialState }) { } }; + this.render = () => { + $target.appendChild($notionContainer); + + // 루트 url인 경우 노션 컨테이너 렌더링 X + if (this.state.documentId === null) { + $target.removeChild($notionContainer); + } + }; + const init = async () => { await fetchDocuments(); }; From 4c697cd4fa04d0b192f8bea8314a02045070f6fb Mon Sep 17 00:00:00 2001 From: eeseung Date: Tue, 4 Jul 2023 18:06:27 +0900 Subject: [PATCH 06/13] =?UTF-8?q?refactor:=20documentId=20Number=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/App.js | 4 ++-- src/components/DocumentList.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/App.js b/src/App.js index 7bf8b92f..ee70d1f3 100644 --- a/src/App.js +++ b/src/App.js @@ -19,10 +19,10 @@ export default function App({ $target }) { documentId: null, }); } else if (pathname.indexOf('/documents/') === 0) { - const [, , documentId] = pathname.split('/'); + const [, , id] = pathname.split('/'); notionPage.setState({ ...notionPage.state, - documentId, + documentId: parseInt(id), }); } }; diff --git a/src/components/DocumentList.js b/src/components/DocumentList.js index 80458295..d64a236e 100644 --- a/src/components/DocumentList.js +++ b/src/components/DocumentList.js @@ -53,9 +53,9 @@ export default function DocumentList({ $target, initialState, onCreate, onDelete if (className === 'toggle') { } else if (className === 'create') { - onCreate(id); + onCreate(parseInt(id)); } else if (className === 'delete') { - onDelete(id); + onDelete(parseInt(id)); } else { push(`/documents/${id}`); } From c19d25e29551feeb613e09da117d389de72c7015 Mon Sep 17 00:00:00 2001 From: eeseung Date: Wed, 5 Jul 2023 17:01:23 +0900 Subject: [PATCH 07/13] =?UTF-8?q?feat:=20DocumentList=20=ED=86=A0=EA=B8=80?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 1 + src/App.js | 4 +++ src/components/DocumentList.js | 47 ++++++++++++++------------ src/pages/NotionPage.js | 62 ++++++++++++++++++++++++++++++++++ src/styles/style.css | 16 +++++++++ 5 files changed, 109 insertions(+), 21 deletions(-) create mode 100644 src/styles/style.css diff --git a/index.html b/index.html index d8100bc8..2012880f 100644 --- a/index.html +++ b/index.html @@ -1,6 +1,7 @@ Notion +
diff --git a/src/App.js b/src/App.js index ee70d1f3..f967a96a 100644 --- a/src/App.js +++ b/src/App.js @@ -1,12 +1,16 @@ import NotionPage from './pages/NotionPage.js'; import { initRouter } from './utils/router.js'; +import { getItem } from './utils/storage.js'; export default function App({ $target }) { + const openedDocuments = getItem('opened-documents', []); + const notionPage = new NotionPage({ $target, initialState: { documents: [], documentId: null, + openedDocuments: openedDocuments, }, }); diff --git a/src/components/DocumentList.js b/src/components/DocumentList.js index d64a236e..8e42d781 100644 --- a/src/components/DocumentList.js +++ b/src/components/DocumentList.js @@ -1,6 +1,6 @@ import { push } from '../utils/router.js'; -export default function DocumentList({ $target, initialState, onCreate, onDelete }) { +export default function DocumentList({ $target, initialState, onToggle, onCreate, onDelete }) { const $documentList = document.createElement('div'); $target.appendChild($documentList); @@ -13,34 +13,38 @@ export default function DocumentList({ $target, initialState, onCreate, onDelete const renderDocuments = (documents, depth) => { return ` -
    ${ documents.length > 0 ? documents - .map( - (document) => - `
  • -
    - -
    ${document.title.length === 0 ? '제목 없음' : document.title}
    + .map((document) => { + const isExpanded = this.state.openedDocuments.indexOf(document.id) > -1; + + return `
  • +
    + + ${document.title.length === 0 ? '제목 없음' : document.title}
    - - + +
    - ${renderDocuments(document.documents, depth + 1)} -
  • ` - ) +
      + ${renderDocuments(document.documents, depth + 1)} +
    + `; + }) .join('') - : '' + : `
  • 하위 페이지 없음
  • ` } -
`; }; this.render = () => { $documentList.innerHTML = ` - ${renderDocuments(this.state.documents, 0)} +
    + ${renderDocuments(this.state.documents, 0)} +
`; }; @@ -49,14 +53,15 @@ export default function DocumentList({ $target, initialState, onCreate, onDelete if ($li) { const { id } = $li.dataset; - const { className } = e.target; + const [className] = e.target.classList; - if (className === 'toggle') { - } else if (className === 'create') { + if (className === 'toggle-button') { + onToggle(parseInt(id), $li.querySelector('ul')); + } else if (className === 'create-button') { onCreate(parseInt(id)); - } else if (className === 'delete') { + } else if (className === 'delete-button') { onDelete(parseInt(id)); - } else { + } else if (className === 'document-item-container') { push(`/documents/${id}`); } } diff --git a/src/pages/NotionPage.js b/src/pages/NotionPage.js index f220f626..eeed684d 100644 --- a/src/pages/NotionPage.js +++ b/src/pages/NotionPage.js @@ -25,6 +25,32 @@ export default function NotionPage({ $target, initialState }) { $target: $sidebarContainer, initialState: { documents: this.state.documents, + documentId: this.state.documentId, + openedDocuments: this.state.openedDocuments, + }, + onToggle: (id, $ul) => { + const index = this.state.openedDocuments.indexOf(parseInt(id)); + + if (index > -1) { + // 토글 닫기 + const copyOpenedDocuments = [...this.state.openedDocuments]; + copyOpenedDocuments.splice(index, 1); + + closeSubList($ul, copyOpenedDocuments); + + this.setState({ + ...this.state, + openedDocuments: copyOpenedDocuments, + }); + setItem('opened-documents', copyOpenedDocuments); + } else { + // 토글 열기 + this.setState({ + ...this.state, + openedDocuments: [...this.state.openedDocuments, parseInt(id)], + }); + setItem('opened-documents', this.state.openedDocuments); + } }, onCreate: async (id) => { const createdDocument = await request('/documents', { @@ -34,6 +60,12 @@ export default function NotionPage({ $target, initialState }) { await fetchDocuments(); push(`/documents/${createdDocument.id}`); + + this.setState({ + ...this.state, + openedDocuments: [...this.state.openedDocuments, id], + }); + setItem('opened-documents', this.state.openedDocuments); }, onDelete: async (id) => { await request(`/documents/${id}`, { @@ -42,6 +74,19 @@ export default function NotionPage({ $target, initialState }) { await fetchDocuments(); push(`/documents/${id === this.state.documentId ? this.state.documents[0]?.id ?? null : this.state.documentId}`); + + const index = this.state.openedDocuments.indexOf(id); + + if (index > -1) { + const copyOpenedDocuments = [...this.state.openedDocuments]; + copyOpenedDocuments.splice(index, 1); + + this.setState({ + ...this.state, + openedDocuments: copyOpenedDocuments, + }); + setItem('opened-documents', copyOpenedDocuments); + } }, }); @@ -100,8 +145,11 @@ export default function NotionPage({ $target, initialState }) { this.state = nextState; documentList.setState({ + documentId: this.state.documentId, documents: this.state.documents, + openedDocuments: this.state.openedDocuments, }); + editor.setState( this.state.document || { title: '', @@ -110,6 +158,20 @@ export default function NotionPage({ $target, initialState }) { ); }; + // 하위 목록 토글 닫기 + const closeSubList = ($ul, copyOpenedDocuments) => { + if ($ul) { + $ul.querySelectorAll('li').forEach(($li) => { + const { id } = $li.dataset; + const index = [...copyOpenedDocuments].indexOf(parseInt(id)); + if (index > -1) { + copyOpenedDocuments.splice(index, 1); + closeSubList($li.querySelector('ul'), copyOpenedDocuments); + } + }); + } + }; + const fetchDocuments = async () => { const documents = await request('/documents'); diff --git a/src/styles/style.css b/src/styles/style.css new file mode 100644 index 00000000..ba662c2a --- /dev/null +++ b/src/styles/style.css @@ -0,0 +1,16 @@ +ul { + padding: 0; + list-style: none; +} + +ul:not(.expanded) { + display: none; +} + +.document-item-container.selected { + font-weight: 600; +} + +.document-item-container button.expanded { + transform: rotate(90deg); +} From 914096d720c55001da9cef9931de39b30650ba1d Mon Sep 17 00:00:00 2001 From: eeseung Date: Thu, 6 Jul 2023 14:37:12 +0900 Subject: [PATCH 08/13] =?UTF-8?q?design:=20normalize.css=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/index.html b/index.html index 2012880f..336f2654 100644 --- a/index.html +++ b/index.html @@ -1,6 +1,13 @@ Notion + From b4af05924b4fa08fcfeee0399f58495324651a27 Mon Sep 17 00:00:00 2001 From: eeseung Date: Thu, 6 Jul 2023 20:16:57 +0900 Subject: [PATCH 09/13] =?UTF-8?q?fix:=20document=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EC=8B=9C=20=EB=9D=BC=EC=9A=B0=ED=8C=85=20=EC=98=A4=EB=A5=98=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/NotionPage.js | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/pages/NotionPage.js b/src/pages/NotionPage.js index eeed684d..6087ac5c 100644 --- a/src/pages/NotionPage.js +++ b/src/pages/NotionPage.js @@ -7,9 +7,9 @@ import Editor from '../components/Editor.js'; export default function NotionPage({ $target, initialState }) { const $sidebarContainer = document.createElement('div'); - const $notionContainer = document.createElement('div'); - - $sidebarContainer.classList.add('sidebar'); + const $documentContainer = document.createElement('div'); + $sidebarContainer.classList.add('sidebar-container'); + $documentContainer.classList.add('document-container'); $target.appendChild($sidebarContainer); this.state = initialState; @@ -73,7 +73,19 @@ export default function NotionPage({ $target, initialState }) { }); await fetchDocuments(); - push(`/documents/${id === this.state.documentId ? this.state.documents[0]?.id ?? null : this.state.documentId}`); + if (id === this.state.documentId) { + if (this.state.documents.length > 0) { + push(`/documents/${this.state.documents[0].id}`); + } else { + push('/'); + } + } else { + if (this.state.documentId) { + push(`/documents/${this.state.documentId}`); + } else { + push('/'); + } + } const index = this.state.openedDocuments.indexOf(id); @@ -107,7 +119,7 @@ export default function NotionPage({ $target, initialState }) { }); const editor = new Editor({ - $target: $notionContainer, + $target: $documentContainer, initialState: doc, onEditing: (document) => { if (timer !== null) { @@ -210,11 +222,11 @@ export default function NotionPage({ $target, initialState }) { }; this.render = () => { - $target.appendChild($notionContainer); + $target.appendChild($documentContainer); // 루트 url인 경우 노션 컨테이너 렌더링 X if (this.state.documentId === null) { - $target.removeChild($notionContainer); + $target.removeChild($documentContainer); } }; From b17d83e5c8052f5514f8b6cee3c0db5ec616a1dc Mon Sep 17 00:00:00 2001 From: eeseung Date: Thu, 6 Jul 2023 21:54:10 +0900 Subject: [PATCH 10/13] =?UTF-8?q?design:=20=EB=85=B8=EC=85=98=20=EB=94=94?= =?UTF-8?q?=EC=9E=90=EC=9D=B8=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 3 + src/assets/arrow-icon.svg | 3 + src/assets/plus-icon.svg | 5 + src/assets/trash-icon.svg | 10 ++ src/components/CreateButton.js | 1 + src/components/DocumentList.js | 61 ++++++---- src/components/Editor.js | 3 +- src/styles/style.css | 213 ++++++++++++++++++++++++++++++++- 8 files changed, 268 insertions(+), 31 deletions(-) create mode 100644 src/assets/arrow-icon.svg create mode 100644 src/assets/plus-icon.svg create mode 100644 src/assets/trash-icon.svg diff --git a/index.html b/index.html index 336f2654..dfae3ac8 100644 --- a/index.html +++ b/index.html @@ -8,6 +8,9 @@ crossorigin="anonymous" referrerpolicy="no-referrer" /> + + + diff --git a/src/assets/arrow-icon.svg b/src/assets/arrow-icon.svg new file mode 100644 index 00000000..6521957d --- /dev/null +++ b/src/assets/arrow-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/plus-icon.svg b/src/assets/plus-icon.svg new file mode 100644 index 00000000..36936eca --- /dev/null +++ b/src/assets/plus-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/assets/trash-icon.svg b/src/assets/trash-icon.svg new file mode 100644 index 00000000..10c786e4 --- /dev/null +++ b/src/assets/trash-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/components/CreateButton.js b/src/components/CreateButton.js index 0c3601ad..ce549e49 100644 --- a/src/components/CreateButton.js +++ b/src/components/CreateButton.js @@ -1,5 +1,6 @@ export default function CreateButton({ $target, initialState, onClick }) { const $button = document.createElement('button'); + $button.classList.add('create-button'); $target.appendChild($button); this.state = initialState; diff --git a/src/components/DocumentList.js b/src/components/DocumentList.js index 8e42d781..826536aa 100644 --- a/src/components/DocumentList.js +++ b/src/components/DocumentList.js @@ -2,6 +2,7 @@ import { push } from '../utils/router.js'; export default function DocumentList({ $target, initialState, onToggle, onCreate, onDelete }) { const $documentList = document.createElement('div'); + $documentList.classList.add('document-list'); $target.appendChild($documentList); this.state = initialState; @@ -13,43 +14,49 @@ export default function DocumentList({ $target, initialState, onToggle, onCreate const renderDocuments = (documents, depth) => { return ` - ${ - documents.length > 0 - ? documents - .map((document) => { - const isExpanded = this.state.openedDocuments.indexOf(document.id) > -1; - - return `
  • -
    - + ${ + documents.length > 0 + ? documents + .map((document) => { + const isExpanded = this.state.openedDocuments.indexOf(document.id) > -1; + return ` +
  • +
    + +
    ${document.title.length === 0 ? '제목 없음' : document.title} +
    +
    - - + +
    -
      - ${renderDocuments(document.documents, depth + 1)} -
    -
  • `; - }) - .join('') - : `
  • 하위 페이지 없음
  • ` - } + +
      + ${renderDocuments(document.documents, depth + 1)} +
    + `; + }) + .join('') + : ` +
  • + 하위 페이지 없음 +
  • + ` + } `; }; this.render = () => { $documentList.innerHTML = ` -
      - ${renderDocuments(this.state.documents, 0)} -
    + ${this.state.documents.length > 0 ? `
      ${renderDocuments(this.state.documents, 0)}
    ` : ''} `; }; $documentList.addEventListener('click', (e) => { - const $li = e.target.closest('.document-item'); + const $li = e.target.closest('.document-list-item'); if ($li) { const { id } = $li.dataset; @@ -57,11 +64,13 @@ export default function DocumentList({ $target, initialState, onToggle, onCreate if (className === 'toggle-button') { onToggle(parseInt(id), $li.querySelector('ul')); - } else if (className === 'create-button') { + } else if (className === 'add-button') { onCreate(parseInt(id)); } else if (className === 'delete-button') { onDelete(parseInt(id)); - } else if (className === 'document-item-container') { + } else if (className === 'document-item-none') { + return; + } else { push(`/documents/${id}`); } } diff --git a/src/components/Editor.js b/src/components/Editor.js index aab67781..0d277eb9 100644 --- a/src/components/Editor.js +++ b/src/components/Editor.js @@ -1,5 +1,6 @@ export default function Editor({ $target, initialState, onEditing }) { const $editor = document.createElement('div'); + $editor.classList.add('editor'); $target.appendChild($editor); let isInitialize = false; @@ -19,7 +20,7 @@ export default function Editor({ $target, initialState, onEditing }) { if (!isInitialize) { $editor.innerHTML = ` - + `; isInitialize = true; } diff --git a/src/styles/style.css b/src/styles/style.css index ba662c2a..c3346a7d 100644 --- a/src/styles/style.css +++ b/src/styles/style.css @@ -1,16 +1,221 @@ +:root { + --color-base-100: #fafbfb; + --color-gray-50: rgba(0, 0, 0, 0.024); + --color-gray-100: rgba(0, 0, 0, 0.04); + --color-gray-150: rgba(55, 53, 47, 0.08); + --color-gray-200: rgba(0, 0, 0, 0.1); + + --text-color-light: rgba(0, 0, 0, 0.4); + --text-color-medium: rgba(25, 23, 17, 0.6); + --text-color-dark: #37352f; +} + +* { + box-sizing: border-box; +} + +body { + margin: 0; + font-family: 'Noto Sans KR', sans-serif; +} + +main { + display: flex; + height: 100vh; +} + ul { + margin: 0; padding: 0; list-style: none; } -ul:not(.expanded) { +.sidebar-container { + width: 220px; + padding: 0 4px 20px; + background-color: var(--color-base-100); + box-shadow: var(--color-gray-50) -1px 0px 0px 0px inset; + overflow-y: scroll; +} + +.document-container { + flex-grow: 1; +} + +/* DocumentList */ +.document-list { + padding-top: 6px; +} + +.document-list ul:not(.expanded) { display: none; } -.document-item-container.selected { - font-weight: 600; +.document-list-item { + cursor: pointer; +} + +.document-item, +.document-list-none { + display: flex; + justify-content: center; + align-items: center; + width: 100%; + height: 27px; + margin: 1px 0; + font-weight: 500; + font-size: 14px; + color: var(--text-color-medium); } -.document-item-container button.expanded { +.document-list-none { + justify-content: normal; + color: var(--text-color-light); + cursor: default; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.document-item.selected { + border-radius: 3px; + background-color: var(--color-gray-100); + font-weight: 500; + color: var(--text-color-dark); +} + +.document-item:hover { + background-color: var(--color-gray-150); +} + +.document-title { + flex: 1 1 auto; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.document-button-wrapper > div { + display: flex; + align-items: center; + position: absolute; + width: 0; + height: 0; + padding-left: 3px; + white-space: nowrap; + overflow: hidden; +} + +.document-item:hover .document-button-wrapper > div { + display: flex; + position: initial; + width: initial; + height: initial; +} + +.toggle-button, +.add-button, +.delete-button { + display: flex; + justify-content: center; + align-items: center; + width: 20px; + height: 20px; + border: none; + border-radius: 3px; + background: none; + cursor: inherit; +} + +.toggle-button:hover, +.add-button:hover, +.delete-button:hover { + background-color: var(--color-gray-200); +} + +.toggle-button { + flex-shrink: 0; + flex-grow: 0; + margin-right: 4px; + background: url('/src/assets/arrow-icon.svg') no-repeat center center / 16px 16px; + transition: transform 1.5s ease-out; +} + +.toggle-button.expanded { transform: rotate(90deg); } + +.delete-button { + background: url('/src/assets/trash-icon.svg') no-repeat center center / 16px 16px; +} + +.add-button { + margin-left: 4px; + background: url('/src/assets/plus-icon.svg') no-repeat center center / 16px 16px; +} + +/* CreateButton */ +.create-button { + display: flex; + align-items: center; + width: 100%; + height: 27px; + padding-left: 29px; + border: none; + background: url('/src/assets/plus-icon.svg') no-repeat 5px center / 16px 16px; + border-radius: 3px; + font-weight: 500; + font-size: 14px; + color: var(--text-color-medium); +} + +.create-button:hover { + background-color: var(--color-gray-200); +} + +/* Editor */ +.editor { + display: flex; + flex-direction: column; + width: 100%; + max-width: 900px; + height: 100%; + margin: 0 auto; + padding: 80px 96px 96px; +} + +.editor input { + width: 100%; + height: 54px; + padding: 3px 2px; + border: none; + font-weight: 700; + font-size: 40px; + line-height: 1.2; + color: var(--text-color-dark); + outline: none; + white-space: pre-wrap; + word-break: break-word; + caret-color: var(--text-color-dark); +} + +.editor textarea { + width: 100%; + height: 100%; + margin-top: 5px; + padding: 3px 2px; + border: none; + font-size: 16px; + line-height: 1.5; + color: var(--text-color-dark); + outline: none; + white-space: pre-wrap; + word-break: break-word; + caret-color: var(--text-color-dark); + resize: none; +} + +.editor input::placeholder, +.editor textarea::placeholder { + color: var(--text-color-light); +} From 7d675233f59d9c9933c994b66cb19ae5ec1b68e7 Mon Sep 17 00:00:00 2001 From: eeseung Date: Thu, 6 Jul 2023 23:18:06 +0900 Subject: [PATCH 11/13] =?UTF-8?q?refactor:=20constants=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api.js | 4 ++-- src/constants.js | 10 ++++++++++ src/pages/NotionPage.js | 30 ++++++++++-------------------- 3 files changed, 22 insertions(+), 22 deletions(-) create mode 100644 src/constants.js diff --git a/src/api.js b/src/api.js index 52bf61c9..ed43306b 100644 --- a/src/api.js +++ b/src/api.js @@ -1,4 +1,4 @@ -export const API_END_POINT = 'https://kdt-frontend.programmers.co.kr'; +import { API_END_POINT, USER_NAME } from './constants.js'; export const request = async (url, options = {}) => { try { @@ -6,7 +6,7 @@ export const request = async (url, options = {}) => { ...options, headers: { 'Content-Type': 'application/json', - 'x-username': 'eeseung', + 'x-username': USER_NAME, }, }); diff --git a/src/constants.js b/src/constants.js new file mode 100644 index 00000000..52767cb2 --- /dev/null +++ b/src/constants.js @@ -0,0 +1,10 @@ +export const API_END_POINT = 'https://kdt-frontend.programmers.co.kr'; +export const USER_NAME = 'eeseung'; + +export const TEMP_DOCUMENT_KEY = (id) => `temp-document-${id}`; +export const OPENED_DOCUMENTS_KEY = 'opened-documents'; + +export const INIT_DOCUMENT = { + title: '', + content: '', +}; diff --git a/src/pages/NotionPage.js b/src/pages/NotionPage.js index 6087ac5c..d7b5aaa5 100644 --- a/src/pages/NotionPage.js +++ b/src/pages/NotionPage.js @@ -1,6 +1,7 @@ import { request } from '../api.js'; import { getItem, setItem, removeItem } from '../utils/storage.js'; import { push } from '../utils/router.js'; +import { TEMP_DOCUMENT_KEY, OPENED_DOCUMENTS_KEY, INIT_DOCUMENT } from '../constants.js'; import DocumentList from '../components/DocumentList.js'; import CreateButton from '../components/CreateButton.js'; import Editor from '../components/Editor.js'; @@ -14,12 +15,9 @@ export default function NotionPage({ $target, initialState }) { this.state = initialState; - let documentLocalSaveKey = `temp-document-${this.state.documentId}`; + let documentLocalSaveKey = `${TEMP_DOCUMENT_KEY(this.state.documentId)}`; let timer = null; - const doc = getItem(documentLocalSaveKey, { - title: '', - content: '', - }); + const doc = getItem(documentLocalSaveKey, INIT_DOCUMENT); const documentList = new DocumentList({ $target: $sidebarContainer, @@ -42,14 +40,14 @@ export default function NotionPage({ $target, initialState }) { ...this.state, openedDocuments: copyOpenedDocuments, }); - setItem('opened-documents', copyOpenedDocuments); + setItem(OPENED_DOCUMENTS_KEY, copyOpenedDocuments); } else { // 토글 열기 this.setState({ ...this.state, openedDocuments: [...this.state.openedDocuments, parseInt(id)], }); - setItem('opened-documents', this.state.openedDocuments); + setItem(OPENED_DOCUMENTS_KEY, this.state.openedDocuments); } }, onCreate: async (id) => { @@ -65,7 +63,7 @@ export default function NotionPage({ $target, initialState }) { ...this.state, openedDocuments: [...this.state.openedDocuments, id], }); - setItem('opened-documents', this.state.openedDocuments); + setItem(OPENED_DOCUMENTS_KEY, this.state.openedDocuments); }, onDelete: async (id) => { await request(`/documents/${id}`, { @@ -97,7 +95,7 @@ export default function NotionPage({ $target, initialState }) { ...this.state, openedDocuments: copyOpenedDocuments, }); - setItem('opened-documents', copyOpenedDocuments); + setItem(OPENED_DOCUMENTS_KEY, copyOpenedDocuments); } }, }); @@ -145,7 +143,7 @@ export default function NotionPage({ $target, initialState }) { this.setState = async (nextState) => { if (this.state.documentId !== nextState.documentId) { - documentLocalSaveKey = `temp-document-${nextState.documentId}`; + documentLocalSaveKey = `${TEMP_DOCUMENT_KEY(nextState.documentId)}`; this.state = nextState; await fetchDocument(); @@ -162,12 +160,7 @@ export default function NotionPage({ $target, initialState }) { openedDocuments: this.state.openedDocuments, }); - editor.setState( - this.state.document || { - title: '', - content: '', - } - ); + editor.setState(this.state.document || INIT_DOCUMENT); }; // 하위 목록 토글 닫기 @@ -199,10 +192,7 @@ export default function NotionPage({ $target, initialState }) { if (documentId) { const document = await request(`/documents/${documentId}`); - const tempDocument = getItem(documentLocalSaveKey, { - title: '', - content: '', - }); + const tempDocument = getItem(documentLocalSaveKey, INIT_DOCUMENT); if (tempDocument.tempSaveDate && tempDocument.tempSaveDate > document.updatedAt) { if (confirm('저장되지 않은 임시 데이터가 있습니다. 불러올까요?')) { From 5b086be70e9a15023283da567e0337752fc4dd43 Mon Sep 17 00:00:00 2001 From: eeseung Date: Fri, 7 Jul 2023 00:45:32 +0900 Subject: [PATCH 12/13] =?UTF-8?q?feat:=20SidebarHeader,=20DocumentHeader?= =?UTF-8?q?=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * components 폴더 정리 --- src/components/Document/DocumentHeader.js | 21 +++++++++++ src/components/{ => Document}/Editor.js | 0 src/components/{ => Sidebar}/CreateButton.js | 0 src/components/{ => Sidebar}/DocumentList.js | 2 +- src/components/Sidebar/SidebarHeader.js | 15 ++++++++ src/pages/NotionPage.js | 22 +++++++++--- src/styles/style.css | 38 ++++++++++++++++++++ 7 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 src/components/Document/DocumentHeader.js rename src/components/{ => Document}/Editor.js (100%) rename src/components/{ => Sidebar}/CreateButton.js (100%) rename src/components/{ => Sidebar}/DocumentList.js (98%) create mode 100644 src/components/Sidebar/SidebarHeader.js diff --git a/src/components/Document/DocumentHeader.js b/src/components/Document/DocumentHeader.js new file mode 100644 index 00000000..7a0e344a --- /dev/null +++ b/src/components/Document/DocumentHeader.js @@ -0,0 +1,21 @@ +export default function DocumentHeader({ $target, initialState }) { + const $header = document.createElement('header'); + $header.classList.add('document-header'); + $target.appendChild($header); + + this.state = initialState; + + this.setState = (nextState) => { + this.state = nextState; + + this.render(); + }; + + this.render = () => { + $header.innerHTML = ` + ${this.state.title} + `; + }; + + this.render(); +} diff --git a/src/components/Editor.js b/src/components/Document/Editor.js similarity index 100% rename from src/components/Editor.js rename to src/components/Document/Editor.js diff --git a/src/components/CreateButton.js b/src/components/Sidebar/CreateButton.js similarity index 100% rename from src/components/CreateButton.js rename to src/components/Sidebar/CreateButton.js diff --git a/src/components/DocumentList.js b/src/components/Sidebar/DocumentList.js similarity index 98% rename from src/components/DocumentList.js rename to src/components/Sidebar/DocumentList.js index 826536aa..9bf3bbb1 100644 --- a/src/components/DocumentList.js +++ b/src/components/Sidebar/DocumentList.js @@ -1,4 +1,4 @@ -import { push } from '../utils/router.js'; +import { push } from '../../utils/router.js'; export default function DocumentList({ $target, initialState, onToggle, onCreate, onDelete }) { const $documentList = document.createElement('div'); diff --git a/src/components/Sidebar/SidebarHeader.js b/src/components/Sidebar/SidebarHeader.js new file mode 100644 index 00000000..d3a0d8ba --- /dev/null +++ b/src/components/Sidebar/SidebarHeader.js @@ -0,0 +1,15 @@ +export default function SidebarHeader({ $target, initialState }) { + const $header = document.createElement('header'); + $header.classList.add('sidebar-header'); + $target.appendChild($header); + + this.state = initialState; + + this.render = () => { + $header.innerHTML = ` + ${this.state.heading} + `; + }; + + this.render(); +} diff --git a/src/pages/NotionPage.js b/src/pages/NotionPage.js index d7b5aaa5..95e5d5e6 100644 --- a/src/pages/NotionPage.js +++ b/src/pages/NotionPage.js @@ -2,9 +2,11 @@ import { request } from '../api.js'; import { getItem, setItem, removeItem } from '../utils/storage.js'; import { push } from '../utils/router.js'; import { TEMP_DOCUMENT_KEY, OPENED_DOCUMENTS_KEY, INIT_DOCUMENT } from '../constants.js'; -import DocumentList from '../components/DocumentList.js'; -import CreateButton from '../components/CreateButton.js'; -import Editor from '../components/Editor.js'; +import SidebarHeader from '../components/Sidebar/SidebarHeader.js'; +import DocumentList from '../components/Sidebar/DocumentList.js'; +import CreateButton from '../components/Sidebar/CreateButton.js'; +import DocumentHeader from '../components/Document/DocumentHeader.js'; +import Editor from '../components/Document/Editor.js'; export default function NotionPage({ $target, initialState }) { const $sidebarContainer = document.createElement('div'); @@ -19,6 +21,13 @@ export default function NotionPage({ $target, initialState }) { let timer = null; const doc = getItem(documentLocalSaveKey, INIT_DOCUMENT); + new SidebarHeader({ + $target: $sidebarContainer, + initialState: { + heading: '📚 Notion', + }, + }); + const documentList = new DocumentList({ $target: $sidebarContainer, initialState: { @@ -116,6 +125,11 @@ export default function NotionPage({ $target, initialState }) { }, }); + const documentHeader = new DocumentHeader({ + $target: $documentContainer, + initialState: doc, + }); + const editor = new Editor({ $target: $documentContainer, initialState: doc, @@ -159,7 +173,7 @@ export default function NotionPage({ $target, initialState }) { documents: this.state.documents, openedDocuments: this.state.openedDocuments, }); - + documentHeader.setState(this.state.document || INIT_DOCUMENT); editor.setState(this.state.document || INIT_DOCUMENT); }; diff --git a/src/styles/style.css b/src/styles/style.css index c3346a7d..9def8590 100644 --- a/src/styles/style.css +++ b/src/styles/style.css @@ -31,6 +31,7 @@ ul { } .sidebar-container { + flex-shrink: 0; width: 220px; padding: 0 4px 20px; background-color: var(--color-base-100); @@ -42,6 +43,21 @@ ul { flex-grow: 1; } +/* SidebarHeader */ +.sidebar-header { + display: flex; + align-items: center; + height: 45px; + padding: 0 5px; +} + +.sidebar-header a { + font-weight: 500; + font-size: 14px; + color: var(--text-color-dark); + text-decoration: none; +} + /* DocumentList */ .document-list { padding-top: 6px; @@ -173,6 +189,28 @@ ul { background-color: var(--color-gray-200); } +/* DocumentHeader */ +.document-header { + display: flex; + align-items: center; + height: 45px; + padding: 0 12px; +} + +.document-header a { + padding: 0 6px; + font-weight: 400; + font-size: 14px; + line-height: 24px; + color: var(--text-color-dark); + text-decoration: none; + border-radius: 4px; +} + +.document-header a:hover { + background-color: var(--color-gray-150); +} + /* Editor */ .editor { display: flex; From 168ee2b221183d5a954146572c3a550b1aaab541 Mon Sep 17 00:00:00 2001 From: eeseung Date: Thu, 13 Jul 2023 03:33:26 +0900 Subject: [PATCH 13/13] =?UTF-8?q?feat:=20index.html=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index dfae3ac8..24cf5863 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,8 @@ - + + + + Notion