From 7ef92ffa78afe6ff92440348e25032d204c653ec Mon Sep 17 00:00:00 2001 From: DarkSky Date: Wed, 17 Aug 2022 02:24:34 +0800 Subject: [PATCH 01/58] chore: cleanup deps --- .vscode/settings.json | 1 + apps/ligo-virgo-e2e/package.json | 11 + libs/components/account/package.json | 5 +- libs/datasource/state/package.json | 1 - package.json | 5 - pnpm-lock.yaml | 1643 ++------------------------ 6 files changed, 92 insertions(+), 1574 deletions(-) create mode 100644 apps/ligo-virgo-e2e/package.json diff --git a/.vscode/settings.json b/.vscode/settings.json index defe3ab909..375ba3b6e0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -24,6 +24,7 @@ "Kanban", "keyval", "ligo", + "livedemo", "lozad", "mastersthesis", "nrwl", diff --git a/apps/ligo-virgo-e2e/package.json b/apps/ligo-virgo-e2e/package.json new file mode 100644 index 0000000000..03d495c5a1 --- /dev/null +++ b/apps/ligo-virgo-e2e/package.json @@ -0,0 +1,11 @@ +{ + "name": "ligo-virgo-e2e", + "version": "1.0.0", + "license": "MIT", + "description": "", + "author": "AFFiNE ", + "dependencies": {}, + "devDependencies": { + "cypress": "^10.4.0" + } +} diff --git a/libs/components/account/package.json b/libs/components/account/package.json index 96fb8115d7..00634cf9b1 100644 --- a/libs/components/account/package.json +++ b/libs/components/account/package.json @@ -3,10 +3,7 @@ "version": "0.0.1", "license": "MIT", "dependencies": { - "@authing/react-ui-components": "^3.1.39", "@emotion/styled": "^11.9.3" }, - "devDependencies": { - "authing-js-sdk": "^4.23.35" - } + "devDependencies": {} } diff --git a/libs/datasource/state/package.json b/libs/datasource/state/package.json index dcf7b9750a..a1a92d478b 100644 --- a/libs/datasource/state/package.json +++ b/libs/datasource/state/package.json @@ -6,7 +6,6 @@ "jotai": "^1.7.4" }, "devDependencies": { - "authing-js-sdk": "^4.23.35", "firebase": "^9.9.2" } } diff --git a/package.json b/package.json index 5abcf2e612..3c9ce22156 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,6 @@ "got": "^12.1.0", "level": "^8.0.0", "level-read-stream": "1.1.0", - "next": "12.2.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router": "^6.3.0", @@ -91,8 +90,6 @@ "@nrwl/jest": "^14.4.0", "@nrwl/js": "^14.4.0", "@nrwl/linter": "^14.4.0", - "@nrwl/nest": "^14.4.0", - "@nrwl/next": "^14.4.0", "@nrwl/node": "^14.4.0", "@nrwl/nx-cloud": "^14.2.0", "@nrwl/react": "^14.4.0", @@ -120,11 +117,9 @@ "compression-webpack-plugin": "^10.0.0", "cross-env": "^7.0.3", "css-minimizer-webpack-plugin": "^4.0.0", - "cypress": "^10.4.0", "cz-customizable": "^5.3.0", "env-cmd": "^10.1.0", "eslint": "^8.19.0", - "eslint-config-next": "12.2.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-cypress": "^2.10.3", "eslint-plugin-filename-rules": "^1.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a632fb99bd..43a0b9910e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,8 +17,6 @@ importers: '@nrwl/jest': ^14.4.0 '@nrwl/js': ^14.4.0 '@nrwl/linter': ^14.4.0 - '@nrwl/nest': ^14.4.0 - '@nrwl/next': ^14.4.0 '@nrwl/node': ^14.4.0 '@nrwl/nx-cloud': ^14.2.0 '@nrwl/react': ^14.4.0 @@ -49,11 +47,9 @@ importers: core-js: ^3.23.3 cross-env: ^7.0.3 css-minimizer-webpack-plugin: ^4.0.0 - cypress: ^10.4.0 cz-customizable: ^5.3.0 env-cmd: ^10.1.0 eslint: ^8.19.0 - eslint-config-next: 12.2.0 eslint-config-prettier: ^8.5.0 eslint-plugin-cypress: ^2.10.3 eslint-plugin-filename-rules: ^1.2.0 @@ -71,7 +67,6 @@ importers: level: ^8.0.0 level-read-stream: 1.1.0 lint-staged: ^13.0.3 - next: 12.2.0 nx: ^14.4.0 prettier: ^2.7.1 react: ^18.2.0 @@ -101,7 +96,6 @@ importers: got: 12.1.0 level: 8.0.0 level-read-stream: 1.1.0 - next: 12.2.0_beenoklgwfttvph5dgxj7na7aq react: 18.2.0 react-dom: 18.2.0_react@18.2.0 react-router: 6.3.0_react@18.2.0 @@ -115,18 +109,16 @@ importers: '@headlessui/react': 1.6.5_biqbaboplfbrettd7655fr4n2y '@heroicons/react': 1.0.6_react@18.2.0 '@nrwl/cli': 14.4.2_@swc+core@1.2.210 - '@nrwl/cypress': 14.4.2_3xokhr63pvhsh24r6gmwyvbcfi + '@nrwl/cypress': 14.4.2_gtbxvtmh5ipj3piki3xg57n5fe '@nrwl/eslint-plugin-nx': 14.4.2_afsbewstkdex5d4fc6xnpjlnau '@nrwl/jest': 14.4.2_dltevkctzdxkrvyldbyepwbdle '@nrwl/js': 14.4.2_gtbxvtmh5ipj3piki3xg57n5fe '@nrwl/linter': 14.4.2_jqnzvbaca4rx3byobgjku3onji - '@nrwl/nest': 14.4.2_e6qtqvxbhokjbvzxuqyvhc6pli - '@nrwl/next': 14.4.2_tij6xbouytihgovru6qahme53a '@nrwl/node': 14.4.2_ehspof47b5bphcyk4536mwaw4u '@nrwl/nx-cloud': 14.2.0 - '@nrwl/react': 14.4.2_uzkaey7ewjmyys5ezff4uhptsm + '@nrwl/react': 14.4.2_46t6z7wulh2zjyi5wmxujdm57y '@nrwl/tao': 14.4.2_@swc+core@1.2.210 - '@nrwl/web': 14.4.2_hikps3f6ih4xnq3f4csrxvfvzu + '@nrwl/web': 14.4.2_7ggz7ibmlwrqtwusxeq53zzcym '@nrwl/workspace': 14.4.2_a22ftc74wzukohhtmp6cnnvzoq '@portabletext/react': 1.0.6_react@18.2.0 '@svgr/core': 6.2.1 @@ -149,11 +141,9 @@ importers: compression-webpack-plugin: 10.0.0_webpack@5.74.0 cross-env: 7.0.3 css-minimizer-webpack-plugin: 4.0.0_webpack@5.74.0 - cypress: 10.4.0 cz-customizable: 5.10.0 env-cmd: 10.1.0 eslint: 8.19.0 - eslint-config-next: 12.2.0_4x5o4skxv6sl53vpwefgt23khm eslint-config-prettier: 8.5.0_eslint@8.19.0 eslint-plugin-cypress: 2.12.1_eslint@8.19.0 eslint-plugin-filename-rules: 1.2.0 @@ -219,6 +209,12 @@ importers: mini-css-extract-plugin: 2.6.1_webpack@5.74.0 webpack: 5.74.0 + apps/ligo-virgo-e2e: + specifiers: + cypress: ^10.4.0 + devDependencies: + cypress: 10.4.0 + apps/venus: specifiers: '@emotion/react': ^11.10.0 @@ -244,14 +240,9 @@ importers: libs/components/account: specifiers: - '@authing/react-ui-components': ^3.1.39 '@emotion/styled': ^11.9.3 - authing-js-sdk: ^4.23.35 dependencies: - '@authing/react-ui-components': 3.1.39 '@emotion/styled': 11.9.3 - devDependencies: - authing-js-sdk: 4.23.35 libs/components/affine-board: specifiers: {} @@ -293,7 +284,7 @@ importers: '@tldraw/intersect': ^1.7.1 '@tldraw/vec': ^1.7.0 dependencies: - '@tldraw/core': 1.14.1_mobx@6.6.1 + '@tldraw/core': 1.14.1 '@tldraw/intersect': 1.7.1 '@tldraw/vec': 1.7.1 @@ -304,7 +295,7 @@ importers: '@tldraw/vec': ^1.7.0 perfect-freehand: ^1.0.16 dependencies: - '@tldraw/core': 1.14.1_mobx@6.6.1 + '@tldraw/core': 1.14.1 '@tldraw/intersect': 1.7.1 '@tldraw/vec': 1.7.1 perfect-freehand: 1.1.0 @@ -317,7 +308,7 @@ importers: idb-keyval: ^6.2.0 zustand: ^3.7.2 dependencies: - '@tldraw/core': 1.14.1_mobx@6.6.1 + '@tldraw/core': 1.14.1 '@tldraw/intersect': 1.7.1 '@tldraw/vec': 1.7.1 idb-keyval: 6.2.0 @@ -329,7 +320,7 @@ importers: '@tldraw/intersect': ^1.7.1 '@tldraw/vec': ^1.7.0 dependencies: - '@tldraw/core': 1.14.1_mobx@6.6.1 + '@tldraw/core': 1.14.1 '@tldraw/intersect': 1.7.1 '@tldraw/vec': 1.7.1 @@ -339,7 +330,7 @@ importers: '@tldraw/intersect': ^1.7.1 '@tldraw/vec': ^1.7.0 dependencies: - '@tldraw/core': 1.14.1_mobx@6.6.1 + '@tldraw/core': 1.14.1 '@tldraw/intersect': 1.7.1 '@tldraw/vec': 1.7.1 @@ -655,13 +646,11 @@ importers: libs/datasource/state: specifiers: - authing-js-sdk: ^4.23.35 firebase: ^9.9.2 jotai: ^1.7.4 dependencies: jotai: 1.7.4 devDependencies: - authing-js-sdk: 4.23.35 firebase: 9.9.2 libs/framework/virgo: @@ -691,105 +680,6 @@ packages: '@jridgewell/gen-mapping': 0.1.1 '@jridgewell/trace-mapping': 0.3.14 - /@angular-devkit/core/13.3.5: - resolution: {integrity: sha512-w7vzK4VoYP9rLgxJ2SwEfrkpKybdD+QgQZlsDBzT0C6Ebp7b4gkNcNVFo8EiZvfDl6Yplw2IAP7g7fs3STn0hQ==} - engines: {node: ^12.20.0 || ^14.15.0 || >=16.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - peerDependencies: - chokidar: ^3.5.2 - peerDependenciesMeta: - chokidar: - optional: true - dependencies: - ajv: 8.9.0 - ajv-formats: 2.1.1 - fast-json-stable-stringify: 2.1.0 - magic-string: 0.25.7 - rxjs: 6.6.7 - source-map: 0.7.3 - dev: true - - /@angular-devkit/schematics/13.3.5: - resolution: {integrity: sha512-0N/kL/Vfx0yVAEwa3HYxNx9wYb+G9r1JrLjJQQzDp+z9LtcojNf7j3oey6NXrDUs1WjVZOa/AIdRl3/DuaoG5w==} - engines: {node: ^12.20.0 || ^14.15.0 || >=16.10.0, npm: ^6.11.0 || ^7.5.6 || >=8.0.0, yarn: '>= 1.13.0'} - dependencies: - '@angular-devkit/core': 13.3.5 - jsonc-parser: 3.0.0 - magic-string: 0.25.7 - ora: 5.4.1 - rxjs: 6.6.7 - transitivePeerDependencies: - - chokidar - dev: true - - /@ant-design/colors/6.0.0: - resolution: {integrity: sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==} - dependencies: - '@ctrl/tinycolor': 3.4.1 - dev: false - - /@ant-design/icons-svg/4.2.1: - resolution: {integrity: sha512-EB0iwlKDGpG93hW8f85CTJTs4SvMX7tt5ceupvhALp1IF44SeUFOMhKUOYqpsoYWQKAOuTRDMqn75rEaKDp0Xw==} - dev: false - - /@ant-design/icons/4.7.0: - resolution: {integrity: sha512-aoB4Z7JA431rt6d4u+8xcNPPCrdufSRMUOpxa1ab6mz1JCQZOEVolj2WVs/tDFmN62zzK30mNelEsprLYsSF3g==} - engines: {node: '>=8'} - peerDependencies: - react: '>=16.0.0' - react-dom: '>=16.0.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@ant-design/colors': 6.0.0 - '@ant-design/icons-svg': 4.2.1 - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-util: 5.22.5 - dev: false - - /@ant-design/react-slick/0.29.2: - resolution: {integrity: sha512-kgjtKmkGHa19FW21lHnAfyyH9AAoh35pBdcJ53rHmQ3O+cfFHGHnUbj/HFrRNJ5vIts09FKJVAD8RpaC+RaWfA==} - peerDependencies: - react: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - json2mq: 0.2.0 - lodash: 4.17.21 - resize-observer-polyfill: 1.5.1 - dev: false - - /@authing/react-ui-components/3.1.39: - resolution: {integrity: sha512-DhPtbHbRSFtFv6XbKF+wiO7Y39UkgDaREBNai7VwKfv8LCOP/SfPdockQpGWHKh29AdbaHEMq+ExDvhpkNsPDw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - antd: 4.21.5 - authing-js-sdk: 4.23.35 - fastclick: 1.0.6 - global: 4.4.0 - phone: 3.1.22 - qs: 6.11.0 - react-responsive: 9.0.0-beta.10 - react-use: 17.4.0 - ua-parser-js: 1.0.2 - wildcard: 1.1.2 - transitivePeerDependencies: - - supports-color - dev: false - /@babel/code-frame/7.18.6: resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} engines: {node: '>=6.9.0'} @@ -2588,11 +2478,6 @@ packages: '@jridgewell/trace-mapping': 0.3.9 dev: true - /@ctrl/tinycolor/3.4.1: - resolution: {integrity: sha512-ej5oVy6lykXsvieQtqZxCOaLT+xD4+QNarq78cIYISHmZXshCvROLudpQN3lfL8G0NL7plMSSK+zlyvCaIJ4Iw==} - engines: {node: '>=10'} - dev: false - /@cypress/request/2.88.10: resolution: {integrity: sha512-Zp7F+R93N0yZyG34GutyTNr+okam7s/Fzc1+i3kcqOP8vk6OuajuE9qZJ6Rs+10/1JFtXFYMdyarnU1rZuJesg==} engines: {node: '>= 6'} @@ -5074,134 +4959,6 @@ packages: yargs: 17.5.1 dev: false - /@nestjs/schematics/8.0.11_typescript@4.7.4: - resolution: {integrity: sha512-W/WzaxgH5aE01AiIErE9QrQJ73VR/M/8p8pq0LZmjmNcjZqU5kQyOWUxZg13WYfSpJdOa62t6TZRtFDmgZPoIg==} - peerDependencies: - typescript: ^3.4.5 || ^4.3.5 - dependencies: - '@angular-devkit/core': 13.3.5 - '@angular-devkit/schematics': 13.3.5 - fs-extra: 10.1.0 - jsonc-parser: 3.0.0 - pluralize: 8.0.0 - typescript: 4.7.4 - transitivePeerDependencies: - - chokidar - dev: true - - /@next/env/12.2.0: - resolution: {integrity: sha512-/FCkDpL/8SodJEXvx/DYNlOD5ijTtkozf4PPulYPtkPOJaMPpBSOkzmsta4fnrnbdH6eZjbwbiXFdr6gSQCV4w==} - - /@next/eslint-plugin-next/12.2.0: - resolution: {integrity: sha512-nIj5xV/z3dOfeBnE7qFAjUQZAi4pTlIMuusRM6s/T6lOz8x7mjY5s1ZkTUBmcjPVCb2VIv3CrMH0WZL6xfjZZg==} - dependencies: - glob: 7.1.7 - dev: true - - /@next/swc-android-arm-eabi/12.2.0: - resolution: {integrity: sha512-hbneH8DNRB2x0Nf5fPCYoL8a0osvdTCe4pvOc9Rv5CpDsoOlf8BWBs2OWpeP0U2BktGvIsuUhmISmdYYGyrvTw==} - engines: {node: '>= 10'} - cpu: [arm] - os: [android] - requiresBuild: true - optional: true - - /@next/swc-android-arm64/12.2.0: - resolution: {integrity: sha512-1eEk91JHjczcJomxJ8X0XaUeNcp5Lx1U2Ic7j15ouJ83oRX+3GIslOuabW2oPkSgXbHkThMClhirKpvG98kwZg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [android] - requiresBuild: true - optional: true - - /@next/swc-darwin-arm64/12.2.0: - resolution: {integrity: sha512-x5U5gJd7ZvrEtTFnBld9O2bUlX8opu7mIQUqRzj7KeWzBwPhrIzTTsQXAiNqsaMuaRPvyHBVW/5d/6g6+89Y8g==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optional: true - - /@next/swc-darwin-x64/12.2.0: - resolution: {integrity: sha512-iwMNFsrAPjfedjKDv9AXPAV16PWIomP3qw/FfPaxkDVRbUls7BNdofBLzkQmqxqWh93WrawLwaqyXpJuAaiwJA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - optional: true - - /@next/swc-freebsd-x64/12.2.0: - resolution: {integrity: sha512-gRiAw8g3Akf6niTDLEm1Emfa7jXDjvaAj/crDO8hKASKA4Y1fS4kbi/tyWw5VtoFI4mUzRmCPmZ8eL0tBSG58A==} - engines: {node: '>= 10'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - optional: true - - /@next/swc-linux-arm-gnueabihf/12.2.0: - resolution: {integrity: sha512-/TJZkxaIpeEwnXh6A40trgwd40C5+LJroLUOEQwMOJdavLl62PjCA6dGl1pgooWLCIb5YdBQ0EG4ylzvLwS2+Q==} - engines: {node: '>= 10'} - cpu: [arm] - os: [linux] - requiresBuild: true - optional: true - - /@next/swc-linux-arm64-gnu/12.2.0: - resolution: {integrity: sha512-++WAB4ElXCSOKG9H8r4ENF8EaV+w0QkrpjehmryFkQXmt5juVXz+nKDVlCRMwJU7A1O0Mie82XyEoOrf6Np1pA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - - /@next/swc-linux-arm64-musl/12.2.0: - resolution: {integrity: sha512-XrqkHi/VglEn5zs2CYK6ofJGQySrd+Lr4YdmfJ7IhsCnMKkQY1ma9Hv5THwhZVof3e+6oFHrQ9bWrw9K4WTjFA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - optional: true - - /@next/swc-linux-x64-gnu/12.2.0: - resolution: {integrity: sha512-MyhHbAKVjpn065WzRbqpLu2krj4kHLi6RITQdD1ee+uxq9r2yg5Qe02l24NxKW+1/lkmpusl4Y5Lks7rBiJn4w==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - - /@next/swc-linux-x64-musl/12.2.0: - resolution: {integrity: sha512-Tz1tJZ5egE0S/UqCd5V6ZPJsdSzv/8aa7FkwFmIJ9neLS8/00za+OY5pq470iZQbPrkTwpKzmfTTIPRVD5iqDg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - optional: true - - /@next/swc-win32-arm64-msvc/12.2.0: - resolution: {integrity: sha512-0iRO/CPMCdCYUzuH6wXLnsfJX1ykBX4emOOvH0qIgtiZM0nVYbF8lkEyY2ph4XcsurpinS+ziWuYCXVqrOSqiw==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - optional: true - - /@next/swc-win32-ia32-msvc/12.2.0: - resolution: {integrity: sha512-8A26RJVcJHwIKm8xo/qk2ePRquJ6WCI2keV2qOW/Qm+ZXrPXHMIWPYABae/nKN243YFBNyPiHytjX37VrcpUhg==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - requiresBuild: true - optional: true - - /@next/swc-win32-x64-msvc/12.2.0: - resolution: {integrity: sha512-OI14ozFLThEV3ey6jE47zrzSTV/6eIMsvbwozo+XfdWqOPwQ7X00YkRx4GVMKMC0rM44oGS2gmwMKYpe4EblnA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - requiresBuild: true - optional: true - /@nodelib/fs.scandir/2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -5238,7 +4995,7 @@ packages: - '@swc/core' dev: true - /@nrwl/cypress/14.4.2_3xokhr63pvhsh24r6gmwyvbcfi: + /@nrwl/cypress/14.4.2_gtbxvtmh5ipj3piki3xg57n5fe: resolution: {integrity: sha512-vek4tJYzaJwnLgeJLAJKWuCmtE+XWCq6IgmCl/4G/lWxTWGzlJ19ZK8MoCEiJqbnNYeoHZPxoaAGwyBAbVuO3w==} peerDependencies: cypress: '>= 3 < 10' @@ -5254,7 +5011,6 @@ packages: '@nrwl/workspace': 14.4.2_a22ftc74wzukohhtmp6cnnvzoq babel-loader: 8.2.5_m3opitmgss2x7fiy6klia7uvaa chalk: 4.1.0 - cypress: 10.4.0 enhanced-resolve: 5.10.0 fork-ts-checker-webpack-plugin: 6.2.10_wln64xm7gyszy6wbwhdijmigya rxjs: 6.6.7 @@ -5412,101 +5168,6 @@ packages: - utf-8-validate dev: true - /@nrwl/nest/14.4.2_e6qtqvxbhokjbvzxuqyvhc6pli: - resolution: {integrity: sha512-TVlY7UbWQLMjQyCwkos8IkLzhKz/58IPUqoE3Jr9syf8KJ+JCkVxndEcUSPMlEJWtfxdEjchNrOwZH5bWpZPBw==} - dependencies: - '@nestjs/schematics': 8.0.11_typescript@4.7.4 - '@nrwl/devkit': 14.4.2_nx@14.4.2 - '@nrwl/jest': 14.4.2_dltevkctzdxkrvyldbyepwbdle - '@nrwl/js': 14.4.2_gtbxvtmh5ipj3piki3xg57n5fe - '@nrwl/linter': 14.4.2_jqnzvbaca4rx3byobgjku3onji - '@nrwl/node': 14.4.2_ehspof47b5bphcyk4536mwaw4u - transitivePeerDependencies: - - '@swc-node/register' - - '@swc/core' - - '@swc/wasm' - - '@types/node' - - bufferutil - - canvas - - chokidar - - esbuild - - eslint - - node-notifier - - nx - - prettier - - supports-color - - ts-node - - typescript - - uglify-js - - utf-8-validate - - vue-template-compiler - - webpack-cli - dev: true - - /@nrwl/next/14.4.2_tij6xbouytihgovru6qahme53a: - resolution: {integrity: sha512-T8F8Fy7jJ7dNhLET14FhslD9lGzpUrzOQQfES5mb8LK0Y3kNyumGfCetAuFwkUEp/7aC5FxsZSc/32l4b6dxZA==} - peerDependencies: - next: ^12.1.0 - dependencies: - '@babel/plugin-proposal-decorators': 7.18.6_@babel+core@7.18.6 - '@nrwl/cypress': 14.4.2_3xokhr63pvhsh24r6gmwyvbcfi - '@nrwl/devkit': 14.4.2_nx@14.4.2 - '@nrwl/jest': 14.4.2_dltevkctzdxkrvyldbyepwbdle - '@nrwl/linter': 14.4.2_jqnzvbaca4rx3byobgjku3onji - '@nrwl/react': 14.4.2_uzkaey7ewjmyys5ezff4uhptsm - '@nrwl/web': 14.4.2_hikps3f6ih4xnq3f4csrxvfvzu - '@nrwl/workspace': 14.4.2_a22ftc74wzukohhtmp6cnnvzoq - '@svgr/webpack': 6.2.1 - chalk: 4.1.0 - eslint-config-next: 12.2.0_4x5o4skxv6sl53vpwefgt23khm - fs-extra: 10.1.0 - next: 12.2.0_beenoklgwfttvph5dgxj7na7aq - ts-node: 10.8.2_y42jqzo3jkzuv3kp7opavo2xbi - tsconfig-paths: 3.14.1 - url-loader: 4.1.1_webpack@5.74.0 - webpack-merge: 5.8.0 - transitivePeerDependencies: - - '@babel/core' - - '@parcel/css' - - '@swc-node/register' - - '@swc/core' - - '@swc/wasm' - - '@types/babel__core' - - '@types/node' - - '@types/webpack' - - '@typescript-eslint/parser' - - bufferutil - - canvas - - clean-css - - csso - - cypress - - debug - - esbuild - - eslint - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - fibers - - file-loader - - html-webpack-plugin - - node-notifier - - node-sass - - nx - - prettier - - sass-embedded - - sockjs-client - - supports-color - - type-fest - - typescript - - uglify-js - - utf-8-validate - - vue-template-compiler - - webpack - - webpack-cli - - webpack-dev-server - - webpack-hot-middleware - - webpack-plugin-serve - dev: true - /@nrwl/node/14.4.2_ehspof47b5bphcyk4536mwaw4u: resolution: {integrity: sha512-YMolQH3R/DTyPap3fQFWXvBaKJQG6l+msAUqzHp5OML3lPDg+zBYGW2kD1IsXpYq/ccpaot1ePS5K0JDpbZ8zQ==} dependencies: @@ -5568,18 +5229,18 @@ packages: - debug dev: true - /@nrwl/react/14.4.2_uzkaey7ewjmyys5ezff4uhptsm: + /@nrwl/react/14.4.2_46t6z7wulh2zjyi5wmxujdm57y: resolution: {integrity: sha512-5OlTpa5wRgADkNuP55Ii0myZLqzcefwR+lMRSBFquwOzxQ5VEU9JCyZVeO4pBdVr1ibbIJoj1EfO+NnVpCtELg==} dependencies: '@babel/core': 7.18.6 '@babel/preset-react': 7.18.6_@babel+core@7.18.6 - '@nrwl/cypress': 14.4.2_3xokhr63pvhsh24r6gmwyvbcfi + '@nrwl/cypress': 14.4.2_gtbxvtmh5ipj3piki3xg57n5fe '@nrwl/devkit': 14.4.2_nx@14.4.2 '@nrwl/jest': 14.4.2_dltevkctzdxkrvyldbyepwbdle '@nrwl/js': 14.4.2_gtbxvtmh5ipj3piki3xg57n5fe '@nrwl/linter': 14.4.2_jqnzvbaca4rx3byobgjku3onji - '@nrwl/storybook': 14.4.2_yflzlx5dxniwxy53i7vvsdpbmy - '@nrwl/web': 14.4.2_hikps3f6ih4xnq3f4csrxvfvzu + '@nrwl/storybook': 14.4.2_brofqo76x5gdh2qufyuyzjmfne + '@nrwl/web': 14.4.2_7ggz7ibmlwrqtwusxeq53zzcym '@nrwl/workspace': 14.4.2_a22ftc74wzukohhtmp6cnnvzoq '@pmmmwh/react-refresh-webpack-plugin': 0.5.7_bgbvhssx5jbdjtmrq4m55itcsu '@storybook/node-logger': 6.1.20 @@ -5635,10 +5296,10 @@ packages: - webpack-plugin-serve dev: true - /@nrwl/storybook/14.4.2_yflzlx5dxniwxy53i7vvsdpbmy: + /@nrwl/storybook/14.4.2_brofqo76x5gdh2qufyuyzjmfne: resolution: {integrity: sha512-G6h3jQT+pIY0RAEbeclguEFSAIXsToRVKEeRyq1bk6fWJHy7y//bCeJrINL9xPf9zk12cWyKkjJvwsOcy0Z1Mw==} dependencies: - '@nrwl/cypress': 14.4.2_3xokhr63pvhsh24r6gmwyvbcfi + '@nrwl/cypress': 14.4.2_gtbxvtmh5ipj3piki3xg57n5fe '@nrwl/devkit': 14.4.2_nx@14.4.2 '@nrwl/linter': 14.4.2_jqnzvbaca4rx3byobgjku3onji '@nrwl/workspace': 14.4.2_a22ftc74wzukohhtmp6cnnvzoq @@ -5677,7 +5338,7 @@ packages: - '@swc/core' dev: true - /@nrwl/web/14.4.2_hikps3f6ih4xnq3f4csrxvfvzu: + /@nrwl/web/14.4.2_7ggz7ibmlwrqtwusxeq53zzcym: resolution: {integrity: sha512-x00dE67yDRC3zmVEdO1HdtIbPezZ5gSKmNmEL2++PrA6AUz3a+f7/Ahhs4ALxnEPx1oDRLzM5OxRb5w6kLmGfw==} dependencies: '@babel/core': 7.18.6 @@ -5688,7 +5349,7 @@ packages: '@babel/preset-env': 7.18.6_@babel+core@7.18.6 '@babel/preset-typescript': 7.18.6_@babel+core@7.18.6 '@babel/runtime': 7.18.6 - '@nrwl/cypress': 14.4.2_3xokhr63pvhsh24r6gmwyvbcfi + '@nrwl/cypress': 14.4.2_gtbxvtmh5ipj3piki3xg57n5fe '@nrwl/devkit': 14.4.2_nx@14.4.2 '@nrwl/jest': 14.4.2_dltevkctzdxkrvyldbyepwbdle '@nrwl/js': 14.4.2_gtbxvtmh5ipj3piki3xg57n5fe @@ -6133,10 +5794,6 @@ packages: picomatch: 2.3.1 dev: true - /@rushstack/eslint-patch/1.1.4: - resolution: {integrity: sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==} - dev: true - /@sinclair/typebox/0.23.5: resolution: {integrity: sha512-AFBVi/iT4g20DHoujvMH1aEDn8fGJh4xsRGCP6d8RpLPMqsNPvW01Jcn0QysXTsg++/xj25NmJsGyH9xug/wKg==} dev: true @@ -6498,11 +6155,6 @@ packages: '@swc/core-win32-ia32-msvc': 1.2.210 '@swc/core-win32-x64-msvc': 1.2.210 - /@swc/helpers/0.4.2: - resolution: {integrity: sha512-556Az0VX7WR6UdoTn4htt/l3zPQ7bsQWK+HqdG4swV7beUCxo/BqmvbOpUkTIm/9ih86LIf1qsUnywNL3obGHw==} - dependencies: - tslib: 2.4.0 - /@swc/helpers/0.4.3: resolution: {integrity: sha512-6JrF+fdUK2zbGpJIlN7G3v966PQjyx/dPt1T9km2wj+EUBqgrxCk3uX4Kct16MIm9gGxfKRcfax2hVf5jvlTzA==} dependencies: @@ -6585,6 +6237,28 @@ packages: react-dom: 18.2.0_react@18.2.0 dev: true + /@tldraw/core/1.14.1: + resolution: {integrity: sha512-FAiX/TD/tl5eMvTk0IHhFUSmldCe/UTTOnLL5aWQHqhicF/iTP5m3H12L6kyjN60yfssN8U9g4E/7y70TY7JxA==} + peerDependencies: + react: '>=16.8' + react-dom: '>=16.8' + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + dependencies: + '@tldraw/intersect': 1.7.1 + '@tldraw/vec': 1.7.1 + '@use-gesture/react': 10.2.16 + mobx-react-lite: 3.4.0 + perfect-freehand: 1.1.0 + resize-observer-polyfill: 1.5.1 + transitivePeerDependencies: + - mobx + - react-native + dev: false + /@tldraw/core/1.14.1_mobx@6.6.1: resolution: {integrity: sha512-FAiX/TD/tl5eMvTk0IHhFUSmldCe/UTTOnLL5aWQHqhicF/iTP5m3H12L6kyjN60yfssN8U9g4E/7y70TY7JxA==} peerDependencies: @@ -6850,10 +6524,6 @@ packages: pretty-format: 28.1.1 dev: true - /@types/js-cookie/2.2.7: - resolution: {integrity: sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA==} - dev: false - /@types/json-buffer/3.0.0: resolution: {integrity: sha512-3YP80IxxFJB4b5tYC2SUPwkg0XQLiu0nWvhRgEatgjf+29IcWO9X1k8xRv5DGssJ/lCrjYTjQPcobJr2yWIVuQ==} dev: false @@ -7344,10 +7014,6 @@ packages: '@webassemblyjs/ast': 1.11.1 '@xtuc/long': 4.2.2 - /@xobotyi/scrollbar-width/1.9.5: - resolution: {integrity: sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==} - dev: false - /@xtuc/ieee754/1.2.0: resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} @@ -7495,15 +7161,6 @@ packages: uri-js: 4.4.1 dev: true - /ajv/8.9.0: - resolution: {integrity: sha512-qOKJyNj/h+OWx7s5DePL6Zu1KeM9jPZhwBqs+7DzP6bGOvqzVCSf0xueYmVuaC/oQ/VtS2zLMLHdQFbkka+XDQ==} - dependencies: - fast-deep-equal: 3.1.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - uri-js: 4.4.1 - dev: true - /ansi-colors/4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} @@ -7573,63 +7230,6 @@ packages: engines: {node: '>=12'} dev: true - /antd/4.21.5: - resolution: {integrity: sha512-S6L29rmbiQvE4/kn1hPBscHFZ405Pbtuw3DCpXVnMt409JtY6sDaUbUcWfl4i21XkABEogKzqxjYVGogf1QIWQ==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@ant-design/colors': 6.0.0 - '@ant-design/icons': 4.7.0 - '@ant-design/react-slick': 0.29.2 - '@babel/runtime': 7.18.6 - '@ctrl/tinycolor': 3.4.1 - classnames: 2.3.1 - copy-to-clipboard: 3.3.1 - lodash: 4.17.21 - memoize-one: 6.0.0 - moment: 2.29.3 - rc-cascader: 3.6.1 - rc-checkbox: 2.3.2 - rc-collapse: 3.3.1 - rc-dialog: 8.9.0 - rc-drawer: 4.4.3 - rc-dropdown: 4.0.1 - rc-field-form: 1.26.7 - rc-image: 5.7.0 - rc-input: 0.0.1-alpha.7 - rc-input-number: 7.3.4 - rc-mentions: 1.8.0 - rc-menu: 9.6.0 - rc-motion: 2.6.0 - rc-notification: 4.6.0 - rc-pagination: 3.1.17 - rc-picker: 2.6.10 - rc-progress: 3.3.3 - rc-rate: 2.9.2 - rc-resize-observer: 1.2.0 - rc-segmented: 2.1.0 - rc-select: 14.1.8 - rc-slider: 10.0.0 - rc-steps: 4.1.4 - rc-switch: 3.2.2 - rc-table: 7.24.3 - rc-tabs: 11.16.0 - rc-textarea: 0.3.7 - rc-tooltip: 5.1.1 - rc-tree: 5.6.5 - rc-tree-select: 5.4.0 - rc-trigger: 5.3.1 - rc-upload: 4.3.4 - rc-util: 5.22.5 - scroll-into-view-if-needed: 2.2.29 - dev: false - /anymatch/3.1.2: resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} engines: {node: '>= 8'} @@ -7706,10 +7306,6 @@ packages: is-string: 1.0.7 dev: true - /array-tree-filter/2.1.0: - resolution: {integrity: sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==} - dev: false - /array-union/2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} @@ -7782,10 +7378,6 @@ packages: dev: false optional: true - /async-validator/4.2.5: - resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} - dev: false - /async/2.6.4: resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==} dependencies: @@ -7822,6 +7414,7 @@ packages: sm-crypto: 0.3.8 transitivePeerDependencies: - supports-color + dev: false /autoprefixer/10.4.7_postcss@8.4.14: resolution: {integrity: sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==} @@ -7880,6 +7473,7 @@ packages: follow-redirects: 1.5.10 transitivePeerDependencies: - supports-color + dev: false /axios/0.21.4: resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} @@ -8694,11 +8288,6 @@ packages: dependencies: mimic-response: 1.0.1 - /clone/1.0.4: - resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} - engines: {node: '>=0.8'} - dev: true - /clsx/1.2.0: resolution: {integrity: sha512-EPRP7XJsM1y0iCU3Z7C7jFKdQboXSeHgEfzQUTlz7m5NP3hDrlz48aUsmNGp4pC+JOW9WA3vIRqlYuo/bl4Drw==} engines: {node: '>=6'} @@ -9060,6 +8649,7 @@ packages: /crypto-js/4.1.1: resolution: {integrity: sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==} + dev: false /css-declaration-sorter/6.3.0_postcss@8.4.14: resolution: {integrity: sha512-OGT677UGHJTAVMRhPO+HJ4oKln3wkBTwtDFH0ojbqm+MJm6xuDMHp2nkhh/ThaBqq20IbraBQSWKfSLNHQO9Og==} @@ -9070,13 +8660,6 @@ packages: postcss: 8.4.14 dev: true - /css-in-js-utils/2.0.1: - resolution: {integrity: sha512-PJF0SpJT+WdbVVt0AOYp9C8GnuruRlL/UFW7932nLWmFLQTaWEzTBQEx7/hn4BuV+WON75iAViSUJLiU3PKbpA==} - dependencies: - hyphenate-style-name: 1.0.4 - isobject: 3.0.1 - dev: false - /css-loader/6.7.1_webpack@5.74.0: resolution: {integrity: sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==} engines: {node: '>= 12.13.0'} @@ -9097,10 +8680,6 @@ packages: webpack: 5.74.0_@swc+core@1.2.210 dev: true - /css-mediaquery/0.1.2: - resolution: {integrity: sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q==} - dev: false - /css-minimizer-webpack-plugin/3.4.1_webpack@5.74.0: resolution: {integrity: sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==} engines: {node: '>= 12.13.0'} @@ -9177,6 +8756,7 @@ packages: dependencies: mdn-data: 2.0.14 source-map: 0.6.1 + dev: true /css-what/6.1.0: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} @@ -9368,6 +8948,7 @@ packages: /dayjs/1.11.3: resolution: {integrity: sha512-xxwlswWOlGhzgQ4TKzASQkUhqERI3egRNqgV4ScR8wlANA/A9tZ7miXa44vTTKEq5l7vWoL5G57bG3zA+Kow0A==} + dev: true /debug/2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} @@ -9533,12 +9114,6 @@ packages: execa: 5.1.1 dev: true - /defaults/1.0.3: - resolution: {integrity: sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==} - dependencies: - clone: 1.0.4 - dev: true - /defer-to-connect/2.0.1: resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} engines: {node: '>=10'} @@ -9650,10 +9225,6 @@ packages: resolution: {integrity: sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg==} dev: true - /dom-align/1.12.3: - resolution: {integrity: sha512-Gj9hZN3a07cbR6zviMUBOMPdWxYhbMI+x+WS0NAIu2zFZmbK8ys9R79g+iG9qLnlCwpFoaB+fKy8Pdv470GsPA==} - dev: false - /dom-converter/0.2.0: resolution: {integrity: sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==} dependencies: @@ -9675,10 +9246,6 @@ packages: entities: 2.2.0 dev: true - /dom-walk/0.1.2: - resolution: {integrity: sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==} - dev: false - /domelementtype/2.3.0: resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} dev: true @@ -9906,6 +9473,7 @@ packages: resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} dependencies: stackframe: 1.3.4 + dev: true /es-abstract/1.20.1: resolution: {integrity: sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==} @@ -9990,31 +9558,6 @@ packages: source-map: 0.6.1 dev: true - /eslint-config-next/12.2.0_4x5o4skxv6sl53vpwefgt23khm: - resolution: {integrity: sha512-QWzNegadFXjQ0h3hixnLacRM9Kot85vQefyNsA8IeOnERZMz0Gvays1W6DMCjSxJbnCwuWaMXj9DCpar5IahRA==} - peerDependencies: - eslint: ^7.23.0 || ^8.0.0 - typescript: '>=3.3.1' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@next/eslint-plugin-next': 12.2.0 - '@rushstack/eslint-patch': 1.1.4 - '@typescript-eslint/parser': 5.30.5_4x5o4skxv6sl53vpwefgt23khm - eslint: 8.19.0 - eslint-import-resolver-node: 0.3.6 - eslint-import-resolver-typescript: 2.7.1_q2xwze32dd33a2fc2qubwr4ie4 - eslint-plugin-import: 2.26.0_6o2fuefo7gfpbr7nbqwgu7w4mq - eslint-plugin-jsx-a11y: 6.6.0_eslint@8.19.0 - eslint-plugin-react: 7.30.1_eslint@8.19.0 - eslint-plugin-react-hooks: 4.6.0_eslint@8.19.0 - typescript: 4.7.4 - transitivePeerDependencies: - - eslint-import-resolver-webpack - - supports-color - dev: true - /eslint-config-prettier/8.5.0_eslint@8.19.0: resolution: {integrity: sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==} hasBin: true @@ -10033,24 +9576,6 @@ packages: - supports-color dev: true - /eslint-import-resolver-typescript/2.7.1_q2xwze32dd33a2fc2qubwr4ie4: - resolution: {integrity: sha512-00UbgGwV8bSgUv34igBDbTOtKhqoRMy9bFjNehT40bXg6585PNIct8HhXZ0SybqB9rWtXj9crcku8ndDn/gIqQ==} - engines: {node: '>=4'} - peerDependencies: - eslint: '*' - eslint-plugin-import: '*' - dependencies: - debug: 4.3.4 - eslint: 8.19.0 - eslint-plugin-import: 2.26.0_6o2fuefo7gfpbr7nbqwgu7w4mq - glob: 7.2.3 - is-glob: 4.0.3 - resolve: 1.22.1 - tsconfig-paths: 3.14.1 - transitivePeerDependencies: - - supports-color - dev: true - /eslint-module-utils/2.7.3_ea34krk32wbcqzxapvwr7rsjs4: resolution: {integrity: sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==} engines: {node: '>=4'} @@ -10077,33 +9602,6 @@ packages: - supports-color dev: true - /eslint-module-utils/2.7.3_ngc5pgxzrdnldt43xbcfncn6si: - resolution: {integrity: sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint-import-resolver-node: '*' - eslint-import-resolver-typescript: '*' - eslint-import-resolver-webpack: '*' - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - eslint-import-resolver-node: - optional: true - eslint-import-resolver-typescript: - optional: true - eslint-import-resolver-webpack: - optional: true - dependencies: - '@typescript-eslint/parser': 5.30.5_4x5o4skxv6sl53vpwefgt23khm - debug: 3.2.7 - eslint-import-resolver-node: 0.3.6 - eslint-import-resolver-typescript: 2.7.1_q2xwze32dd33a2fc2qubwr4ie4 - find-up: 2.1.0 - transitivePeerDependencies: - - supports-color - dev: true - /eslint-plugin-cypress/2.12.1_eslint@8.19.0: resolution: {integrity: sha512-c2W/uPADl5kospNDihgiLc7n87t5XhUbFDoTl6CfVkmG+kDAb5Ux10V9PoLPu9N+r7znpc+iQlcmAqT1A/89HA==} peerDependencies: @@ -10118,37 +9616,6 @@ packages: engines: {node: '>=6.0.0'} dev: true - /eslint-plugin-import/2.26.0_6o2fuefo7gfpbr7nbqwgu7w4mq: - resolution: {integrity: sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==} - engines: {node: '>=4'} - peerDependencies: - '@typescript-eslint/parser': '*' - eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 - peerDependenciesMeta: - '@typescript-eslint/parser': - optional: true - dependencies: - '@typescript-eslint/parser': 5.30.5_4x5o4skxv6sl53vpwefgt23khm - array-includes: 3.1.5 - array.prototype.flat: 1.3.0 - debug: 2.6.9 - doctrine: 2.1.0 - eslint: 8.19.0 - eslint-import-resolver-node: 0.3.6 - eslint-module-utils: 2.7.3_ngc5pgxzrdnldt43xbcfncn6si - has: 1.0.3 - is-core-module: 2.9.0 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.values: 1.1.5 - resolve: 1.22.1 - tsconfig-paths: 3.14.1 - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - dev: true - /eslint-plugin-import/2.26.0_iom7pm3yknyiblqpw2vvqvxs5i: resolution: {integrity: sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==} engines: {node: '>=4'} @@ -10672,10 +10139,6 @@ packages: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} dev: true - /fast-shallow-equal/1.0.0: - resolution: {integrity: sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==} - dev: false - /fast-sort/3.2.0: resolution: {integrity: sha512-EgQtkmWo2Icq6uei57fTrZAKayL9b4OISU1613737AuLcIbAZ57tcOtGaK2A7zO54kk97wOnSw6INDA++rjMAQ==} dev: false @@ -10685,14 +10148,6 @@ packages: dev: false optional: true - /fastclick/1.0.6: - resolution: {integrity: sha512-cXyDBT4g0uWl/Xe75QspBDAgAWQ0lkPi/zgp6YFEUHj6WV6VIZl7R6TiDZhdOVU3W4ehp/8tG61Jev1jit+ztQ==} - dev: false - - /fastest-stable-stringify/2.0.2: - resolution: {integrity: sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==} - dev: false - /fastq/1.13.0: resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} dependencies: @@ -10999,6 +10454,7 @@ packages: debug: 3.1.0 transitivePeerDependencies: - supports-color + dev: false /for-each/0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} @@ -11348,17 +10804,6 @@ packages: path-is-absolute: 1.0.1 dev: true - /glob/7.1.7: - resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==} - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - /glob/7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} dependencies: @@ -11377,13 +10822,6 @@ packages: ini: 2.0.0 dev: true - /global/4.4.0: - resolution: {integrity: sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==} - dependencies: - min-document: 2.19.0 - process: 0.11.10 - dev: false - /globals/11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} @@ -11931,10 +11369,6 @@ packages: hasBin: true dev: true - /hyphenate-style-name/1.0.4: - resolution: {integrity: sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==} - dev: false - /iconv-lite/0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -12126,12 +11560,6 @@ packages: resolution: {integrity: sha512-FBxbgh1+ziiPFA09s0JgYtB7gRYfbfVrcO1sTv2JnPwbbz0M35zSYVUR3oyrTfLo/S+sbY4JG1W16hY91Hbh/Q==} dev: false - /inline-style-prefixer/6.0.1: - resolution: {integrity: sha512-AsqazZ8KcRzJ9YPN1wMH2aNM7lkWQ8tSPrW5uDk1ziYwiAPWSZnUsC7lfZq+BDqLqz0B4Pho5wscWcJzVvRzDQ==} - dependencies: - css-in-js-utils: 2.0.1 - dev: false - /inquirer/6.5.2: resolution: {integrity: sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==} engines: {node: '>=6.0.0'} @@ -12308,11 +11736,6 @@ packages: is-path-inside: 3.0.3 dev: true - /is-interactive/1.0.0: - resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} - engines: {node: '>=8'} - dev: true - /is-module/1.0.0: resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} dev: true @@ -12489,6 +11912,7 @@ packages: /isobject/3.0.1: resolution: {integrity: sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==} engines: {node: '>=0.10.0'} + dev: true /isomorphic.js/0.2.5: resolution: {integrity: sha512-PIeMbHqMt4DnUP3MA/Flc0HElYjMXArsw1qwJZcm9sqR8mq3l8NYizFMty0pWwE/tzIGH3EKK5+jes5mAr85yw==} @@ -13400,10 +12824,6 @@ packages: optional: true dev: false - /js-cookie/2.2.1: - resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==} - dev: false - /js-logger/1.6.1: resolution: {integrity: sha512-yTgMCPXVjhmg28CuUH8CKjU+cIKL/G+zTu4Fn4lQxs8mRFH/03QTNvEFngcxfg/gRDiQAOoyCKmMTOm9ayOzXA==} dev: false @@ -13432,6 +12852,7 @@ packages: /jsbn/1.1.0: resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} + dev: false /jsdom/16.7.0: resolution: {integrity: sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==} @@ -13477,6 +12898,7 @@ packages: /jsencrypt/3.2.1: resolution: {integrity: sha512-k1sD5QV0KPn+D8uG9AdGzTQuamt82QZ3A3l6f7TRwMU6Oi2Vg0BsL+wZIQBONcraO1pc78ExMdvmBBJ8WhNYUA==} + dev: false /jsesc/0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} @@ -13525,12 +12947,6 @@ packages: resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} dev: true - /json2mq/0.2.0: - resolution: {integrity: sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==} - dependencies: - string-convert: 0.2.1 - dev: false - /json5/1.0.1: resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==} hasBin: true @@ -13664,6 +13080,7 @@ packages: /jwt-decode/2.2.0: resolution: {integrity: sha512-86GgN2vzfUu7m9Wcj63iUkuDzFNYFVmjeDm2GzWpUk+opB0pEpMsw6ePCMrhYkumz2C1ihqtZzOMAg7FiXcNoQ==} + dev: false /keyv/3.0.0: resolution: {integrity: sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA==} @@ -14184,12 +13601,6 @@ packages: hasBin: true dev: true - /magic-string/0.25.7: - resolution: {integrity: sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==} - dependencies: - sourcemap-codec: 1.4.8 - dev: true - /magic-string/0.25.9: resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} dependencies: @@ -14230,14 +13641,9 @@ packages: tmpl: 1.0.5 dev: true - /matchmediaquery/0.3.1: - resolution: {integrity: sha512-Hlk20WQHRIm9EE9luN1kjRjYXAQToHOIAHPJn9buxBwuhfTHoKUcX+lXBbxc85DVQfXYbEQ4HcwQdd128E3qHQ==} - dependencies: - css-mediaquery: 0.1.2 - dev: false - /mdn-data/2.0.14: resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + dev: true /media-typer/0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} @@ -14255,10 +13661,6 @@ packages: resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==} dev: false - /memoize-one/6.0.0: - resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} - dev: false - /merge-descriptors/1.0.1: resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} dev: true @@ -14331,12 +13733,6 @@ packages: engines: {node: '>=10'} dev: false - /min-document/2.19.0: - resolution: {integrity: sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==} - dependencies: - dom-walk: 0.1.2 - dev: false - /mini-css-extract-plugin/1.6.2: resolution: {integrity: sha512-WhDvO3SjGm40oV5y26GjMJYjd2UMqrLAGKy5YS2/3QKJy2F7jgynuHTir/tgUUOiNQu5saXHdc8reo7YuhhT4Q==} engines: {node: '>= 10.13.0'} @@ -14451,6 +13847,22 @@ packages: hasBin: true dev: true + /mobx-react-lite/3.4.0: + resolution: {integrity: sha512-bRuZp3C0itgLKHu/VNxi66DN/XVkQG7xtoBVWxpvC5FhAqbOCP21+nPhULjnzEqd7xBMybp6KwytdUpZKEgpIQ==} + peerDependencies: + mobx: ^6.1.0 + react: ^16.8.0 || ^17 || ^18 + react-dom: '*' + react-native: '*' + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + react-native: + optional: true + dev: false + /mobx-react-lite/3.4.0_mobx@6.6.1: resolution: {integrity: sha512-bRuZp3C0itgLKHu/VNxi66DN/XVkQG7xtoBVWxpvC5FhAqbOCP21+nPhULjnzEqd7xBMybp6KwytdUpZKEgpIQ==} peerDependencies: @@ -14478,10 +13890,6 @@ packages: engines: {node: '>=10'} dev: false - /moment/2.29.3: - resolution: {integrity: sha512-c6YRvhEo//6T2Jz/vVtYzqBzwvPT95JBQ+smCytzf7c50oMZRsR/a4w88aD34I+/QVSfnoAnSBFPJHItlOMJVw==} - dev: false - /mrmime/1.0.1: resolution: {integrity: sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw==} engines: {node: '>=10'} @@ -14512,27 +13920,6 @@ packages: resolution: {integrity: sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=} dev: true - /nano-css/5.3.5: - resolution: {integrity: sha512-vSB9X12bbNu4ALBu7nigJgRViZ6ja3OU7CeuiV1zMIbXOdmkLahgtPmh3GBOlDxbKY0CitqlPdOReGlBLSp+yg==} - peerDependencies: - react: '*' - react-dom: '*' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - css-tree: 1.1.3 - csstype: 3.1.0 - fastest-stable-stringify: 2.0.2 - inline-style-prefixer: 6.0.1 - rtl-css-js: 1.15.0 - sourcemap-codec: 1.4.8 - stacktrace-js: 2.0.2 - stylis: 4.1.1 - dev: false - /nanoid/3.3.4: resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} @@ -14566,54 +13953,6 @@ packages: /neo-async/2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - /next/12.2.0_beenoklgwfttvph5dgxj7na7aq: - resolution: {integrity: sha512-B4j7D3SHYopLYx6/Ark0fenwIar9tEaZZFAaxmKjgcMMexhVJzB3jt7X+6wcdXPPMeUD6r09weUtnDpjox/vIA==} - engines: {node: '>=12.22.0'} - hasBin: true - peerDependencies: - fibers: '>= 3.1.0' - node-sass: ^6.0.0 || ^7.0.0 - react: ^17.0.2 || ^18.0.0-0 - react-dom: ^17.0.2 || ^18.0.0-0 - sass: ^1.3.0 - peerDependenciesMeta: - fibers: - optional: true - node-sass: - optional: true - react: - optional: true - react-dom: - optional: true - sass: - optional: true - dependencies: - '@next/env': 12.2.0 - '@swc/helpers': 0.4.2 - caniuse-lite: 1.0.30001363 - postcss: 8.4.5 - react: 18.2.0 - react-dom: 18.2.0_react@18.2.0 - styled-jsx: 5.0.2_2sb3a56iojvze2npkgcccbebf4 - use-sync-external-store: 1.1.0_react@18.2.0 - optionalDependencies: - '@next/swc-android-arm-eabi': 12.2.0 - '@next/swc-android-arm64': 12.2.0 - '@next/swc-darwin-arm64': 12.2.0 - '@next/swc-darwin-x64': 12.2.0 - '@next/swc-freebsd-x64': 12.2.0 - '@next/swc-linux-arm-gnueabihf': 12.2.0 - '@next/swc-linux-arm64-gnu': 12.2.0 - '@next/swc-linux-arm64-musl': 12.2.0 - '@next/swc-linux-x64-gnu': 12.2.0 - '@next/swc-linux-x64-musl': 12.2.0 - '@next/swc-win32-arm64-msvc': 12.2.0 - '@next/swc-win32-ia32-msvc': 12.2.0 - '@next/swc-win32-x64-msvc': 12.2.0 - transitivePeerDependencies: - - '@babel/core' - - babel-plugin-macros - /nice-try/1.0.5: resolution: {integrity: sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==} dev: true @@ -14966,21 +14305,6 @@ packages: bin-wrapper: 4.1.0 dev: true - /ora/5.4.1: - resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} - engines: {node: '>=10'} - dependencies: - bl: 4.1.0 - chalk: 4.1.2 - cli-cursor: 3.1.0 - cli-spinners: 2.6.1 - is-interactive: 1.0.0 - is-unicode-supported: 0.1.0 - log-symbols: 4.1.0 - strip-ansi: 6.0.1 - wcwidth: 1.0.1 - dev: true - /os-filter-obj/2.0.0: resolution: {integrity: sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg==} engines: {node: '>=4'} @@ -15289,11 +14613,6 @@ packages: resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} dev: true - /phone/3.1.22: - resolution: {integrity: sha512-0Qr2cCgheYvwWY6zDHRCRcsWT0nyDaRREEfr9wvmTH8X306fD3Q4f334Q6vp5eMBC16zH6bGNKBUZNsOFjtFPQ==} - engines: {node: '>=12'} - dev: false - /picocolors/1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} @@ -15358,11 +14677,6 @@ packages: find-up: 5.0.0 dev: true - /pluralize/8.0.0: - resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} - engines: {node: '>=4'} - dev: true - /portfinder/1.0.28: resolution: {integrity: sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==} engines: {node: '>= 0.12.0'} @@ -15778,14 +15092,6 @@ packages: picocolors: 1.0.0 source-map-js: 1.0.2 - /postcss/8.4.5: - resolution: {integrity: sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==} - engines: {node: ^10 || ^12 || >=14} - dependencies: - nanoid: 3.3.4 - picocolors: 1.0.0 - source-map-js: 1.0.2 - /prelude-ls/1.1.2: resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} engines: {node: '>= 0.8.0'} @@ -15859,11 +15165,6 @@ packages: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} dev: true - /process/0.11.10: - resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} - engines: {node: '>= 0.6.0'} - dev: false - /promise-polyfill/8.1.3: resolution: {integrity: sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g==} dev: true @@ -15927,7 +15228,7 @@ packages: dev: true /proxy-from-env/1.0.0: - resolution: {integrity: sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=} + resolution: {integrity: sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==} dev: true /prr/1.0.1: @@ -15977,6 +15278,7 @@ packages: engines: {node: '>=0.6'} dependencies: side-channel: 1.0.4 + dev: true /qs/6.5.3: resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==} @@ -16040,637 +15342,6 @@ packages: webpack: 5.74.0_@swc+core@1.2.210 dev: true - /rc-align/4.0.12: - resolution: {integrity: sha512-3DuwSJp8iC/dgHzwreOQl52soj40LchlfUHtgACOUtwGuoFIOVh6n/sCpfqCU8kO5+iz6qR0YKvjgB8iPdE3aQ==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - dom-align: 1.12.3 - lodash: 4.17.21 - rc-util: 5.22.5 - resize-observer-polyfill: 1.5.1 - dev: false - - /rc-cascader/3.6.1: - resolution: {integrity: sha512-+GmN2Z0IybKT45t0Z94jkjmsOHGxAliobR2tzt05/Gw0AKBYLHX5bdvsVXR7abPnarYyYzZ/cWe8CoFgDjAFNw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - array-tree-filter: 2.1.0 - classnames: 2.3.1 - rc-select: 14.1.8 - rc-tree: 5.6.5 - rc-util: 5.22.5 - dev: false - - /rc-checkbox/2.3.2: - resolution: {integrity: sha512-afVi1FYiGv1U0JlpNH/UaEXdh6WUJjcWokj/nUN2TgG80bfG+MDdbfHKlLcNNba94mbjy2/SXJ1HDgrOkXGAjg==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - dev: false - - /rc-collapse/3.3.1: - resolution: {integrity: sha512-cOJfcSe3R8vocrF8T+PgaHDrgeA1tX+lwfhwSj60NX9QVRidsILIbRNDLD6nAzmcvVC5PWiIRiR4S1OobxdhCg==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-motion: 2.6.0 - rc-util: 5.22.5 - shallowequal: 1.1.0 - dev: false - - /rc-dialog/8.9.0: - resolution: {integrity: sha512-Cp0tbJnrvPchJfnwIvOMWmJ4yjX3HWFatO6oBFD1jx8QkgsQCR0p8nUWAKdd3seLJhEC39/v56kZaEjwp9muoQ==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-motion: 2.6.0 - rc-util: 5.22.5 - dev: false - - /rc-drawer/4.4.3: - resolution: {integrity: sha512-FYztwRs3uXnFOIf1hLvFxIQP9MiZJA+0w+Os8dfDh/90X7z/HqP/Yg+noLCIeHEbKln1Tqelv8ymCAN24zPcfQ==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-util: 5.22.5 - dev: false - - /rc-dropdown/4.0.1: - resolution: {integrity: sha512-OdpXuOcme1rm45cR0Jzgfl1otzmU4vuBVb+etXM8vcaULGokAKVpKlw8p6xzspG7jGd/XxShvq+N3VNEfk/l5g==} - peerDependencies: - react: '>=16.11.0' - react-dom: '>=16.11.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-trigger: 5.3.1 - rc-util: 5.22.5 - dev: false - - /rc-field-form/1.26.7: - resolution: {integrity: sha512-CIb7Gw+DG9R+g4HxaDGYHhOjhjQoU2mGU4y+UM2+KQ3uRz9HrrNgTspGvNynn3UamsYcYcaPWZJmiJ6VklkT/w==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - async-validator: 4.2.5 - rc-util: 5.22.5 - dev: false - - /rc-image/5.7.0: - resolution: {integrity: sha512-v6dzSgYfYrH4liKmOZKZZO+x21sJ9KPXNinBfkAoQg2Ihcd5QZ+P/JjB7v60X981XTPGjegy8U17Z8VUX4V36g==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-dialog: 8.9.0 - rc-util: 5.22.5 - dev: false - - /rc-input-number/7.3.4: - resolution: {integrity: sha512-W9uqSzuvJUnz8H8vsVY4kx+yK51SsAxNTwr8SNH4G3XqQNocLVmKIibKFRjocnYX1RDHMND9FFbgj2h7E7nvGA==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-util: 5.22.5 - dev: false - - /rc-input/0.0.1-alpha.7: - resolution: {integrity: sha512-eozaqpCYWSY5LBMwlHgC01GArkVEP+XlJ84OMvdkwUnJBSv83Yxa15pZpn7vACAj84uDC4xOA2CoFdbLuqB08Q==} - peerDependencies: - react: '>=16.0.0' - react-dom: '>=16.0.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-util: 5.22.5 - dev: false - - /rc-mentions/1.8.0: - resolution: {integrity: sha512-ch7yfMMvx2UXy+EvE4axm0Vp6VlVZ30WLrZtLtV/Eb1ty7rQQRzNzCwAHAMyw6tNKTMs9t9sF68AVjAzQ0rvJw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-menu: 9.6.0 - rc-textarea: 0.3.7 - rc-trigger: 5.3.1 - rc-util: 5.22.5 - dev: false - - /rc-menu/9.6.0: - resolution: {integrity: sha512-d26waws42U/rVwW/+rOE2FN9pX6wUc9bDy38vVQYoie6gE85auWIpl5oChGlnW6nE2epnTwUsgWl8ipOPgmnUA==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-motion: 2.6.0 - rc-overflow: 1.2.6 - rc-trigger: 5.3.1 - rc-util: 5.22.5 - shallowequal: 1.1.0 - dev: false - - /rc-motion/2.6.0: - resolution: {integrity: sha512-1MDWA9+i174CZ0SIDenSYm2Wb9YbRkrexjZWR0CUFu7D6f23E8Y0KsTgk9NGOLJsGak5ELZK/Y5lOlf5wQdzbw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-util: 5.22.5 - dev: false - - /rc-notification/4.6.0: - resolution: {integrity: sha512-xF3MKgIoynzjQAO4lqsoraiFo3UXNYlBfpHs0VWvwF+4pimen9/H1DYLN2mfRWhHovW6gRpla73m2nmyIqAMZQ==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-motion: 2.6.0 - rc-util: 5.22.5 - dev: false - - /rc-overflow/1.2.6: - resolution: {integrity: sha512-YqbocgzuQxfq2wZy72vdAgrgzzEuM/5d4gF9TBEodCpXPbUeXGrUXNm1J6G1MSkCU2N0ePIgCEu5qD/0Ldi63Q==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-resize-observer: 1.2.0 - rc-util: 5.22.5 - dev: false - - /rc-pagination/3.1.17: - resolution: {integrity: sha512-/BQ5UxcBnW28vFAcP2hfh+Xg15W0QZn8TWYwdCApchMH1H0CxiaUUcULP8uXcFM1TygcdKWdt3JqsL9cTAfdkQ==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - dev: false - - /rc-picker/2.6.10: - resolution: {integrity: sha512-9wYtw0DFWs9FO92Qh2D76P0iojUr8ZhLOtScUeOit6ks/F+TBLrOC1uze3IOu+u9gbDAjmosNWLKbBzx/Yuv2w==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - date-fns: 2.28.0 - dayjs: 1.11.3 - moment: 2.29.3 - rc-trigger: 5.3.1 - rc-util: 5.22.5 - shallowequal: 1.1.0 - dev: false - - /rc-progress/3.3.3: - resolution: {integrity: sha512-MDVNVHzGanYtRy2KKraEaWeZLri2ZHWIRyaE1a9MQ2MuJ09m+Wxj5cfcaoaR6z5iRpHpA59YeUxAlpML8N4PJw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-util: 5.22.5 - dev: false - - /rc-rate/2.9.2: - resolution: {integrity: sha512-SaiZFyN8pe0Fgphv8t3+kidlej+cq/EALkAJAc3A0w0XcPaH2L1aggM8bhe1u6GAGuQNAoFvTLjw4qLPGRKV5g==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-util: 5.22.5 - dev: false - - /rc-resize-observer/1.2.0: - resolution: {integrity: sha512-6W+UzT3PyDM0wVCEHfoW3qTHPTvbdSgiA43buiy8PzmeMnfgnDeb9NjdimMXMl3/TcrvvWl5RRVdp+NqcR47pQ==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-util: 5.22.5 - resize-observer-polyfill: 1.5.1 - dev: false - - /rc-segmented/2.1.0: - resolution: {integrity: sha512-hUlonro+pYoZcwrH6Vm56B2ftLfQh046hrwif/VwLIw1j3zGt52p5mREBwmeVzXnSwgnagpOpfafspzs1asjGw==} - peerDependencies: - react: '>=16.0.0' - react-dom: '>=16.0.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-motion: 2.6.0 - rc-util: 5.22.5 - dev: false - - /rc-select/14.1.8: - resolution: {integrity: sha512-1kU/7ZCggyR5r5jVEQfAiN6Sq3LGLD2b6FNz5GWel3TOEQZYyDn0o4FAoIRqS6Y5ldWmkFxtd834ilPnG6NV6w==} - engines: {node: '>=8.x'} - peerDependencies: - react: '*' - react-dom: '*' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-motion: 2.6.0 - rc-overflow: 1.2.6 - rc-trigger: 5.3.1 - rc-util: 5.22.5 - rc-virtual-list: 3.4.8 - dev: false - - /rc-slider/10.0.0: - resolution: {integrity: sha512-Bk54UIKWW4wyhHcL8ehAxt+wX+n69dscnHTX6Uv0FMxSke/TGrlkZz1LSIWblCpfE2zr/dwR2Ca8nZGk3U+Tbg==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-tooltip: 5.1.1 - rc-util: 5.22.5 - shallowequal: 1.1.0 - dev: false - - /rc-steps/4.1.4: - resolution: {integrity: sha512-qoCqKZWSpkh/b03ASGx1WhpKnuZcRWmvuW+ZUu4mvMdfvFzVxblTwUM+9aBd0mlEUFmt6GW8FXhMpHkK3Uzp3w==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-util: 5.22.5 - dev: false - - /rc-switch/3.2.2: - resolution: {integrity: sha512-+gUJClsZZzvAHGy1vZfnwySxj+MjLlGRyXKXScrtCTcmiYNPzxDFOxdQ/3pK1Kt/0POvwJ/6ALOR8gwdXGhs+A==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-util: 5.22.5 - dev: false - - /rc-table/7.24.3: - resolution: {integrity: sha512-3Z74jeIpQ2t0i/PQ3iSKXsl1WGT809yzq3KzIDzEB7SIA0zat+rqwI+OnrwfhJVRp7GTjeT7sJyCatXpw1YJdg==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-resize-observer: 1.2.0 - rc-util: 5.22.5 - shallowequal: 1.1.0 - dev: false - - /rc-tabs/11.16.0: - resolution: {integrity: sha512-CIDPv3lHaXSHTJevmFP2eHoD3Hq9psfKbOZYf6D4FYPACloNGHpz44y3RGeJgataQ7omFLrGBm3dOBMUki87tA==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-dropdown: 4.0.1 - rc-menu: 9.6.0 - rc-resize-observer: 1.2.0 - rc-util: 5.22.5 - dev: false - - /rc-textarea/0.3.7: - resolution: {integrity: sha512-yCdZ6binKmAQB13hc/oehh0E/QRwoPP1pjF21aHBxlgXO3RzPF6dUu4LG2R4FZ1zx/fQd2L1faktulrXOM/2rw==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-resize-observer: 1.2.0 - rc-util: 5.22.5 - shallowequal: 1.1.0 - dev: false - - /rc-tooltip/5.1.1: - resolution: {integrity: sha512-alt8eGMJulio6+4/uDm7nvV+rJq9bsfxFDCI0ljPdbuoygUscbsMYb6EQgwib/uqsXQUvzk+S7A59uYHmEgmDA==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - rc-trigger: 5.3.1 - dev: false - - /rc-tree-select/5.4.0: - resolution: {integrity: sha512-reRbOqC7Ic/nQocJAJeCl4n6nJUY3NoqiwRXKvhjgZJU7NGr9vIccXEsY+Lghkw5UMpPoxGsIJB0jiAvM18XYA==} - peerDependencies: - react: '*' - react-dom: '*' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-select: 14.1.8 - rc-tree: 5.6.5 - rc-util: 5.22.5 - dev: false - - /rc-tree/5.6.5: - resolution: {integrity: sha512-Bnyen46B251APyRZ9D/jYeTnSqbSEvK2AkU5B4vWkNYgUJNPrxO+VMgcDRedP/8N7YcsgdDT9hxqVvNOq7oCAQ==} - engines: {node: '>=10.x'} - peerDependencies: - react: '*' - react-dom: '*' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-motion: 2.6.0 - rc-util: 5.22.5 - rc-virtual-list: 3.4.8 - dev: false - - /rc-trigger/5.3.1: - resolution: {integrity: sha512-5gaFbDkYSefZ14j2AdzucXzlWgU2ri5uEjkHvsf1ynRhdJbKxNOnw4PBZ9+FVULNGFiDzzlVF8RJnR9P/xrnKQ==} - engines: {node: '>=8.x'} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-align: 4.0.12 - rc-motion: 2.6.0 - rc-util: 5.22.5 - dev: false - - /rc-upload/4.3.4: - resolution: {integrity: sha512-uVbtHFGNjHG/RyAfm9fluXB6pvArAGyAx8z7XzXXyorEgVIWj6mOlriuDm0XowDHYz4ycNK0nE0oP3cbFnzxiQ==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - classnames: 2.3.1 - rc-util: 5.22.5 - dev: false - - /rc-util/5.22.5: - resolution: {integrity: sha512-awD2TGMGU97OZftT2R3JwrHWjR8k/xIwqjwcivPskciweUdgXE7QsyXkBKVSBHXS+c17AWWMDWuKWsJSheQy8g==} - peerDependencies: - react: '>=16.9.0' - react-dom: '>=16.9.0' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@babel/runtime': 7.18.6 - react-is: 16.13.1 - shallowequal: 1.1.0 - dev: false - - /rc-virtual-list/3.4.8: - resolution: {integrity: sha512-qSN+Rv4i/E7RCTvTMr1uZo7f3crJJg/5DekoCagydo9zsXrxj07zsFSxqizqW+ldGA16lwa8So/bIbV9Ofjddg==} - engines: {node: '>=8.x'} - peerDependencies: - react: '*' - react-dom: '*' - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - classnames: 2.3.1 - rc-resize-observer: 1.2.0 - rc-util: 5.22.5 - dev: false - /react-date-range/1.4.0_date-fns@2.28.0: resolution: {integrity: sha512-+9t0HyClbCqw1IhYbpWecjsiaftCeRN5cdhsi9v06YdimwyMR2yYHWcgVn3URwtN/txhqKpEZB6UX1fHpvK76w==} peerDependencies: @@ -16792,21 +15463,6 @@ packages: - react-dom dev: false - /react-responsive/9.0.0-beta.10: - resolution: {integrity: sha512-41H8g4FYP46ln16rsHvs9/0ZoZxAPfnNiHET86/5pgS+Vw8fSKfLBuOS2SAquaxOxq7DgPviFoHmybgVvSKCNQ==} - engines: {node: '>=0.10'} - peerDependencies: - react: '>=16.8.0' - peerDependenciesMeta: - react: - optional: true - dependencies: - hyphenate-style-name: 1.0.4 - matchmediaquery: 0.3.1 - prop-types: 15.8.1 - shallow-equal: 1.2.1 - dev: false - /react-router-dom/6.3.0_biqbaboplfbrettd7655fr4n2y: resolution: {integrity: sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==} peerDependencies: @@ -16899,45 +15555,6 @@ packages: react-dom: 18.2.0_react@18.2.0 dev: false - /react-universal-interface/0.6.2_tslib@2.4.0: - resolution: {integrity: sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==} - peerDependencies: - react: '*' - tslib: '*' - peerDependenciesMeta: - react: - optional: true - dependencies: - tslib: 2.4.0 - dev: false - - /react-use/17.4.0: - resolution: {integrity: sha512-TgbNTCA33Wl7xzIJegn1HndB4qTS9u03QUwyNycUnXaweZkE4Kq2SB+Yoxx8qbshkZGYBDvUXbXWRUmQDcZZ/Q==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - react-dom: - optional: true - dependencies: - '@types/js-cookie': 2.2.7 - '@xobotyi/scrollbar-width': 1.9.5 - copy-to-clipboard: 3.3.1 - fast-deep-equal: 3.1.3 - fast-shallow-equal: 1.0.0 - js-cookie: 2.2.1 - nano-css: 5.3.5 - react-universal-interface: 0.6.2_tslib@2.4.0 - resize-observer-polyfill: 1.5.1 - screenfull: 5.2.0 - set-harmonic-interval: 1.0.1 - throttle-debounce: 3.0.1 - ts-easing: 0.2.0 - tslib: 2.4.0 - dev: false - /react-window/1.8.7: resolution: {integrity: sha512-JHEZbPXBpKMmoNO1bNhoXOOLg/ujhL/BU4IqVU9r8eQPcy5KQnGHIHDRkJ0ns9IM5+Aq5LNwt3j8t3tIrePQzA==} engines: {node: '>8.0.0'} @@ -17316,12 +15933,6 @@ packages: optionalDependencies: fsevents: 2.3.2 - /rtl-css-js/1.15.0: - resolution: {integrity: sha512-99Cu4wNNIhrI10xxUaABHsdDqzalrSRTie4GeCmbGVuehm4oj+fIy8fTzB+16pmKe8Bv9rl+hxIBez6KxExTew==} - dependencies: - '@babel/runtime': 7.18.6 - dev: false - /run-async/2.4.1: resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} engines: {node: '>=0.12.0'} @@ -17472,11 +16083,6 @@ packages: ajv-keywords: 5.1.0_ajv@8.11.0 dev: true - /screenfull/5.2.0: - resolution: {integrity: sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==} - engines: {node: '>=0.10.0'} - dev: false - /scroll-into-view-if-needed/2.2.29: resolution: {integrity: sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg==} dependencies: @@ -17623,11 +16229,6 @@ packages: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} dev: true - /set-harmonic-interval/1.0.1: - resolution: {integrity: sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==} - engines: {node: '>=6.9'} - dev: false - /setimmediate/1.0.5: resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} dev: true @@ -17657,10 +16258,6 @@ packages: resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==} dev: false - /shallowequal/1.1.0: - resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} - dev: false - /shebang-command/1.2.0: resolution: {integrity: sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==} engines: {node: '>=0.10.0'} @@ -17784,6 +16381,7 @@ packages: resolution: {integrity: sha512-BEF+VQMD5EH96ouBBVNoJ6URDkLp8zIvQY7wLh1ZPFlbt/vpXxlb35hKFb2+UDiHGGdV/rxNVqvGjhxuhLd9mA==} dependencies: jsbn: 1.1.0 + dev: false /snake-case/3.0.4: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} @@ -17877,11 +16475,6 @@ packages: buffer-from: 1.1.2 source-map: 0.6.1 - /source-map/0.5.6: - resolution: {integrity: sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==} - engines: {node: '>=0.10.0'} - dev: false - /source-map/0.5.7: resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} engines: {node: '>=0.10.0'} @@ -17903,6 +16496,7 @@ packages: /sourcemap-codec/1.4.8: resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + dev: true /spdy-transport/3.0.0: resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} @@ -17959,12 +16553,6 @@ packages: deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' dev: true - /stack-generator/2.0.10: - resolution: {integrity: sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==} - dependencies: - stackframe: 1.3.4 - dev: false - /stack-utils/2.0.5: resolution: {integrity: sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==} engines: {node: '>=10'} @@ -17974,21 +16562,7 @@ packages: /stackframe/1.3.4: resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} - - /stacktrace-gps/3.1.2: - resolution: {integrity: sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==} - dependencies: - source-map: 0.5.6 - stackframe: 1.3.4 - dev: false - - /stacktrace-js/2.0.2: - resolution: {integrity: sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==} - dependencies: - error-stack-parser: 2.1.4 - stack-generator: 2.0.10 - stacktrace-gps: 3.1.2 - dev: false + dev: true /statuses/1.5.0: resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} @@ -18022,10 +16596,6 @@ packages: engines: {node: '>=0.6.19'} dev: true - /string-convert/0.2.1: - resolution: {integrity: sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==} - dev: false - /string-hash/1.1.3: resolution: {integrity: sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==} dev: true @@ -18290,24 +16860,6 @@ packages: - webpack dev: false - /styled-jsx/5.0.2_2sb3a56iojvze2npkgcccbebf4: - resolution: {integrity: sha512-LqPQrbBh3egD57NBcHET4qcgshPks+yblyhPlH2GY8oaDgKs8SK4C3dBh3oSJjgzJ3G5t1SYEZGHkP+QEpX9EQ==} - engines: {node: '>= 12.0.0'} - peerDependencies: - '@babel/core': '*' - babel-plugin-macros: '*' - react: '>= 16.8.0 || 17.x.x || ^18.0.0-0' - peerDependenciesMeta: - '@babel/core': - optional: true - babel-plugin-macros: - optional: true - react: - optional: true - dependencies: - '@babel/core': 7.18.6 - react: 18.2.0 - /stylehacks/5.1.0_postcss@8.4.14: resolution: {integrity: sha512-SzLmvHQTrIWfSgljkQCw2++C9+Ne91d/6Sp92I8c5uHTcy/PgeHamwITIbBW9wnFTY/3ZfSXR9HIL6Ikqmcu6Q==} engines: {node: ^10 || ^12 || >=14.0} @@ -18323,10 +16875,6 @@ packages: resolution: {integrity: sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==} dev: false - /stylis/4.1.1: - resolution: {integrity: sha512-lVrM/bNdhVX2OgBFNa2YJ9Lxj7kPzylieHd3TNjuGE0Re9JB7joL5VUKOVH1kdNNJTgGPpT8hmwIAPLaSyEVFQ==} - dev: false - /stylus-loader/6.2.0_772wava6yveehcyvgfd527qm3q: resolution: {integrity: sha512-5dsDc7qVQGRoc6pvCL20eYgRUxepZ9FpeK28XhdXaIPP6kXr6nI1zAAKFQgP5OBkOfKaURp4WUpJzspg1f01Gg==} engines: {node: '>= 12.13.0'} @@ -18585,11 +17133,6 @@ packages: resolution: {integrity: sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==} dev: true - /throttle-debounce/3.0.1: - resolution: {integrity: sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==} - engines: {node: '>=10'} - dev: false - /throttleit/1.0.0: resolution: {integrity: sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==} dev: true @@ -18717,10 +17260,6 @@ packages: resolution: {integrity: sha512-+1iDGY6NmOGidq7i7xZGA4cm8DAa6fqdYcvO5Z6yBevH++Bdo9Qt/mN0TzHUgcCcKv1gmh9+W5dHqz8pMWbCbg==} dev: true - /ts-easing/0.2.0: - resolution: {integrity: sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==} - dev: false - /ts-jest/28.0.5_dvf3gqad2lwurck7yyca7j3d3i: resolution: {integrity: sha512-Sx9FyP9pCY7pUzQpy4FgRZf2bhHY3za576HMKJFs+OnQ9jS96Du5vNsDKkyedQkik+sEabbKAnCliv9BEsHZgQ==} engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} @@ -18906,10 +17445,6 @@ packages: hasBin: true dev: true - /ua-parser-js/1.0.2: - resolution: {integrity: sha512-00y/AXhx0/SsnI51fTc0rLRmafiGOM4/O+ny10Ps7f+j/b8p/ZY11ytMgznXkOVo4GQ+KwQG5UQLkLGirsACRg==} - dev: false - /unbox-primitive/1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} dependencies: @@ -19059,16 +17594,6 @@ packages: querystring: 0.2.0 dev: false - /use-sync-external-store/1.1.0_react@18.2.0: - resolution: {integrity: sha512-SEnieB2FPKEVne66NpXPd1Np4R1lTNKfjuy3XdIoPQKYBAFdzbzSZlSn1KJZUiihQLQC5Znot4SBz1EOTBwQAQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - peerDependenciesMeta: - react: - optional: true - dependencies: - react: 18.2.0 - /user-home/2.0.0: resolution: {integrity: sha512-KMWqdlOcjCYdtIJpicDSFBQ8nFwS2i9sslAd6f4+CBGcU4gist2REnr2fxj2YocvJFxSF3ZOHLYLVZnUxv4BZQ==} engines: {node: '>=0.10.0'} @@ -19146,7 +17671,7 @@ packages: dev: true /verror/1.10.0: - resolution: {integrity: sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=} + resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} engines: {'0': node >=0.6.0} dependencies: assert-plus: 1.0.0 @@ -19190,12 +17715,6 @@ packages: minimalistic-assert: 1.0.1 dev: true - /wcwidth/1.0.1: - resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} - dependencies: - defaults: 1.0.3 - dev: true - /webidl-conversions/3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -19517,10 +18036,6 @@ packages: string-width: 1.0.2 dev: true - /wildcard/1.1.2: - resolution: {integrity: sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==} - dev: false - /wildcard/2.0.0: resolution: {integrity: sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==} dev: true From d432b836a9bf43b411d743f4899013e3e324186b Mon Sep 17 00:00:00 2001 From: DarkSky Date: Wed, 17 Aug 2022 17:30:48 +0800 Subject: [PATCH 02/58] chore: improve deps install --- .github/deployment/Dockerfile-affine | 2 +- .github/deployment/Dockerfile-lisa | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/deployment/Dockerfile-affine b/.github/deployment/Dockerfile-affine index 5cf4243eab..18da60c4fa 100644 --- a/.github/deployment/Dockerfile-affine +++ b/.github/deployment/Dockerfile-affine @@ -2,7 +2,7 @@ FROM node:16-alpine as builder WORKDIR /app COPY . . RUN apk add g++ make python3 git libpng-dev -RUN npm i -g pnpm@7 && pnpm i --frozen-lockfile --store=node_modules/.pnpm-store && pnpm run build:local --skip-nx-cache +RUN npm i -g pnpm@7 && pnpm i --frozen-lockfile --store=node_modules/.pnpm-store --filter "!ligo-virgo-e2e" --filter "!keck" --filter "!venus" && pnpm run build:local --skip-nx-cache FROM node:16-alpine as relocate WORKDIR /app diff --git a/.github/deployment/Dockerfile-lisa b/.github/deployment/Dockerfile-lisa index 471e4d0d48..9f17f6527e 100644 --- a/.github/deployment/Dockerfile-lisa +++ b/.github/deployment/Dockerfile-lisa @@ -2,7 +2,7 @@ FROM node:16-alpine as builder WORKDIR /app COPY . . RUN apk add g++ make python3 git libpng-dev -RUN npm i -g pnpm@7 && pnpm i --frozen-lockfile --store=node_modules/.pnpm-store && pnpm run build +RUN npm i -g pnpm@7 && pnpm i --frozen-lockfile --store=node_modules/.pnpm-store --filter "!ligo-virgo-e2e" --filter "!keck" --filter "!venus" && pnpm run build FROM node:16-alpine as relocate WORKDIR /app From 405e65e4aa60b28002157989ac3bbe4d5501e3e5 Mon Sep 17 00:00:00 2001 From: DarkSky Date: Wed, 17 Aug 2022 17:35:56 +0800 Subject: [PATCH 03/58] chore: cleanup deps --- .github/deployment/Dockerfile-affine | 3 ++- .github/deployment/Dockerfile-lisa | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/deployment/Dockerfile-affine b/.github/deployment/Dockerfile-affine index 18da60c4fa..9d54eb0cf4 100644 --- a/.github/deployment/Dockerfile-affine +++ b/.github/deployment/Dockerfile-affine @@ -1,7 +1,8 @@ FROM node:16-alpine as builder WORKDIR /app COPY . . -RUN apk add g++ make python3 git libpng-dev +# RUN apk add g++ make python3 git libpng-dev +RUN apk add git RUN npm i -g pnpm@7 && pnpm i --frozen-lockfile --store=node_modules/.pnpm-store --filter "!ligo-virgo-e2e" --filter "!keck" --filter "!venus" && pnpm run build:local --skip-nx-cache FROM node:16-alpine as relocate diff --git a/.github/deployment/Dockerfile-lisa b/.github/deployment/Dockerfile-lisa index 9f17f6527e..f469a7fce8 100644 --- a/.github/deployment/Dockerfile-lisa +++ b/.github/deployment/Dockerfile-lisa @@ -1,7 +1,8 @@ FROM node:16-alpine as builder WORKDIR /app COPY . . -RUN apk add g++ make python3 git libpng-dev +# RUN apk add g++ make python3 git libpng-dev +RUN apk add git RUN npm i -g pnpm@7 && pnpm i --frozen-lockfile --store=node_modules/.pnpm-store --filter "!ligo-virgo-e2e" --filter "!keck" --filter "!venus" && pnpm run build FROM node:16-alpine as relocate From 41bb7368ffe7b8f7089962ac3179eef0495afbb9 Mon Sep 17 00:00:00 2001 From: alt0 Date: Thu, 18 Aug 2022 15:45:58 +0800 Subject: [PATCH 04/58] fix: autofocus when create group in board --- .../board-shapes/src/editor-util/EditorUtil.tsx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/libs/components/board-shapes/src/editor-util/EditorUtil.tsx b/libs/components/board-shapes/src/editor-util/EditorUtil.tsx index 6e6f123a72..0855310081 100644 --- a/libs/components/board-shapes/src/editor-util/EditorUtil.tsx +++ b/libs/components/board-shapes/src/editor-util/EditorUtil.tsx @@ -8,6 +8,7 @@ import { TDShapeType, TransformInfo, } from '@toeverything/components/board-types'; +import type { BlockEditor } from '@toeverything/components/editor-core'; import { MIN_PAGE_WIDTH } from '@toeverything/components/editor-core'; import { styled } from '@toeverything/components/ui'; import type { SyntheticEvent } from 'react'; @@ -66,6 +67,7 @@ export class EditorUtil extends TDShapeUtil { Component = TDShapeUtil.Component( ({ shape, meta: { app }, events, isEditing, onShapeChange }, ref) => { const containerRef = useRef(); + const editorRef = useRef(); const { workspace, rootBlockId, @@ -135,6 +137,18 @@ export class EditorUtil extends TDShapeUtil { } }, [app, state, shape.id, editingText, editingId]); + useEffect(() => { + (async () => { + if (isEditing) { + const lastBlock = + await editorRef.current.getLastBlock(); + editorRef.current.selectionManager.activeNodeByNodeId( + lastBlock.id + ); + } + })(); + }, [isEditing]); + return ( { rootBlockId={rootBlockId} scrollBlank={false} isEdgeless + ref={editorRef} /> {editingText ? null : } From 919e0d08d561d0cd8da9f52aa3a610252f0aae13 Mon Sep 17 00:00:00 2001 From: xiaodong zuo Date: Thu, 18 Aug 2022 16:22:45 +0800 Subject: [PATCH 05/58] feat: Intra-line double link interaction --- libs/components/common/src/lib/list/index.tsx | 15 +- .../common/src/lib/text/EditableText.tsx | 58 +-- .../src/lib/text/plugins/DoubleLink.tsx | 29 ++ .../common/src/lib/text/slate-utils.ts | 146 ++++++-- .../src/editor/block/async-block.ts | 45 ++- .../src/editor/block/block-helper.ts | 75 +++- .../editor-core/src/editor/editor.ts | 8 +- libs/components/editor-plugins/src/index.ts | 22 +- .../src/menu/double-link-menu/Container.tsx | 185 ++++++++++ .../menu/double-link-menu/DoubleLinkMenu.tsx | 346 ++++++++++++++++++ .../Plugin.tsx | 7 +- .../src/menu/double-link-menu/index.ts | 1 + .../editor-plugins/src/menu/index.ts | 10 +- .../src/menu/reference-menu/Container.tsx | 190 ---------- .../src/menu/reference-menu/ReferenceMenu.tsx | 148 -------- .../src/menu/reference-menu/index.ts | 1 - libs/components/ui/src/button/ListButton.tsx | 3 +- libs/datasource/jwt/src/index.ts | 30 +- 18 files changed, 859 insertions(+), 460 deletions(-) create mode 100644 libs/components/common/src/lib/text/plugins/DoubleLink.tsx create mode 100644 libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx create mode 100644 libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx rename libs/components/editor-plugins/src/menu/{reference-menu => double-link-menu}/Plugin.tsx (79%) create mode 100644 libs/components/editor-plugins/src/menu/double-link-menu/index.ts delete mode 100644 libs/components/editor-plugins/src/menu/reference-menu/Container.tsx delete mode 100644 libs/components/editor-plugins/src/menu/reference-menu/ReferenceMenu.tsx delete mode 100644 libs/components/editor-plugins/src/menu/reference-menu/index.ts diff --git a/libs/components/common/src/lib/list/index.tsx b/libs/components/common/src/lib/list/index.tsx index 8f57a1d871..7de7e35b8e 100644 --- a/libs/components/common/src/lib/list/index.tsx +++ b/libs/components/common/src/lib/list/index.tsx @@ -1,8 +1,4 @@ -import { useState } from 'react'; -import { useNavigate } from 'react-router'; -import clsx from 'clsx'; -import style9 from 'style9'; - +import { BackwardUndoIcon } from '@toeverything/components/icons'; import { BaseButton, ListButton, @@ -12,9 +8,11 @@ import { } from '@toeverything/components/ui'; // eslint-disable-next-line @nrwl/nx/enforce-module-boundaries import { BlockSearchItem } from '@toeverything/datasource/jwt'; - +import clsx from 'clsx'; +import { useState } from 'react'; +import { useNavigate } from 'react-router'; +import style9 from 'style9'; import { BlockPreview } from '../block-preview'; -import { BackwardUndoIcon } from '@toeverything/components/icons'; export const commonListContainer = 'commonListContainer'; @@ -28,6 +26,7 @@ export type CommonListItem = { divider?: string; content?: Content; block?: BlockSearchItem; + renderCustom?: (props: CommonListItem) => JSX.Element; }; type MenuItemsProps = { @@ -45,7 +44,7 @@ export const CommonList = (props: MenuItemsProps) => { // ]); // TODO Insert bidirectional link to be developed const JSONUnsupportedBlockTypes = ['page']; - let usedItems = items.filter(item => { + const usedItems = items.filter(item => { return !JSONUnsupportedBlockTypes.includes(item?.content?.id); }); return ( diff --git a/libs/components/common/src/lib/text/EditableText.tsx b/libs/components/common/src/lib/text/EditableText.tsx index 3c9ca6fe5c..7bc6c3904a 100644 --- a/libs/components/common/src/lib/text/EditableText.tsx +++ b/libs/components/common/src/lib/text/EditableText.tsx @@ -1,54 +1,54 @@ /* eslint-disable max-lines */ +import { SearchIcon } from '@toeverything/components/icons'; +import { ErrorBoundary, isEqual } from '@toeverything/utils'; +import isHotkey from 'is-hotkey'; +import isUrl from 'is-url'; import React, { + CSSProperties, + DragEvent, + forwardRef, KeyboardEvent, KeyboardEventHandler, + MouseEvent, + MouseEventHandler, useCallback, useEffect, + useLayoutEffect, useMemo, useRef, useState, - forwardRef, - MouseEventHandler, - useLayoutEffect, - CSSProperties, - MouseEvent, - DragEvent, } from 'react'; -import isHotkey from 'is-hotkey'; import { createEditor, Descendant, - Range, - Element as SlateElement, Editor, - Transforms, + Element as SlateElement, Node, Path, + Range, + Transforms, } from 'slate'; import { Editable, - withReact, - Slate, ReactEditor, + Slate, useSlateStatic, + withReact, } from 'slate-react'; - -import { ErrorBoundary, isEqual, uaHelper } from '@toeverything/utils'; - -import { Contents, SlateUtils, isSelectAll } from './slate-utils'; +import { CustomElement } from '..'; +import { HOTKEYS, INLINE_STYLES } from './constants'; +import { TextWithComments } from './element-leaf/TextWithComments'; +import { InlineDate, withDate } from './plugins/date'; +import { DoubleLinkComponent } from './plugins/DoubleLink'; +import { LinkComponent, LinkModal, withLinks, wrapLink } from './plugins/link'; +import { InlineRefLink } from './plugins/reflink'; +import { Contents, isSelectAll, SlateUtils } from './slate-utils'; import { getCommentsIdsOnTextNode, getExtraPropertiesFromEditorOutmostNode, isInterceptCharacter, matchMarkdown, } from './utils'; -import { HOTKEYS, INLINE_STYLES } from './constants'; -import { LinkComponent, LinkModal, withLinks, wrapLink } from './plugins/link'; -import { withDate, InlineDate } from './plugins/date'; -import { CustomElement } from '..'; -import isUrl from 'is-url'; -import { InlineRefLink } from './plugins/reflink'; -import { TextWithComments } from './element-leaf/TextWithComments'; export interface TextProps { /** read only */ @@ -739,6 +739,9 @@ const EditorElement = (props: any) => { switch (element.type) { case 'link': { + if (element.linkType === 'doubleLink') { + return ; + } return ( { } } + if (leaf.doubleLinkSearch) { + customChildren = ( + + + {customChildren} + + ); + } + customChildren = ( {customChildren} diff --git a/libs/components/common/src/lib/text/plugins/DoubleLink.tsx b/libs/components/common/src/lib/text/plugins/DoubleLink.tsx new file mode 100644 index 0000000000..8160731bf2 --- /dev/null +++ b/libs/components/common/src/lib/text/plugins/DoubleLink.tsx @@ -0,0 +1,29 @@ +import { PagesIcon } from '@toeverything/components/icons'; +import React, { useCallback } from 'react'; +import { useNavigate } from 'react-router-dom'; + +export const DoubleLinkComponent = ({ attributes, children, element }: any) => { + const navigate = useNavigate(); + + const handleClickLinkText = useCallback( + (event: React.MouseEvent) => { + event.preventDefault(); + event.stopPropagation(); + const { workspaceId, blockId } = element; + navigate(`/${workspaceId}/${blockId}`); + }, + [element, navigate] + ); + + return ( + + + + {children} + + + ); +}; diff --git a/libs/components/common/src/lib/text/slate-utils.ts b/libs/components/common/src/lib/text/slate-utils.ts index ec7e219810..9b1fff664c 100644 --- a/libs/components/common/src/lib/text/slate-utils.ts +++ b/libs/components/common/src/lib/text/slate-utils.ts @@ -11,7 +11,6 @@ import { Transforms, } from 'slate'; import { ReactEditor } from 'slate-react'; - import { fontBgColorPalette, fontColorPalette, @@ -21,6 +20,7 @@ import { import { getCommentsIdsOnTextNode, getEditorMarkForCommentId, + getRandomString, MARKDOWN_STYLE_MAP, MatchRes, } from './utils'; @@ -246,7 +246,11 @@ Editor.insertText = function ( const { path, offset } = at; if (text.length > 0) { const marks = Editor.marks(editor); - if (text === '\u0020' && Object.keys(marks).length) { + if ( + text === '\u0020' && + Object.keys(marks).length && + !(marks as any).doubleLinkSearch + ) { // If the input is a space and the mark has content, remove the mark const newPath = [path[0], path[1] + 1]; const newPoint = { @@ -1084,34 +1088,130 @@ class SlateUtils { }); } - public insertReference(reference: string) { - try { - // Transforms.setSelection(this.editor, this.getEndSelection()); - const { anchor, focus } = this.getEndSelection(); - Transforms.insertNodes( + public setDoubleLinkSearchSlash(point: Point) { + const str = Editor.string(this.editor, { + anchor: this.getStart(), + focus: point, + }); + if (str.endsWith('[[')) { + Transforms.select(this.editor, { + anchor: point, + focus: Object.assign({}, point, { + offset: point.offset - 2, + }), + }); + Editor.addMark(this.editor, 'doubleLinkSearch', true); + Transforms.select(this.editor, { + anchor: this.editor.selection.anchor, + focus: this.editor.selection.anchor, + }); + } + } + + public getDoubleLinkSearchSlashText() { + const nodes = Editor.nodes(this.editor, { + at: [], + //@ts-ignore + match: node => !!node.doubleLinkSearch, + }); + const searchNode = nodes.next().value; + if (searchNode && (searchNode[0] as { text?: string }).text) { + return (searchNode[0] as { text?: string }).text; + } + return ''; + } + + public setSelectDoubleLinkSearchSlash() { + const nodes = Editor.nodes(this.editor, { + at: [], + //@ts-ignore + match: node => !!node.doubleLinkSearch, + }); + const searchNode = nodes.next().value; + if (searchNode) { + const text = (searchNode[0] as { text?: string })?.text || ''; + const path = searchNode[1]; + const anchor = Editor.before( this.editor, { - type: 'reflink', - reference, - children: [], + path, + offset: 1, }, - { at: focus || anchor } + { + unit: 'offset', + } ); - - // requestAnimationFrame(() => { - // console.log(this.editor.selection, this.editor.insertNode); - // this.editor.insertNode({ - // type: 'reflink', - // reference, - // children: [{ text: '' }] - // }); - // // Transforms.select(); - // }); - } catch (e) { - console.log(e); + const focus = Editor.after( + this.editor, + { + path, + offset: text.length - 1, + }, + { + unit: 'offset', + } + ); + Transforms.select(this.editor, { anchor, focus }); } } + public removeDoubleLinkSearchSlash(isRemoveSlash?: boolean) { + if (isRemoveSlash) { + const nodes = Editor.nodes(this.editor, { + at: [], + //@ts-ignore + match: node => !!node.doubleLinkSearch, + }); + const searchNode = nodes.next().value; + if (searchNode) { + const text = (searchNode[0] as { text?: string })?.text || ''; + if (text.startsWith('[[')) { + const path = searchNode[1]; + Transforms.delete(this.editor, { + at: { + path, + offset: 0, + }, + distance: text.length, + unit: 'character', + }); + } + } + } + Transforms.setNodes( + this.editor, + { doubleLinkSearch: null } as Partial, + { + at: [], + match: node => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + //@ts-ignore + return !!node.doubleLinkSearch; + }, + } + ); + this.editor.removeMark('doubleLinkSearch'); + } + + public insertDoubleLink( + workspaceId: string, + linkBlockId: string, + children: any[] + ) { + const link = { + type: 'link', + linkType: 'doubleLink', + workspaceId: workspaceId, + blockId: linkBlockId, + children: children, + id: getRandomString('link'), + }; + Transforms.insertNodes(this.editor, link); + requestAnimationFrame(() => { + ReactEditor.focus(this.editor); + }); + } + /** todo improve if selection is collapsed */ public getCommentsIdsBySelection() { const commentedTextNodes = Editor.nodes(this.editor, { diff --git a/libs/components/editor-core/src/editor/block/async-block.ts b/libs/components/editor-core/src/editor/block/async-block.ts index df2f6d972c..9eb156852e 100644 --- a/libs/components/editor-core/src/editor/block/async-block.ts +++ b/libs/components/editor-core/src/editor/block/async-block.ts @@ -1,19 +1,19 @@ /* eslint-disable max-lines */ -import EventEmitter from 'eventemitter3'; import { - ReturnEditorBlock, - UpdateEditorBlock, DefaultColumnsValue, Protocol, + ReturnEditorBlock, + UpdateEditorBlock, } from '@toeverything/datasource/db-service'; import { - isDev, createNoopWithMessage, - lowerFirst, + isDev, last, + lowerFirst, } from '@toeverything/utils'; -import { BlockProvider } from './block-provider'; +import EventEmitter from 'eventemitter3'; import { BaseView, BaseView as BlockView } from './../views/base-view'; +import { BlockProvider } from './block-provider'; type EventType = 'update'; export interface EventData { @@ -154,6 +154,7 @@ export class AsyncBlock { } this.initialized = true; this.raw_data = await this.filterPageInvalidChildren(this.raw_data); + this.raw_data = await this.updateDoubleLinkBlock(this.raw_data); const { workspace, id } = this.raw_data; this.unobserve = await this.services.observe( { workspace, id }, @@ -161,6 +162,7 @@ export class AsyncBlock { const oldData = this.raw_data; this.raw_data = blockData; this.raw_data = await this.filterPageInvalidChildren(blockData); + this.raw_data = await this.updateDoubleLinkBlock(this.raw_data); this.emit('update', { block: this, oldData }); } ); @@ -495,4 +497,35 @@ export class AsyncBlock { getBoundingClientRect() { return this.dom?.getBoundingClientRect(); } + + async updateDoubleLinkBlock(rawData: ReturnEditorBlock) { + const values = rawData.properties?.text?.value || []; + for (let i = 0; i < values.length; i++) { + const item = values[i] as any; + if (item.linkType === 'doubleLink') { + const linkBlock = await this.services.load({ + workspace: item.workspaceId, + id: item.blockId, + }); + + if (linkBlock) { + let children = linkBlock.getProperties().text?.value || []; + if (children.length === 1 && !children[0].text) { + children = [{ text: 'Untitled' }]; + } + if ( + children.map(v => v.text).join('') !== + (item.children || []).map((v: any) => v.text).join('') + ) { + const newItem = { + ...item, + children: children, + }; + values.splice(i, 1, newItem); + } + } + } + } + return rawData; + } } diff --git a/libs/components/editor-core/src/editor/block/block-helper.ts b/libs/components/editor-core/src/editor/block/block-helper.ts index 7bd0284ffc..012633b813 100644 --- a/libs/components/editor-core/src/editor/block/block-helper.ts +++ b/libs/components/editor-core/src/editor/block/block-helper.ts @@ -19,6 +19,11 @@ type TextUtilsFunctions = | 'setSearchSlash' | 'removeSearchSlash' | 'getSearchSlashText' + | 'setDoubleLinkSearchSlash' + | 'getDoubleLinkSearchSlashText' + | 'setSelectDoubleLinkSearchSlash' + | 'removeDoubleLinkSearchSlash' + | 'insertDoubleLink' | 'selectionToSlateRange' | 'transformPoint' | 'toggleTextFormatBySelection' @@ -32,7 +37,6 @@ type TextUtilsFunctions = | 'getCommentsIdsBySelection' | 'getCurrentSelection' | 'removeSelection' - | 'insertReference' | 'isCollapsed' | 'blur' | 'setSelection' @@ -149,27 +153,60 @@ export class BlockHelper { } } - public insertReference( - reference: string, + public setDoubleLinkSearchSlash(blockId: string, point: Point) { + const textUtils = this._blockTextUtilsMap[blockId]; + if (textUtils) { + textUtils.setDoubleLinkSearchSlash(point); + } else { + console.warn('Could find the block text utils'); + } + } + + public getDoubleLinkSearchSlashText(blockId: string) { + const textUtils = this._blockTextUtilsMap[blockId]; + if (textUtils) { + return textUtils.getDoubleLinkSearchSlashText(); + } + console.warn('Could find the block text utils'); + return ''; + } + public setSelectDoubleLinkSearchSlash(blockId: string) { + const textUtils = this._blockTextUtilsMap[blockId]; + if (textUtils) { + return textUtils.setSelectDoubleLinkSearchSlash(); + } + console.warn('Could find the block text utils'); + return ''; + } + + public removeDoubleLinkSearchSlash( blockId: string, - selection: Selection, - offset: number + isRemoveSlash?: boolean ) { - const text_utils = this._blockTextUtilsMap[blockId]; - if (text_utils) { - const offsetSelection = window.getSelection(); - offsetSelection.setBaseAndExtent( - selection.anchorNode, - selection.anchorOffset, - selection.focusNode, - selection.focusOffset + offset - ); + const textUtils = this._blockTextUtilsMap[blockId]; + if (textUtils) { + textUtils.removeDoubleLinkSearchSlash(isRemoveSlash); + } else { + console.warn('Could find the block text utils'); + } + } - text_utils.removeSelection(offsetSelection); - text_utils.insertReference(reference); - - // range. - // text_utils.toggleTextFormatBySelection(format, range); + public async insertDoubleLink( + workspaceId: string, + linkBlockId: string, + blockId: string + ) { + const textUtils = this._blockTextUtilsMap[blockId]; + if (textUtils) { + const linkBlock = await this._editor.getBlock({ + workspace: workspaceId, + id: linkBlockId, + }); + let children = linkBlock.getProperties().text?.value || []; + if (children.length === 1 && !children[0].text) { + children = [{ text: 'Untitled' }]; + } + textUtils.insertDoubleLink(workspaceId, linkBlockId, children); } console.warn('Could find the block text utils'); } diff --git a/libs/components/editor-core/src/editor/editor.ts b/libs/components/editor-core/src/editor/editor.ts index e85db2ba65..e7f6458a5f 100644 --- a/libs/components/editor-core/src/editor/editor.ts +++ b/libs/components/editor-core/src/editor/editor.ts @@ -1,17 +1,15 @@ /* eslint-disable max-lines */ -import HotKeys from 'hotkeys-js'; - import type { PatchNode } from '@toeverything/components/ui'; +import { Commands } from '@toeverything/datasource/commands'; import type { BlockFlavors, ReturnEditorBlock, UpdateEditorBlock, } from '@toeverything/datasource/db-service'; import { services } from '@toeverything/datasource/db-service'; - -import { Commands } from '@toeverything/datasource/commands'; import { domToRect, last, Point, sleep } from '@toeverything/utils'; import assert from 'assert'; +import HotKeys from 'hotkeys-js'; import type { WorkspaceAndBlockId } from './block'; import { AsyncBlock } from './block'; import { BlockHelper } from './block/block-helper'; @@ -282,7 +280,7 @@ export class Editor implements Virgo { return await blockView.onCreate(block); } - private async getBlock({ + public async getBlock({ workspace, id, }: WorkspaceAndBlockId): Promise { diff --git a/libs/components/editor-plugins/src/index.ts b/libs/components/editor-plugins/src/index.ts index be7bb9bd97..73cfece84f 100644 --- a/libs/components/editor-plugins/src/index.ts +++ b/libs/components/editor-plugins/src/index.ts @@ -1,15 +1,15 @@ import type { PluginCreator } from '@toeverything/framework/virgo'; -import { - LeftMenuPlugin, - InlineMenuPlugin, - CommandMenuPlugin, - ReferenceMenuPlugin, - SelectionGroupPlugin, - GroupMenuPlugin, -} from './menu'; -import { TemplatePlugin } from './template'; -import { FullTextSearchPlugin } from './search'; import { AddCommentPlugin } from './comment'; +import { + CommandMenuPlugin, + DoubleLinkMenuPlugin, + GroupMenuPlugin, + InlineMenuPlugin, + LeftMenuPlugin, + SelectionGroupPlugin, +} from './menu'; +import { FullTextSearchPlugin } from './search'; +import { TemplatePlugin } from './template'; // import { PlaceholderPlugin } from './placeholder'; // import { BlockPropertyPlugin } from './block-property'; @@ -19,7 +19,7 @@ export const plugins: PluginCreator[] = [ LeftMenuPlugin, InlineMenuPlugin, CommandMenuPlugin, - ReferenceMenuPlugin, + DoubleLinkMenuPlugin, TemplatePlugin, SelectionGroupPlugin, AddCommentPlugin, diff --git a/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx b/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx new file mode 100644 index 0000000000..8714ab519f --- /dev/null +++ b/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx @@ -0,0 +1,185 @@ +import React, { useEffect, useState, useCallback, useRef } from 'react'; + +import { Virgo, PluginHooks, HookType } from '@toeverything/framework/virgo'; +import { + CommonList, + CommonListItem, + commonListContainer, +} from '@toeverything/components/common'; +import { domToRect } from '@toeverything/utils'; +import { styled } from '@toeverything/components/ui'; + +import { QueryResult } from '../../search'; + +export type DoubleLinkMenuContainerProps = { + editor: Virgo; + hooks: PluginHooks; + style?: React.CSSProperties; + isShow?: boolean; + blockId: string; + onSelected?: (item: string) => void; + onClose?: () => void; + types?: Array; + items?: CommonListItem[]; +}; + +export const DoubleLinkMenuContainer = ({ + hooks, + isShow = false, + onSelected, + onClose, + types, + style, + items, +}: DoubleLinkMenuContainerProps) => { + const menuRef = useRef(null); + const [currentItem, setCurrentItem] = useState(); + const [needCheckIntoView, setNeedCheckIntoView] = useState(false); + + useEffect(() => { + if (needCheckIntoView) { + if (currentItem && menuRef.current) { + const itemEle = + menuRef.current.querySelector( + `.item-${currentItem}` + ); + const scrollEle = + menuRef.current.querySelector( + `.${commonListContainer}` + ); + if (itemEle) { + const itemRect = domToRect(itemEle); + const scrollRect = domToRect(scrollEle); + if ( + itemRect.top < scrollRect.top || + itemRect.bottom > scrollRect.bottom + ) { + // IMP: may be do it with self function + itemEle.scrollIntoView({ + block: 'nearest', + }); + } + } + } + setNeedCheckIntoView(false); + } + }, [needCheckIntoView, currentItem]); + + useEffect(() => { + if (isShow && types && !currentItem) setCurrentItem(types[0]); + if (!isShow) onClose?.(); + }, [currentItem, isShow, onClose, types]); + + useEffect(() => { + if (isShow && types) { + if (!types.includes(currentItem)) { + setNeedCheckIntoView(true); + if (types.length) { + setCurrentItem(types[0]); + } else { + setCurrentItem(undefined); + } + } + } + }, [isShow, types, currentItem]); + + const handleClickUp = useCallback( + (event: React.KeyboardEvent) => { + if (isShow && types && event.code === 'ArrowUp') { + event.preventDefault(); + if (!currentItem && types.length) { + setCurrentItem(types[types.length - 1]); + } + if (currentItem) { + const idx = types.indexOf(currentItem); + if (idx > 0) { + setNeedCheckIntoView(true); + setCurrentItem(types[idx - 1]); + } + } + } + }, + [isShow, types, currentItem] + ); + + const handleClickDown = useCallback( + (event: React.KeyboardEvent) => { + if (isShow && types && event.code === 'ArrowDown') { + event.preventDefault(); + if (!currentItem && types.length) { + setCurrentItem(types[0]); + } + if (currentItem) { + const idx = types.indexOf(currentItem); + if (idx < types.length - 1) { + setNeedCheckIntoView(true); + setCurrentItem(types[idx + 1]); + } + } + } + }, + [isShow, types, currentItem] + ); + + const handleClickEnter = useCallback( + async (event: React.KeyboardEvent) => { + if (isShow && event.code === 'Enter' && currentItem) { + event.preventDefault(); + onSelected && onSelected(currentItem); + } + }, + [isShow, currentItem, onSelected] + ); + + const handleKeyDown = useCallback( + (event: React.KeyboardEvent) => { + handleClickUp(event); + handleClickDown(event); + handleClickEnter(event); + }, + [handleClickUp, handleClickDown, handleClickEnter] + ); + + useEffect(() => { + const sub = hooks + .get(HookType.ON_ROOT_NODE_KEYDOWN_CAPTURE) + .subscribe(handleKeyDown); + + return () => { + sub.unsubscribe(); + }; + }, [hooks, handleKeyDown]); + + return isShow ? ( + + + onSelected?.(type)} + currentItem={currentItem} + setCurrentItem={setCurrentItem} + /> + + + ) : null; +}; + +const RootContainer = styled('div')(({ theme }) => ({ + // position: 'fixed', + zIndex: 1, + maxHeight: '525px', + borderRadius: '10px', + boxShadow: theme.affine.shadows.shadow1, + backgroundColor: '#fff', + padding: '8px 4px', +})); + +const ContentContainer = styled('div')(({ theme }) => ({ + display: 'flex', + overflow: 'hidden', + maxHeight: '493px', +})); diff --git a/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx b/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx new file mode 100644 index 0000000000..1f545809a3 --- /dev/null +++ b/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx @@ -0,0 +1,346 @@ +import { CommonListItem } from '@toeverything/components/common'; +import { AddIcon } from '@toeverything/components/icons'; +import { + ListButton, + MuiClickAwayListener, + MuiGrow as Grow, + MuiOutlinedInput as OutlinedInput, + MuiPaper as Paper, + MuiPopper as Popper, + styled, +} from '@toeverything/components/ui'; +import { services } from '@toeverything/datasource/db-service'; +import { HookType, PluginHooks, Virgo } from '@toeverything/framework/virgo'; +import { getPageId } from '@toeverything/utils'; +import React, { + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from 'react'; +import { QueryBlocks, QueryResult } from '../../search'; +import { DoubleLinkMenuContainer } from './Container'; + +const ADD_NEW_SUB_PAGE = 'AddNewSubPage'; +const ADD_NEW_PAGE = 'AddNewPage'; + +export type DoubleLinkMenuProps = { + editor: Virgo; + hooks: PluginHooks; + style?: { left: number; top: number }; +}; + +type DoubleMenuStyle = { + left: number; + top: number; + height: number; +}; + +export const DoubleLinkMenu = ({ + editor, + hooks, + style, +}: DoubleLinkMenuProps) => { + const [isShow, setIsShow] = useState(false); + const [blockId, setBlockId] = useState(); + const [searchText, setSearchText] = useState(''); + const [searchBlocks, setSearchBlocks] = useState([]); + const [items, setItems] = useState([]); + const [isNewPage, setIsNewPage] = useState(false); + const [anchorEl, setAnchorEl] = useState(null); + const ref = useRef(); + const ref1 = useRef(); + const [referenceMenuStyle, setReferenceMenuStyle] = + useState({ + left: 0, + top: 0, + height: 0, + }); + + useEffect(() => { + QueryBlocks(editor, searchText, result => { + setSearchBlocks(result); + ref1?.current?.focus(); + const items: CommonListItem[] = []; + if (searchBlocks?.length > 0) { + if (isNewPage) { + items.push({ + renderCustom: () => { + return ; + }, + }); + } else { + items.push({ + renderCustom: () => { + return ; + }, + }); + } + items.push( + ...(searchBlocks?.map( + block => ({ block } as CommonListItem) + ) || []) + ); + } + + if (items.length > 0) { + items.push({ divider: 'newPage' }); + } + items.push({ + content: { + id: ADD_NEW_SUB_PAGE, + content: 'Add new sub-page', + icon: AddIcon, + }, + }); + items.push({ + content: { + id: ADD_NEW_PAGE, + content: 'Add new page in...', + icon: AddIcon, + }, + }); + + setItems(items); + }); + }, [editor, searchText, isNewPage]); + + const types = useMemo(() => { + return Object.values(searchBlocks) + .map(({ id }) => id) + .concat([ADD_NEW_SUB_PAGE, ADD_NEW_PAGE]); + }, [searchBlocks]); + + const hideMenu = useCallback(() => { + setIsShow(false); + setIsNewPage(false); + editor.blockHelper.removeDoubleLinkSearchSlash(blockId); + editor.scrollManager.unLock(); + }, [blockId, editor.blockHelper, editor.scrollManager]); + + const handleSearch = useCallback( + async (event: React.KeyboardEvent) => { + const { type, anchorNode } = editor.selection.currentSelectInfo; + if ( + type === 'Range' && + anchorNode && + editor.blockHelper.isSelectionCollapsed(anchorNode.id) + ) { + const text = editor.blockHelper.getBlockTextBeforeSelection( + anchorNode.id + ); + + if (text.endsWith('[[')) { + if ( + [ + 'ArrowRight', + 'ArrowLeft', + 'ArrowUp', + 'ArrowDown', + ].includes(event.key) + ) { + return; + } + if (event.key === 'Backspace') { + hideMenu(); + return; + } + setBlockId(anchorNode.id); + editor.blockHelper.removeDoubleLinkSearchSlash(blockId); + setTimeout(() => { + const textSelection = + editor.blockHelper.selectionToSlateRange( + anchorNode.id, + editor.selection.currentSelectInfo + .browserSelection + ); + if (textSelection) { + const { anchor } = textSelection; + editor.blockHelper.setDoubleLinkSearchSlash( + anchorNode.id, + anchor + ); + } + }); + setSearchText(''); + setIsShow(true); + editor.scrollManager.lock(); + const rect = + editor.selection.currentSelectInfo?.browserSelection + ?.getRangeAt(0) + ?.getBoundingClientRect(); + if (rect) { + const rectTop = rect.top; + const { top, left } = + editor.container.getBoundingClientRect(); + setReferenceMenuStyle({ + top: rectTop - top, + left: rect.left - left, + height: rect.height, + }); + setAnchorEl(ref.current); + } + } + } + if (isShow) { + const searchText = + editor.blockHelper.getDoubleLinkSearchSlashText(blockId); + if (searchText && searchText.startsWith('[[')) { + setSearchText(searchText.slice(2).trim()); + } + } + }, + [editor, isShow, blockId, hideMenu] + ); + + const handleKeyup = useCallback( + (event: React.KeyboardEvent) => handleSearch(event), + [handleSearch] + ); + + const handleKeyDown = useCallback( + (event: React.KeyboardEvent) => { + if (event.code === 'Escape') { + hideMenu(); + } + }, + [hideMenu] + ); + + useEffect(() => { + const sub = hooks + .get(HookType.ON_ROOT_NODE_KEYUP) + .subscribe(handleKeyup); + sub.add( + hooks + .get(HookType.ON_ROOT_NODE_KEYDOWN_CAPTURE) + .subscribe(handleKeyDown) + ); + + return () => { + sub.unsubscribe(); + }; + }, [handleKeyup, handleKeyDown, hooks]); + + const handleSelected = async (linkBlockId: string) => { + if (blockId) { + if (linkBlockId === ADD_NEW_SUB_PAGE) { + handleAddSubPage(); + return; + } + if (linkBlockId === ADD_NEW_PAGE) { + setIsNewPage(true); + return; + } + if (isNewPage) { + const newPage = await services.api.editorBlock.create({ + workspace: editor.workspace, + type: 'page' as const, + }); + await services.api.pageTree.addChildPageToWorkspace( + editor.workspace, + linkBlockId, + newPage.id + ); + linkBlockId = newPage.id; + } + editor.blockHelper.setSelectDoubleLinkSearchSlash(blockId); + await editor.blockHelper.insertDoubleLink( + editor.workspace, + linkBlockId, + blockId + ); + hideMenu(); + } + }; + + const handleClose = () => { + blockId && editor.blockHelper.removeDoubleLinkSearchSlash(blockId); + }; + + const handleAddSubPage = async () => { + const newPage = await services.api.editorBlock.create({ + workspace: editor.workspace, + type: 'page' as const, + }); + setIsNewPage(false); + services.api.editorBlock.update({ + id: newPage.id, + workspace: editor.workspace, + properties: { + text: { value: [{ text: searchText }] }, + }, + }); + await services.api.pageTree.addChildPageToWorkspace( + editor.workspace, + getPageId(), + newPage.id + ); + handleSelected(newPage.id); + }; + + return ( +
+ hideMenu()}> + + {({ TransitionProps }) => ( + + + + + {}} + /> + + + + + + )} + + +
+ ); +}; + +const DoubleLinkMenuWrapper = styled('div')({ + zIndex: 1, +}); + +const SearchContainer = styled('div')({ + padding: '8px 8px', + input: { + height: '28px', + padding: '5px 10px', + with: '300px', + }, +}); diff --git a/libs/components/editor-plugins/src/menu/reference-menu/Plugin.tsx b/libs/components/editor-plugins/src/menu/double-link-menu/Plugin.tsx similarity index 79% rename from libs/components/editor-plugins/src/menu/reference-menu/Plugin.tsx rename to libs/components/editor-plugins/src/menu/double-link-menu/Plugin.tsx index 688adfd147..3933bf5f1c 100644 --- a/libs/components/editor-plugins/src/menu/reference-menu/Plugin.tsx +++ b/libs/components/editor-plugins/src/menu/double-link-menu/Plugin.tsx @@ -1,12 +1,11 @@ import { StrictMode } from 'react'; - import { BasePlugin } from '../../base-plugin'; import { PluginRenderRoot } from '../../utils'; -import { ReferenceMenu } from './ReferenceMenu'; +import { DoubleLinkMenu } from './DoubleLinkMenu'; const PLUGIN_NAME = 'reference-menu'; -export class ReferenceMenuPlugin extends BasePlugin { +export class DoubleLinkMenuPlugin extends BasePlugin { private _root?: PluginRenderRoot; public static override get pluginName(): string { @@ -22,7 +21,7 @@ export class ReferenceMenuPlugin extends BasePlugin { this._root?.render( - + ); } diff --git a/libs/components/editor-plugins/src/menu/double-link-menu/index.ts b/libs/components/editor-plugins/src/menu/double-link-menu/index.ts new file mode 100644 index 0000000000..e287e74e03 --- /dev/null +++ b/libs/components/editor-plugins/src/menu/double-link-menu/index.ts @@ -0,0 +1 @@ +export { DoubleLinkMenuPlugin } from './Plugin'; diff --git a/libs/components/editor-plugins/src/menu/index.ts b/libs/components/editor-plugins/src/menu/index.ts index 50d4133651..190e3a5109 100644 --- a/libs/components/editor-plugins/src/menu/index.ts +++ b/libs/components/editor-plugins/src/menu/index.ts @@ -1,9 +1,7 @@ +export { CommandMenuPlugin } from './command-menu'; +export { DoubleLinkMenuPlugin } from './double-link-menu'; +export { GroupMenuPlugin } from './group-menu'; export { InlineMenuPlugin } from './inline-menu'; export { LeftMenuPlugin } from './left-menu/LeftMenuPlugin'; -export { CommandMenuPlugin } from './command-menu'; -export { ReferenceMenuPlugin } from './reference-menu'; -export { SelectionGroupPlugin } from './selection-group-menu'; - export { MENU_WIDTH as menuWidth } from './left-menu/menu-config'; - -export { GroupMenuPlugin } from './group-menu'; +export { SelectionGroupPlugin } from './selection-group-menu'; diff --git a/libs/components/editor-plugins/src/menu/reference-menu/Container.tsx b/libs/components/editor-plugins/src/menu/reference-menu/Container.tsx deleted file mode 100644 index 42ca2d679d..0000000000 --- a/libs/components/editor-plugins/src/menu/reference-menu/Container.tsx +++ /dev/null @@ -1,190 +0,0 @@ -import React, { useEffect, useState, useCallback, useRef } from 'react'; - -import { Virgo, PluginHooks, HookType } from '@toeverything/framework/virgo'; -import { - CommonList, - CommonListItem, - commonListContainer, -} from '@toeverything/components/common'; -import { domToRect } from '@toeverything/utils'; -import { styled } from '@toeverything/components/ui'; - -import { QueryResult } from '../../search'; - -export type ReferenceMenuContainerProps = { - editor: Virgo; - hooks: PluginHooks; - style?: React.CSSProperties; - isShow?: boolean; - blockId: string; - onSelected?: (item: string) => void; - onClose?: () => void; - searchBlocks?: QueryResult; - types?: Array; -}; - -export const ReferenceMenuContainer = ({ - hooks, - isShow = false, - onSelected, - onClose, - types, - searchBlocks, - style, -}: ReferenceMenuContainerProps) => { - const menu_ref = useRef(null); - const [current_item, set_current_item] = useState(); - const [need_check_into_view, set_need_check_into_view] = - useState(false); - - useEffect(() => { - if (need_check_into_view) { - if (current_item && menu_ref.current) { - const item_ele = - menu_ref.current.querySelector( - `.item-${current_item}` - ); - const scroll_ele = - menu_ref.current.querySelector( - `.${commonListContainer}` - ); - if (item_ele) { - const itemRect = domToRect(item_ele); - const scrollRect = domToRect(scroll_ele); - if ( - itemRect.top < scrollRect.top || - itemRect.bottom > scrollRect.bottom - ) { - // IMP: may be do it with self function - item_ele.scrollIntoView({ - block: 'nearest', - }); - } - } - } - set_need_check_into_view(false); - } - }, [need_check_into_view, current_item]); - - useEffect(() => { - if (isShow && types && !current_item) set_current_item(types[0]); - if (!isShow) onClose?.(); - }, [current_item, isShow, onClose, types]); - - useEffect(() => { - if (isShow && types) { - if (!types.includes(current_item)) { - set_need_check_into_view(true); - if (types.length) { - set_current_item(types[0]); - } else { - set_current_item(undefined); - } - } - } - }, [isShow, types, current_item]); - - const handle_click_up = useCallback( - (event: React.KeyboardEvent) => { - if (isShow && types && event.code === 'ArrowUp') { - event.preventDefault(); - if (!current_item && types.length) { - set_current_item(types[types.length - 1]); - } - if (current_item) { - const idx = types.indexOf(current_item); - if (idx > 0) { - set_need_check_into_view(true); - set_current_item(types[idx - 1]); - } - } - } - }, - [isShow, types, current_item] - ); - - const handle_click_down = useCallback( - (event: React.KeyboardEvent) => { - if (isShow && types && event.code === 'ArrowDown') { - event.preventDefault(); - if (!current_item && types.length) { - set_current_item(types[0]); - } - if (current_item) { - const idx = types.indexOf(current_item); - if (idx < types.length - 1) { - set_need_check_into_view(true); - set_current_item(types[idx + 1]); - } - } - } - }, - [isShow, types, current_item] - ); - - const handle_click_enter = useCallback( - async (event: React.KeyboardEvent) => { - if (isShow && event.code === 'Enter' && current_item) { - event.preventDefault(); - onSelected && onSelected(current_item); - } - }, - [isShow, current_item, onSelected] - ); - - const handle_key_down = useCallback( - (event: React.KeyboardEvent) => { - handle_click_up(event); - handle_click_down(event); - handle_click_enter(event); - }, - [handle_click_up, handle_click_down, handle_click_enter] - ); - - useEffect(() => { - const sub = hooks - .get(HookType.ON_ROOT_NODE_KEYDOWN_CAPTURE) - .subscribe(handle_key_down); - - return () => { - sub.unsubscribe(); - }; - }, [hooks, handle_key_down]); - - return isShow ? ( - - - ({ block } as CommonListItem) - ) || [] - } - onSelected={type => onSelected?.(type)} - currentItem={current_item} - setCurrentItem={set_current_item} - /> - - - ) : null; -}; - -const RootContainer = styled('div')(({ theme }) => ({ - position: 'fixed', - zIndex: 1, - maxHeight: '525px', - borderRadius: '10px', - boxShadow: theme.affine.shadows.shadow1, - backgroundColor: '#fff', - padding: '8px 4px', -})); - -const ContentContainer = styled('div')(({ theme }) => ({ - display: 'flex', - overflow: 'hidden', - maxHeight: '493px', -})); diff --git a/libs/components/editor-plugins/src/menu/reference-menu/ReferenceMenu.tsx b/libs/components/editor-plugins/src/menu/reference-menu/ReferenceMenu.tsx deleted file mode 100644 index af1cd96cea..0000000000 --- a/libs/components/editor-plugins/src/menu/reference-menu/ReferenceMenu.tsx +++ /dev/null @@ -1,148 +0,0 @@ -import React, { useCallback, useEffect, useMemo, useState } from 'react'; - -import { MuiClickAwayListener, styled } from '@toeverything/components/ui'; -import { Virgo, HookType, PluginHooks } from '@toeverything/framework/virgo'; -import { Point } from '@toeverything/utils'; - -import { ReferenceMenuContainer } from './Container'; -import { QueryBlocks, QueryResult } from '../../search'; - -export type ReferenceMenuProps = { - editor: Virgo; - hooks: PluginHooks; - style?: { left: number; top: number }; -}; - -export type RefLinkComponent = { - type: 'reflink'; - reference: string; -}; - -const BEFORE_REGEX = /\[\[(.*)$/; - -export const ReferenceMenu = ({ editor, hooks, style }: ReferenceMenuProps) => { - const [is_show, set_is_show] = useState(false); - const [block_id, set_block_id] = useState(); - const [position, set_position] = useState(new Point(0, 0)); - - const [search_text, set_search_text] = useState(''); - const [search_blocks, set_search_blocks] = useState([]); - - useEffect(() => { - QueryBlocks(editor, search_text, result => set_search_blocks(result)); - }, [editor, search_text]); - - const search_block_ids = useMemo( - () => Object.values(search_blocks).map(({ id }) => id), - [search_blocks] - ); - - const handle_search = useCallback( - async (event: React.KeyboardEvent) => { - const { type, anchorNode } = editor.selection.currentSelectInfo; - if ( - type === 'Range' && - anchorNode && - editor.blockHelper.isSelectionCollapsed(anchorNode.id) - ) { - const text = editor.blockHelper.getBlockTextBeforeSelection( - anchorNode.id - ); - const matched = BEFORE_REGEX.exec(text)?.[1]; - - if (typeof matched === 'string') { - if (event.key === '[') set_is_show(true); - - set_block_id(anchorNode.id); - set_search_text(matched); - - const rect = - editor.selection.currentSelectInfo?.browserSelection - ?.getRangeAt(0) - ?.getBoundingClientRect(); - if (rect) { - set_position(new Point(rect.left, rect.top + 24)); - } - } else if (is_show) { - set_is_show(false); - } - } - }, - [editor, is_show] - ); - - const handle_keyup = useCallback( - (event: React.KeyboardEvent) => handle_search(event), - [handle_search] - ); - - const handle_key_down = useCallback( - (event: React.KeyboardEvent) => { - if (event.code === 'Escape') { - set_is_show(false); - } - }, - [] - ); - - useEffect(() => { - const sub = hooks - .get(HookType.ON_ROOT_NODE_KEYUP) - .subscribe(handle_keyup); - sub.add( - hooks - .get(HookType.ON_ROOT_NODE_KEYDOWN_CAPTURE) - .subscribe(handle_key_down) - ); - - return () => { - sub.unsubscribe(); - }; - }, [handle_keyup, handle_key_down, hooks]); - - const handle_selected = async (reference: string) => { - if (block_id) { - const { anchorNode } = editor.selection.currentSelectInfo; - editor.blockHelper.insertReference( - reference, - anchorNode.id, - editor.selection.currentSelectInfo?.browserSelection, - -search_text.length - 2 - ); - } - - set_is_show(false); - }; - - const handle_close = () => { - block_id && editor.blockHelper.removeSearchSlash(block_id); - }; - - return ( - - set_is_show(false)}> -
- -
-
-
- ); -}; - -const ReferenceMenuWrapper = styled('div')({ - position: 'absolute', - zIndex: 1, -}); diff --git a/libs/components/editor-plugins/src/menu/reference-menu/index.ts b/libs/components/editor-plugins/src/menu/reference-menu/index.ts deleted file mode 100644 index 0a3879e398..0000000000 --- a/libs/components/editor-plugins/src/menu/reference-menu/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { ReferenceMenuPlugin } from './Plugin'; diff --git a/libs/components/ui/src/button/ListButton.tsx b/libs/components/ui/src/button/ListButton.tsx index 1d6cead375..30e5ca9a31 100644 --- a/libs/components/ui/src/button/ListButton.tsx +++ b/libs/components/ui/src/button/ListButton.tsx @@ -1,6 +1,5 @@ import clsx from 'clsx'; import style9 from 'style9'; - import { SvgIconProps } from '../svg-icon'; import { BaseButton } from './base-button'; @@ -35,7 +34,7 @@ const styles = style9.create({ type ListButtonProps = { className?: string; - onClick: () => void; + onClick?: () => void; onMouseOver?: () => void; content?: string; children?: () => JSX.Element; diff --git a/libs/datasource/jwt/src/index.ts b/libs/datasource/jwt/src/index.ts index 50fec96d5e..664e0f21fa 100644 --- a/libs/datasource/jwt/src/index.ts +++ b/libs/datasource/jwt/src/index.ts @@ -1,7 +1,6 @@ /* eslint-disable max-lines */ import { DocumentSearchOptions } from 'flexsearch'; import LRUCache from 'lru-cache'; - import { AsyncDatabaseAdapter, BlockInstance, @@ -290,19 +289,22 @@ export class BlockClient< | string | Partial> ): Promise { - const promised_pages = await Promise.all( - this.search(part_of_title_or_content).flatMap(({ result }) => - result.map(async id => { - const page = this._pageMapping.get(id as string); - if (page) return page; - const block = await this.get(id as BlockTypeKeys); - return this.set_page(block); - }) - ) - ); - const pages = [ - ...new Set(promised_pages.filter((v): v is string => !!v)), - ]; + let pages = []; + if (part_of_title_or_content) { + const promisedPages = await Promise.all( + this.search(part_of_title_or_content).flatMap(({ result }) => + result.map(async id => { + const page = this._pageMapping.get(id as string); + if (page) return page; + const block = await this.get(id as BlockTypeKeys); + return this.set_page(block); + }) + ) + ); + pages = [...new Set(promisedPages.filter((v): v is string => !!v))]; + } else { + pages = await this.getBlockByFlavor('page'); + } return Promise.all( this._blockIndexer.getMetadata(pages).map(async page => ({ content: this.get_decoded_content( From 6bdb7b48762f3f700bf3f330ffb93b9473143834 Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Fri, 5 Aug 2022 18:55:30 +0800 Subject: [PATCH 06/58] chore: disable selection group plugin --- libs/components/editor-plugins/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/components/editor-plugins/src/index.ts b/libs/components/editor-plugins/src/index.ts index be7bb9bd97..ab657a9904 100644 --- a/libs/components/editor-plugins/src/index.ts +++ b/libs/components/editor-plugins/src/index.ts @@ -21,7 +21,7 @@ export const plugins: PluginCreator[] = [ CommandMenuPlugin, ReferenceMenuPlugin, TemplatePlugin, - SelectionGroupPlugin, + // SelectionGroupPlugin, AddCommentPlugin, GroupMenuPlugin, ]; From 407ee4d8f0ca544580e407e76007410f1ea82725 Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Fri, 5 Aug 2022 18:56:25 +0800 Subject: [PATCH 07/58] feat: add kanban card mask --- .../blocks/group/scene-kanban/CardItem.tsx | 63 ++++++++++++++++--- 1 file changed, 53 insertions(+), 10 deletions(-) diff --git a/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx b/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx index 76220d7ff0..eba13f0db6 100644 --- a/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx +++ b/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx @@ -4,8 +4,14 @@ import { useKanban, useRefPage, } from '@toeverything/components/editor-core'; -import { styled } from '@toeverything/components/ui'; +import { PenIcon } from '@toeverything/components/icons'; +import { + IconButton, + MuiClickAwayListener, + styled, +} from '@toeverything/components/ui'; import { useFlag } from '@toeverything/datasource/feature-flags'; +import { useState } from 'react'; const CardContent = styled('div')({ margin: '20px', @@ -23,6 +29,7 @@ const CardActions = styled('div')({ fontWeight: '300', color: '#98ACBD', transition: 'all ease-in 0.2s', + zIndex: 1, ':hover': { background: '#F5F7F8', @@ -39,11 +46,13 @@ const PlusIcon = styled('div')({ }); const CardContainer = styled('div')({ + position: 'relative', display: 'flex', flexDirection: 'column', backgroundColor: '#fff', border: '1px solid #E2E7ED', borderRadius: '5px', + overflow: 'hidden', [CardActions.toString()]: { opacity: '0', @@ -55,6 +64,23 @@ const CardContainer = styled('div')({ }, }); +const Overlay = styled('div')({ + position: 'absolute', + width: '100%', + height: '100%', + background: 'transparent', + + '& > *': { + visibility: 'hidden', + position: 'absolute', + right: '24px', + top: '16px', + }, + '&:hover > *': { + visibility: 'visible', + }, +}); + export const CardItem = ({ id, block, @@ -64,8 +90,11 @@ export const CardItem = ({ }) => { const { addSubItem } = useKanban(); const { openSubPage } = useRefPage(); + const [editable, setEditable] = useState(false); const showKanbanRefPageFlag = useFlag('ShowKanbanRefPage', false); + const onAddItem = async () => { + setEditable(true); await addSubItem(block); }; @@ -74,14 +103,28 @@ export const CardItem = ({ }; return ( - - - - - - - Add a sub-block - - + setEditable(false)}> + + + + + {!editable && ( + + { + e.stopPropagation(); + setEditable(true); + }} + > + + + + )} + + + Add a sub-block + + + ); }; From dcdc7f8862e3b5435c1ebfd0d9c6688b0de1efa7 Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Wed, 10 Aug 2022 17:41:13 +0800 Subject: [PATCH 08/58] refactor: ref page use AffineEditor --- .../src/blocks/group/scene-kanban/CardItem.tsx | 7 ++----- .../src/blocks/group/scene-kanban/RefPage.tsx} | 16 +++++++++++++--- libs/components/editor-core/src/index.ts | 2 +- .../editor-core/src/recast-block/Context.tsx | 3 +-- .../components/editor-core/src/ref-page/index.ts | 1 - 5 files changed, 17 insertions(+), 12 deletions(-) rename libs/components/{editor-core/src/ref-page/ModalPage.tsx => editor-blocks/src/blocks/group/scene-kanban/RefPage.tsx} (82%) delete mode 100644 libs/components/editor-core/src/ref-page/index.ts diff --git a/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx b/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx index eba13f0db6..c1cc9f9a1c 100644 --- a/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx +++ b/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx @@ -1,9 +1,5 @@ import type { KanbanCard } from '@toeverything/components/editor-core'; -import { - RenderBlock, - useKanban, - useRefPage, -} from '@toeverything/components/editor-core'; +import { RenderBlock, useKanban } from '@toeverything/components/editor-core'; import { PenIcon } from '@toeverything/components/icons'; import { IconButton, @@ -12,6 +8,7 @@ import { } from '@toeverything/components/ui'; import { useFlag } from '@toeverything/datasource/feature-flags'; import { useState } from 'react'; +import { useRefPage } from './RefPage'; const CardContent = styled('div')({ margin: '20px', diff --git a/libs/components/editor-core/src/ref-page/ModalPage.tsx b/libs/components/editor-blocks/src/blocks/group/scene-kanban/RefPage.tsx similarity index 82% rename from libs/components/editor-core/src/ref-page/ModalPage.tsx rename to libs/components/editor-blocks/src/blocks/group/scene-kanban/RefPage.tsx index 52e1d6554f..cd3588162e 100644 --- a/libs/components/editor-core/src/ref-page/ModalPage.tsx +++ b/libs/components/editor-blocks/src/blocks/group/scene-kanban/RefPage.tsx @@ -1,7 +1,8 @@ +import { AffineEditor } from '@toeverything/components/affine-editor'; +import { useEditor } from '@toeverything/components/editor-core'; import { MuiBackdrop, styled, useTheme } from '@toeverything/components/ui'; import { createContext, ReactNode, useContext, useState } from 'react'; import { createPortal } from 'react-dom'; -import { RenderBlock } from '../render-block'; const Dialog = styled('div')({ flex: 1, @@ -30,7 +31,7 @@ const Modal = ({ open, children }: { open: boolean; children?: ReactNode }) => { onClick={closeSubPage} > { + onClick={(e: { stopPropagation: () => void }) => { e.stopPropagation(); }} > @@ -43,9 +44,18 @@ const Modal = ({ open, children }: { open: boolean; children?: ReactNode }) => { }; const ModalPage = ({ blockId }: { blockId: string | null }) => { + const { editor } = useEditor(); + return ( - {blockId && } + {blockId && ( + + )} ); }; diff --git a/libs/components/editor-core/src/index.ts b/libs/components/editor-core/src/index.ts index bea2fed3a0..d28d8e96b3 100644 --- a/libs/components/editor-core/src/index.ts +++ b/libs/components/editor-core/src/index.ts @@ -16,4 +16,4 @@ export * from './utils'; export * from './editor'; -export { RefPageProvider, useRefPage } from './ref-page'; +export { useEditor } from './Contexts'; diff --git a/libs/components/editor-core/src/recast-block/Context.tsx b/libs/components/editor-core/src/recast-block/Context.tsx index 47ec6cfcdb..4236ede55a 100644 --- a/libs/components/editor-core/src/recast-block/Context.tsx +++ b/libs/components/editor-core/src/recast-block/Context.tsx @@ -2,7 +2,6 @@ import { Protocol } from '@toeverything/datasource/db-service'; import { AsyncBlock } from '../editor'; import { ComponentType, createContext, ReactNode, useContext } from 'react'; import { RecastBlock } from './types'; -import { RefPageProvider } from '../ref-page'; /** * Determine whether the block supports RecastBlock @@ -48,7 +47,7 @@ export const RecastBlockProvider = ({ return ( - {children} + {children} ); }; diff --git a/libs/components/editor-core/src/ref-page/index.ts b/libs/components/editor-core/src/ref-page/index.ts deleted file mode 100644 index 4b06310a5c..0000000000 --- a/libs/components/editor-core/src/ref-page/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { useRefPage, RefPageProvider } from './ModalPage'; From 4a99080860d15515345060483e59593b94632162 Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Fri, 12 Aug 2022 13:52:54 +0800 Subject: [PATCH 09/58] chore: set kanban RefPageProvider --- .../blocks/group/scene-kanban/SceneKanban.tsx | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/libs/components/editor-blocks/src/blocks/group/scene-kanban/SceneKanban.tsx b/libs/components/editor-blocks/src/blocks/group/scene-kanban/SceneKanban.tsx index 27d5543177..73424708a7 100644 --- a/libs/components/editor-blocks/src/blocks/group/scene-kanban/SceneKanban.tsx +++ b/libs/components/editor-blocks/src/blocks/group/scene-kanban/SceneKanban.tsx @@ -4,30 +4,33 @@ import { SceneKanbanContext } from './context'; import { CardContainerWrapper } from './dndable/wrapper/CardContainerWrapper'; import type { ComponentType } from 'react'; import type { CreateView } from '@toeverything/framework/virgo'; +import { RefPageProvider } from './RefPage'; export const SceneKanban: ComponentType = withKanban( ({ editor, block }) => { const { kanban } = useKanban(); return ( - - ( - - )} - /> - + + + ( + + )} + /> + + ); } ); From d300b039ad0f3e1fc7c5c227e44fb73ff4d88949 Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Wed, 17 Aug 2022 19:07:55 +0800 Subject: [PATCH 10/58] fix: renaming to edgeless --- .../editor-blocks/src/blocks/group/scene-kanban/RefPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/components/editor-blocks/src/blocks/group/scene-kanban/RefPage.tsx b/libs/components/editor-blocks/src/blocks/group/scene-kanban/RefPage.tsx index cd3588162e..b3353001b0 100644 --- a/libs/components/editor-blocks/src/blocks/group/scene-kanban/RefPage.tsx +++ b/libs/components/editor-blocks/src/blocks/group/scene-kanban/RefPage.tsx @@ -53,7 +53,7 @@ const ModalPage = ({ blockId }: { blockId: string | null }) => { workspace={editor.workspace} rootBlockId={blockId} scrollBlank={false} - isWhiteboard + isEdgeless /> )} From 05361e75a405745e4a3f5c5328e9917ee47c6345 Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Wed, 17 Aug 2022 19:08:16 +0800 Subject: [PATCH 11/58] fix: add pen background --- .../src/blocks/group/scene-kanban/CardItem.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx b/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx index c1cc9f9a1c..c98efdf0f5 100644 --- a/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx +++ b/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx @@ -1,5 +1,9 @@ -import type { KanbanCard } from '@toeverything/components/editor-core'; -import { RenderBlock, useKanban } from '@toeverything/components/editor-core'; +import { + KanbanCard, + RenderBlock, + useEditor, + useKanban, +} from '@toeverything/components/editor-core'; import { PenIcon } from '@toeverything/components/icons'; import { IconButton, @@ -89,6 +93,7 @@ export const CardItem = ({ const { openSubPage } = useRefPage(); const [editable, setEditable] = useState(false); const showKanbanRefPageFlag = useFlag('ShowKanbanRefPage', false); + const { editor } = useEditor(); const onAddItem = async () => { setEditable(true); @@ -108,9 +113,13 @@ export const CardItem = ({ {!editable && ( { e.stopPropagation(); setEditable(true); + editor.selectionManager.activeNodeByNodeId( + block.id + ); }} > From 06d442a8c18a773920ef10f4dfb8aa487d45f2a0 Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Thu, 18 Aug 2022 17:09:28 +0800 Subject: [PATCH 12/58] refactor: clean anti pattern editor element --- .../src/blocks/embed-link/EmbedLinkView.tsx | 7 +++---- .../src/components/source-view/BlockView.tsx | 8 ++++---- .../src/components/source-view/SourceView.tsx | 17 ++++------------- .../editor-core/src/editor/views/base-view.ts | 1 - .../src/render-block/RenderBlock.tsx | 3 +-- 5 files changed, 12 insertions(+), 24 deletions(-) diff --git a/libs/components/editor-blocks/src/blocks/embed-link/EmbedLinkView.tsx b/libs/components/editor-blocks/src/blocks/embed-link/EmbedLinkView.tsx index 86881478ff..86b43908d1 100644 --- a/libs/components/editor-blocks/src/blocks/embed-link/EmbedLinkView.tsx +++ b/libs/components/editor-blocks/src/blocks/embed-link/EmbedLinkView.tsx @@ -1,12 +1,12 @@ -import { useState } from 'react'; -import { CreateView } from '@toeverything/framework/virgo'; import { BlockPendantProvider, useOnSelect, } from '@toeverything/components/editor-core'; -import { Upload } from '../../components/upload/upload'; +import { CreateView } from '@toeverything/framework/virgo'; +import { useState } from 'react'; import { SourceView } from '../../components/source-view'; import { LinkContainer } from '../../components/style-container'; +import { Upload } from '../../components/upload/upload'; const MESSAGES = { ADD_EMBED_LINK: 'Add embed link', @@ -38,7 +38,6 @@ export const EmbedLinkView = (props: EmbedLinkView) => { {embedLinkUrl ? ( { type BlockPreviewProps = { block: AsyncBlock; blockId: string; - editorElement?: () => JSX.Element; }; const InternalBlockPreview = (props: BlockPreviewProps) => { const container = useRef(); const [preview, setPreview] = useState(true); const title = useBlockTitle(props.block, props.blockId); + const { editorElement } = useEditor(); - const AffineEditor = props.editorElement as any; + const AffineEditor = editorElement as any; useEffect(() => { if (container?.current) { diff --git a/libs/components/editor-blocks/src/components/source-view/SourceView.tsx b/libs/components/editor-blocks/src/components/source-view/SourceView.tsx index b03189d7d4..27d19433bf 100644 --- a/libs/components/editor-blocks/src/components/source-view/SourceView.tsx +++ b/libs/components/editor-blocks/src/components/source-view/SourceView.tsx @@ -1,17 +1,15 @@ import { AsyncBlock, useCurrentView, - useLazyIframe, } from '@toeverything/components/editor-core'; import { styled } from '@toeverything/components/ui'; -import { ReactElement, ReactNode, useEffect, useRef, useState } from 'react'; +import { ReactNode, useEffect, useRef, useState } from 'react'; import { SCENE_CONFIG } from '../../blocks/group/config'; import { BlockPreview } from './BlockView'; import { formatUrl } from './format-url'; export interface Props { block: AsyncBlock; - editorElement?: () => JSX.Element; viewType?: string; link: string; // onResizeEnd: (data: any) => void; @@ -150,7 +148,7 @@ const LoadingContiner = () => { }; export const SourceView = (props: Props) => { - const { link, isSelected, block, editorElement } = props; + const { link, isSelected, block } = props; const src = formatUrl(link); // let iframeShow = useLazyIframe(src, 3000, iframeContainer); const [currentView] = useCurrentView(); @@ -161,10 +159,7 @@ export const SourceView = (props: Props) => { - + ); @@ -175,11 +170,7 @@ export const SourceView = (props: Props) => { style={{ padding: '0' }} scene={type} > - + ); } diff --git a/libs/components/editor-core/src/editor/views/base-view.ts b/libs/components/editor-core/src/editor/views/base-view.ts index b69cdd848a..eb5c293243 100644 --- a/libs/components/editor-core/src/editor/views/base-view.ts +++ b/libs/components/editor-core/src/editor/views/base-view.ts @@ -18,7 +18,6 @@ import { SelectBlock } from '../selection'; export interface CreateView { block: AsyncBlock; editor: Editor; - editorElement: () => JSX.Element; /** * @deprecated Use recast table instead */ diff --git a/libs/components/editor-core/src/render-block/RenderBlock.tsx b/libs/components/editor-core/src/render-block/RenderBlock.tsx index 0627aba95b..0a1531a709 100644 --- a/libs/components/editor-core/src/render-block/RenderBlock.tsx +++ b/libs/components/editor-core/src/render-block/RenderBlock.tsx @@ -13,7 +13,7 @@ export function RenderBlock({ blockId, hasContainer = true, }: RenderBlockProps) { - const { editor, editorElement } = useEditor(); + const { editor } = useEditor(); const { block } = useBlock(blockId); const setRef = useCallback( @@ -50,7 +50,6 @@ export function RenderBlock({ block={block} columns={columns.columns} columnsFromId={columns.fromId} - editorElement={editorElement} /> ); From 0d89fa10261aaeb55160f320e71b7a8821c8d95b Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Thu, 18 Aug 2022 17:11:39 +0800 Subject: [PATCH 13/58] fix: workaround circular dependency editor element --- .../editor-blocks/src/blocks/group/scene-kanban/RefPage.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libs/components/editor-blocks/src/blocks/group/scene-kanban/RefPage.tsx b/libs/components/editor-blocks/src/blocks/group/scene-kanban/RefPage.tsx index b3353001b0..3d223d121d 100644 --- a/libs/components/editor-blocks/src/blocks/group/scene-kanban/RefPage.tsx +++ b/libs/components/editor-blocks/src/blocks/group/scene-kanban/RefPage.tsx @@ -1,4 +1,3 @@ -import { AffineEditor } from '@toeverything/components/affine-editor'; import { useEditor } from '@toeverything/components/editor-core'; import { MuiBackdrop, styled, useTheme } from '@toeverything/components/ui'; import { createContext, ReactNode, useContext, useState } from 'react'; @@ -44,7 +43,9 @@ const Modal = ({ open, children }: { open: boolean; children?: ReactNode }) => { }; const ModalPage = ({ blockId }: { blockId: string | null }) => { - const { editor } = useEditor(); + const { editor, editorElement } = useEditor(); + + const AffineEditor = editorElement as any; return ( @@ -53,6 +54,7 @@ const ModalPage = ({ blockId }: { blockId: string | null }) => { workspace={editor.workspace} rootBlockId={blockId} scrollBlank={false} + // use edgeless mode prevent padding and blank bottom isEdgeless /> )} From 42cc6e90420f89d5f2868accc539b0150b63eb75 Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Thu, 18 Aug 2022 17:59:21 +0800 Subject: [PATCH 14/58] chore: clean card item --- .../blocks/group/scene-kanban/CardItem.tsx | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx b/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx index c98efdf0f5..837772bed2 100644 --- a/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx +++ b/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx @@ -11,7 +11,7 @@ import { styled, } from '@toeverything/components/ui'; import { useFlag } from '@toeverything/datasource/feature-flags'; -import { useState } from 'react'; +import { useState, type MouseEvent } from 'react'; import { useRefPage } from './RefPage'; const CardContent = styled('div')({ @@ -101,7 +101,13 @@ export const CardItem = ({ }; const onClickCard = async () => { - showKanbanRefPageFlag && openSubPage(id); + openSubPage(id); + }; + + const onClickPen = (e: MouseEvent) => { + e.stopPropagation(); + setEditable(true); + editor.selectionManager.activeNodeByNodeId(block.id); }; return ( @@ -110,18 +116,9 @@ export const CardItem = ({ - {!editable && ( + {showKanbanRefPageFlag && !editable && ( - { - e.stopPropagation(); - setEditable(true); - editor.selectionManager.activeNodeByNodeId( - block.id - ); - }} - > + From 6915c9c2a5084ff9612dc5b6a51c9105d91c6bdb Mon Sep 17 00:00:00 2001 From: austaras Date: Thu, 18 Aug 2022 17:26:11 +0800 Subject: [PATCH 15/58] fix(whiteboard): only allow pan when middle button is pressed --- libs/components/board-state/src/tldraw-app.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libs/components/board-state/src/tldraw-app.ts b/libs/components/board-state/src/tldraw-app.ts index e4b7a8a34f..5dd9ad09b2 100644 --- a/libs/components/board-state/src/tldraw-app.ts +++ b/libs/components/board-state/src/tldraw-app.ts @@ -3841,7 +3841,7 @@ export class TldrawApp extends StateManager { private get_viewbox_from_svg = (svgStr: string | ArrayBuffer | null) => { if (typeof svgStr === 'string') { - let viewBox = new DOMParser().parseFromString(svgStr, 'text/xml'); + const viewBox = new DOMParser().parseFromString(svgStr, 'text/xml'); return viewBox.children[0].getAttribute('viewBox'); } @@ -4125,7 +4125,7 @@ export class TldrawApp extends StateManager { }; onPointerDown: TLPointerEventHandler = (info, e) => { - if (e.buttons === 4) { + if (e.button === 1) { this.patchState({ settings: { forcePanning: true, @@ -4142,6 +4142,13 @@ export class TldrawApp extends StateManager { }; onPointerUp: TLPointerEventHandler = (info, e) => { + if (e.button === 1) { + this.patchState({ + settings: { + forcePanning: false, + }, + }); + } this.isPointing = false; this.updateInputs(info, e); this.currentTool.onPointerUp?.(info, e); From 4724aee96eb2fbe2b3d92b66211985cf63a548ac Mon Sep 17 00:00:00 2001 From: DiamondThree Date: Thu, 18 Aug 2022 18:22:52 +0800 Subject: [PATCH 16/58] fix:shapaes bidings error --- libs/components/affine-board/src/Board.tsx | 45 ++++++++- .../affine-board/src/hooks/use-shapes.ts | 97 +++++++++++++++---- libs/components/board-draw/src/TlDraw.tsx | 19 ++-- libs/components/board-state/src/tldraw-app.ts | 12 +-- .../utils/column/default-config.ts | 1 + 5 files changed, 132 insertions(+), 42 deletions(-) diff --git a/libs/components/affine-board/src/Board.tsx b/libs/components/affine-board/src/Board.tsx index 82c2948c49..d6cb1240bd 100644 --- a/libs/components/affine-board/src/Board.tsx +++ b/libs/components/affine-board/src/Board.tsx @@ -18,7 +18,6 @@ interface AffineBoardProps { const AffineBoard = ({ workspace, rootBlockId }: AffineBoardProps) => { const [app, set_app] = useState(); - const [document] = useState(() => { return { ...deepCopy(TldrawApp.default_document), @@ -45,10 +44,12 @@ const AffineBoard = ({ workspace, rootBlockId }: AffineBoardProps) => { }; }); - const shapes = useShapes(workspace, rootBlockId); + const { shapes, bindings } = useShapes(workspace, rootBlockId); + + // const bindings = useBindings(workspace, rootBlockId); useEffect(() => { if (app) { - app.replacePageContent(shapes || {}, {}, {}); + app.replacePageContent(shapes || {}, bindings, {}); } }, [app, shapes]); @@ -62,8 +63,11 @@ const AffineBoard = ({ workspace, rootBlockId }: AffineBoardProps) => { onMount(app) { set_app(app); }, - onChangePage(app, shapes, bindings, assets) { - Promise.all( + async onChangePage(app, shapes, bindings, assets) { + console.log('shapes, bindings: ', shapes, bindings); + // + + await Promise.all( Object.entries(shapes).map(async ([id, shape]) => { if (shape === undefined) { return services.api.editorBlock.delete({ @@ -91,6 +95,21 @@ const AffineBoard = ({ workspace, rootBlockId }: AffineBoardProps) => { }); } shape.affineId = block.id; + Object.keys(bindings).forEach(bilingKey => { + if (!bindings[bilingKey]) { + delete bindings[bilingKey]; + } + if ( + bindings[bilingKey]?.fromId === shape.id + ) { + bindings[bilingKey].fromId = block.id; + } + if ( + bindings[bilingKey]?.toId === shape.id + ) { + bindings[bilingKey].toId = block.id; + } + }); return services.api.editorBlock.update({ workspace: shape.workspace, id: block.id, @@ -103,6 +122,22 @@ const AffineBoard = ({ workspace, rootBlockId }: AffineBoardProps) => { } }) ); + // let pageBindings = services.api.editorBlock.get({workspace: workspace,ids:[rootBlockId]})?[0] + let block = ( + await services.api.editorBlock.get({ + workspace: workspace, + ids: [rootBlockId], + }) + )?.[0]; + services.api.editorBlock.update({ + workspace: workspace, + id: block.id, + properties: { + bindings: { + value: JSON.stringify(bindings), + }, + }, + }); }, }} /> diff --git a/libs/components/affine-board/src/hooks/use-shapes.ts b/libs/components/affine-board/src/hooks/use-shapes.ts index 7d07a25957..c7f22744ed 100644 --- a/libs/components/affine-board/src/hooks/use-shapes.ts +++ b/libs/components/affine-board/src/hooks/use-shapes.ts @@ -9,24 +9,45 @@ export const useShapes = (workspace: string, rootBlockId: string) => { const { pageClientWidth } = usePageClientWidth(); // page padding left and right total 300px const editorShapeInitSize = pageClientWidth - 300; - const [blocks, setBlocks] = useState(); + const [blocks, setBlocks] = useState<{ + shapes: [ReturnEditorBlock[]]; + bindings: string; + }>(); useEffect(() => { - services.api.editorBlock - .get({ workspace, ids: [rootBlockId] }) - .then(async blockData => { - const shapes = await Promise.all( - (blockData?.[0]?.children || []).map(async childId => { - const childBlock = ( - await services.api.editorBlock.get({ - workspace, - ids: [childId], - }) - )?.[0]; - return childBlock; - }) - ); - setBlocks(shapes); - }); + Promise.all([ + services.api.editorBlock + .get({ workspace, ids: [rootBlockId] }) + .then(async blockData => { + const shapes = await Promise.all( + (blockData?.[0]?.children || []).map(async childId => { + const childBlock = ( + await services.api.editorBlock.get({ + workspace, + ids: [childId], + }) + )?.[0]; + return childBlock; + }) + ); + return shapes; + // setBlocks(shapes); + }), + ]).then(shapes => { + console.log(shapes); + services.api.editorBlock + .get({ + workspace: workspace, + ids: [rootBlockId], + }) + .then(blcoks => { + setBlocks({ + shapes, + bindings: blcoks[0].properties.bindings?.value, + }); + // setBindings(blcoks[0].properties.bindings?.value); + }); + }); + let unobserve: () => void; services.api.editorBlock .observe({ workspace, id: rootBlockId }, async blockData => { @@ -40,8 +61,23 @@ export const useShapes = (workspace: string, rootBlockId: string) => { )?.[0]; return childBlock; }) - ); - setBlocks(shapes); + ).then(shapes => { + console.log(shapes); + services.api.editorBlock + .get({ + workspace: workspace, + ids: [rootBlockId], + }) + .then(blcoks => { + setBlocks({ + shapes: [shapes], + bindings: blcoks[0].properties.bindings?.value, + }); + // setBindings(blcoks[0].properties.bindings?.value); + }); + }); + return shapes; + // setBlocks(shapes); }) .then(cb => { unobserve = cb; @@ -53,8 +89,7 @@ export const useShapes = (workspace: string, rootBlockId: string) => { }, [workspace, rootBlockId]); let groupCount = 0; - - return blocks?.reduce((acc, block) => { + let blocksShapes = blocks?.shapes[0]?.reduce((acc, block) => { const shapeProps = block.properties.shapeProps?.value ? JSON.parse(block.properties.shapeProps.value) : {}; @@ -75,4 +110,24 @@ export const useShapes = (workspace: string, rootBlockId: string) => { return acc; }, {} as Record); + return { + shapes: blocksShapes, + bindings: JSON.parse(blocks?.bindings ?? '{}'), + }; +}; + +export const useBindings = (workspace: string, rootBlockId: string) => { + const [bindings, setBindings] = useState(); + useEffect(() => { + services.api.editorBlock + .get({ + workspace: workspace, + ids: [rootBlockId], + }) + .then(blcoks => { + setBindings(blcoks[0].properties.bindings?.value); + }); + return () => {}; + }, [workspace, rootBlockId]); + return bindings ? JSON.parse(bindings) : {}; }; diff --git a/libs/components/board-draw/src/TlDraw.tsx b/libs/components/board-draw/src/TlDraw.tsx index 338fffeeaf..1961367235 100644 --- a/libs/components/board-draw/src/TlDraw.tsx +++ b/libs/components/board-draw/src/TlDraw.tsx @@ -13,6 +13,8 @@ import { TDStatus, } from '@toeverything/components/board-types'; import { styled } from '@toeverything/components/ui'; +// import { FocusButton } from '~components/FocusButton'; +import { usePageClientWidth } from '@toeverything/datasource/state'; import { memo, useEffect, @@ -22,22 +24,20 @@ import { useState, type RefObject, } from 'react'; +import { ErrorBoundary } from 'react-error-boundary'; +import { CommandPanel } from './components/command-panel'; +// import { TopPanel } from '~components/TopPanel'; +import { ContextMenu } from './components/context-menu'; +import { ErrorFallback } from './components/error-fallback'; +import { Loading } from './components/loading'; import { ToolsPanel } from './components/tools-panel'; +import { ZoomBar } from './components/zoom-bar'; import { TldrawContext, useKeyboardShortcuts, useStylesheet, useTldrawApp, } from './hooks'; -// import { TopPanel } from '~components/TopPanel'; -import { ContextMenu } from './components/context-menu'; -// import { FocusButton } from '~components/FocusButton'; -import { usePageClientWidth } from '@toeverything/datasource/state'; -import { ErrorBoundary } from 'react-error-boundary'; -import { CommandPanel } from './components/command-panel'; -import { ErrorFallback } from './components/error-fallback'; -import { Loading } from './components/loading'; -import { ZoomBar } from './components/zoom-bar'; export interface TldrawProps extends TldrawAppCtorProps { /** @@ -295,7 +295,6 @@ const InnerTldraw = memo(function InnerTldraw({ const pageState = document.pageStates[page.id]; const assets = document.assets; const { selectedIds } = pageState; - const isHideBoundsShape = selectedIds.length === 1 && page.shapes[selectedIds[0]] && diff --git a/libs/components/board-state/src/tldraw-app.ts b/libs/components/board-state/src/tldraw-app.ts index e4b7a8a34f..79d7215e99 100644 --- a/libs/components/board-state/src/tldraw-app.ts +++ b/libs/components/board-state/src/tldraw-app.ts @@ -15,13 +15,13 @@ import { TLPointerEventHandler, TLShapeCloneHandler, TLWheelEventHandler, - Utils, + Utils } from '@tldraw/core'; import { Vec } from '@tldraw/vec'; import { clearPrevSize, defaultStyle, - shapeUtils, + shapeUtils } from '@toeverything/components/board-shapes'; import { AlignType, @@ -54,7 +54,7 @@ import { TDUser, TldrawCommand, USER_COLORS, - VIDEO_EXTENSIONS, + VIDEO_EXTENSIONS } from '@toeverything/components/board-types'; import { MIN_PAGE_WIDTH } from '@toeverything/components/editor-core'; import { @@ -67,7 +67,7 @@ import { migrate, openAssetFromFileSystem, openFromFileSystem, - saveToFileSystem, + saveToFileSystem } from './data'; import { getClipboard, setClipboard } from './idb-clipboard'; import { StateManager } from './manager/state-manager'; @@ -440,7 +440,6 @@ export class TldrawApp extends StateManager { if (visitedShapes.has(fromShape)) { return; } - // We only need to update the binding's "from" shape (an arrow) const fromDelta = TLDR.update_arrow_bindings( page, @@ -856,14 +855,15 @@ export class TldrawApp extends StateManager { if (!page.bindings[binding.id]) { return; } - const fromShape = page.shapes[binding.fromId] as ArrowShape; if (visitedShapes.has(fromShape)) { return; } + // We only need to update the binding's "from" shape (an arrow) + const fromDelta = TLDR.update_arrow_bindings(page, fromShape); visitedShapes.add(fromShape); diff --git a/libs/datasource/db-service/src/services/editor-block/utils/column/default-config.ts b/libs/datasource/db-service/src/services/editor-block/utils/column/default-config.ts index f2d1c861b6..ca51be0f8c 100644 --- a/libs/datasource/db-service/src/services/editor-block/utils/column/default-config.ts +++ b/libs/datasource/db-service/src/services/editor-block/utils/column/default-config.ts @@ -53,6 +53,7 @@ export type DefaultColumnsValue = { filterConstraint: FilterConstraint; filterWeakSqlConstraint: string; sorterConstraint: SorterConstraint; + bindings: StringColumnValue; }; export const DEFAULT_COLUMN_KEYS = { From a58825dd2fbb5e336dbea30fd45887dc07ad8d13 Mon Sep 17 00:00:00 2001 From: xiaodong zuo Date: Fri, 19 Aug 2022 05:23:25 +0800 Subject: [PATCH 17/58] feat: Intra-line double link interaction --- libs/components/common/src/lib/list/index.tsx | 4 +- .../src/menu/double-link-menu/Container.tsx | 41 +-- .../menu/double-link-menu/DoubleLinkMenu.tsx | 347 +++++++++--------- 3 files changed, 195 insertions(+), 197 deletions(-) diff --git a/libs/components/common/src/lib/list/index.tsx b/libs/components/common/src/lib/list/index.tsx index 7de7e35b8e..c00a4e1415 100644 --- a/libs/components/common/src/lib/list/index.tsx +++ b/libs/components/common/src/lib/list/index.tsx @@ -57,7 +57,9 @@ export const CommonList = (props: MenuItemsProps) => { > {usedItems?.length ? ( usedItems.map((item, idx) => { - if (item.block) { + if (item.renderCustom) { + return item.renderCustom(item); + } else if (item.block) { return ( void; onClose?: () => void; @@ -25,7 +21,6 @@ export type DoubleLinkMenuContainerProps = { export const DoubleLinkMenuContainer = ({ hooks, - isShow = false, onSelected, onClose, types, @@ -66,12 +61,13 @@ export const DoubleLinkMenuContainer = ({ }, [needCheckIntoView, currentItem]); useEffect(() => { - if (isShow && types && !currentItem) setCurrentItem(types[0]); - if (!isShow) onClose?.(); - }, [currentItem, isShow, onClose, types]); + if (types && !currentItem) { + setCurrentItem(types[0]); + } + }, [currentItem, onClose, types]); useEffect(() => { - if (isShow && types) { + if (types) { if (!types.includes(currentItem)) { setNeedCheckIntoView(true); if (types.length) { @@ -81,11 +77,11 @@ export const DoubleLinkMenuContainer = ({ } } } - }, [isShow, types, currentItem]); + }, [types, currentItem]); const handleClickUp = useCallback( (event: React.KeyboardEvent) => { - if (isShow && types && event.code === 'ArrowUp') { + if (types && event.code === 'ArrowUp') { event.preventDefault(); if (!currentItem && types.length) { setCurrentItem(types[types.length - 1]); @@ -99,12 +95,12 @@ export const DoubleLinkMenuContainer = ({ } } }, - [isShow, types, currentItem] + [types, currentItem] ); const handleClickDown = useCallback( (event: React.KeyboardEvent) => { - if (isShow && types && event.code === 'ArrowDown') { + if (types && event.code === 'ArrowDown') { event.preventDefault(); if (!currentItem && types.length) { setCurrentItem(types[0]); @@ -118,17 +114,17 @@ export const DoubleLinkMenuContainer = ({ } } }, - [isShow, types, currentItem] + [types, currentItem] ); const handleClickEnter = useCallback( async (event: React.KeyboardEvent) => { - if (isShow && event.code === 'Enter' && currentItem) { + if (event.code === 'Enter' && currentItem) { event.preventDefault(); onSelected && onSelected(currentItem); } }, - [isShow, currentItem, onSelected] + [currentItem, onSelected] ); const handleKeyDown = useCallback( @@ -150,7 +146,7 @@ export const DoubleLinkMenuContainer = ({ }; }, [hooks, handleKeyDown]); - return isShow ? ( + return ( - ) : null; + ); }; const RootContainer = styled('div')(({ theme }) => ({ - // position: 'fixed', zIndex: 1, maxHeight: '525px', borderRadius: '10px', diff --git a/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx b/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx index 1f545809a3..e79ab7b90b 100644 --- a/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx +++ b/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx @@ -1,10 +1,10 @@ import { CommonListItem } from '@toeverything/components/common'; import { AddIcon } from '@toeverything/components/icons'; import { + Input, ListButton, MuiClickAwayListener, MuiGrow as Grow, - MuiOutlinedInput as OutlinedInput, MuiPaper as Paper, MuiPopper as Popper, styled, @@ -13,6 +13,7 @@ import { services } from '@toeverything/datasource/db-service'; import { HookType, PluginHooks, Virgo } from '@toeverything/framework/virgo'; import { getPageId } from '@toeverything/utils'; import React, { + ChangeEvent, useCallback, useEffect, useMemo, @@ -24,6 +25,7 @@ import { DoubleLinkMenuContainer } from './Container'; const ADD_NEW_SUB_PAGE = 'AddNewSubPage'; const ADD_NEW_PAGE = 'AddNewPage'; +const ARRAY_KEYS = ['ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown']; export type DoubleLinkMenuProps = { editor: Virgo; @@ -31,7 +33,7 @@ export type DoubleLinkMenuProps = { style?: { left: number; top: number }; }; -type DoubleMenuStyle = { +type DoubleLinkMenuStyle = { left: number; top: number; height: number; @@ -42,58 +44,63 @@ export const DoubleLinkMenu = ({ hooks, style, }: DoubleLinkMenuProps) => { - const [isShow, setIsShow] = useState(false); - const [blockId, setBlockId] = useState(); - const [searchText, setSearchText] = useState(''); - const [searchBlocks, setSearchBlocks] = useState([]); - const [items, setItems] = useState([]); - const [isNewPage, setIsNewPage] = useState(false); + const [isOpen, setIsOpen] = useState(false); const [anchorEl, setAnchorEl] = useState(null); - const ref = useRef(); - const ref1 = useRef(); - const [referenceMenuStyle, setReferenceMenuStyle] = - useState({ + const dialogRef = useRef(); + const newPageSearchRef = useRef(); + const [doubleLinkMenuStyle, setDoubleLinkMenuStyle] = + useState({ left: 0, top: 0, height: 0, }); - useEffect(() => { - QueryBlocks(editor, searchText, result => { - setSearchBlocks(result); - ref1?.current?.focus(); - const items: CommonListItem[] = []; - if (searchBlocks?.length > 0) { - if (isNewPage) { - items.push({ - renderCustom: () => { - return ; - }, - }); - } else { - items.push({ - renderCustom: () => { - return ; - }, - }); - } - items.push( - ...(searchBlocks?.map( - block => ({ block } as CommonListItem) - ) || []) - ); - } + const [curBlockId, setCurBlockId] = useState(); + const [searchText, setSearchText] = useState(''); + const [inAddNewPage, setInAddNewPage] = useState(false); + const [filterText, setFilterText] = useState(''); + const [searchResultBlocks, setSearchResultBlocks] = useState( + [] + ); - if (items.length > 0) { - items.push({ divider: 'newPage' }); - } + const menuTypes = useMemo(() => { + return Object.values(searchResultBlocks) + .map(({ id }) => id) + .concat([ADD_NEW_SUB_PAGE, ADD_NEW_PAGE]); + }, [searchResultBlocks]); + + const menuItems: CommonListItem[] = useMemo(() => { + const items: CommonListItem[] = []; + if (searchResultBlocks?.length > 0) { items.push({ - content: { - id: ADD_NEW_SUB_PAGE, - content: 'Add new sub-page', - icon: AddIcon, + renderCustom: () => { + return ( + + ); }, }); + items.push( + ...(searchResultBlocks?.map( + block => ({ block } as CommonListItem) + ) || []) + ); + } + + if (items.length > 0) { + items.push({ divider: 'newPage' }); + } + items.push({ + content: { + id: ADD_NEW_SUB_PAGE, + content: 'Add new sub-page', + icon: AddIcon, + }, + }); + !inAddNewPage && items.push({ content: { id: ADD_NEW_PAGE, @@ -101,26 +108,28 @@ export const DoubleLinkMenu = ({ icon: AddIcon, }, }); + return items; + }, [searchResultBlocks, inAddNewPage]); - setItems(items); + useEffect(() => { + const text = inAddNewPage ? filterText : searchText; + QueryBlocks(editor, text, result => { + setSearchResultBlocks(result); }); - }, [editor, searchText, isNewPage]); - - const types = useMemo(() => { - return Object.values(searchBlocks) - .map(({ id }) => id) - .concat([ADD_NEW_SUB_PAGE, ADD_NEW_PAGE]); - }, [searchBlocks]); + }, [editor, searchText, filterText, inAddNewPage]); const hideMenu = useCallback(() => { - setIsShow(false); - setIsNewPage(false); - editor.blockHelper.removeDoubleLinkSearchSlash(blockId); + setIsOpen(false); + setInAddNewPage(false); + editor.blockHelper.removeDoubleLinkSearchSlash(curBlockId); editor.scrollManager.unLock(); - }, [blockId, editor.blockHelper, editor.scrollManager]); + }, [curBlockId, editor]); - const handleSearch = useCallback( + const searchChange = useCallback( async (event: React.KeyboardEvent) => { + if (ARRAY_KEYS.includes(event.key)) { + return; + } const { type, anchorNode } = editor.selection.currentSelectInfo; if ( type === 'Range' && @@ -130,24 +139,31 @@ export const DoubleLinkMenu = ({ const text = editor.blockHelper.getBlockTextBeforeSelection( anchorNode.id ); - if (text.endsWith('[[')) { - if ( - [ - 'ArrowRight', - 'ArrowLeft', - 'ArrowUp', - 'ArrowDown', - ].includes(event.key) - ) { - return; - } if (event.key === 'Backspace') { hideMenu(); return; } - setBlockId(anchorNode.id); - editor.blockHelper.removeDoubleLinkSearchSlash(blockId); + editor.blockHelper.removeDoubleLinkSearchSlash(curBlockId); + setCurBlockId(anchorNode.id); + setSearchText(''); + setIsOpen(true); + editor.scrollManager.lock(); + const clientRect = + editor.selection.currentSelectInfo?.browserSelection + ?.getRangeAt(0) + ?.getBoundingClientRect(); + if (clientRect) { + const rectTop = clientRect.top; + const { top, left } = + editor.container.getBoundingClientRect(); + setDoubleLinkMenuStyle({ + top: rectTop - top, + left: clientRect.left - left, + height: clientRect.height, + }); + setAnchorEl(dialogRef.current); + } setTimeout(() => { const textSelection = editor.blockHelper.selectionToSlateRange( @@ -163,40 +179,22 @@ export const DoubleLinkMenu = ({ ); } }); - setSearchText(''); - setIsShow(true); - editor.scrollManager.lock(); - const rect = - editor.selection.currentSelectInfo?.browserSelection - ?.getRangeAt(0) - ?.getBoundingClientRect(); - if (rect) { - const rectTop = rect.top; - const { top, left } = - editor.container.getBoundingClientRect(); - setReferenceMenuStyle({ - top: rectTop - top, - left: rect.left - left, - height: rect.height, - }); - setAnchorEl(ref.current); - } } } - if (isShow) { + if (isOpen) { const searchText = - editor.blockHelper.getDoubleLinkSearchSlashText(blockId); + editor.blockHelper.getDoubleLinkSearchSlashText(curBlockId); if (searchText && searchText.startsWith('[[')) { setSearchText(searchText.slice(2).trim()); } } }, - [editor, isShow, blockId, hideMenu] + [editor, isOpen, curBlockId, hideMenu] ); const handleKeyup = useCallback( - (event: React.KeyboardEvent) => handleSearch(event), - [handleSearch] + (event: React.KeyboardEvent) => searchChange(event), + [searchChange] ); const handleKeyDown = useCallback( @@ -223,75 +221,86 @@ export const DoubleLinkMenu = ({ }; }, [handleKeyup, handleKeyDown, hooks]); - const handleSelected = async (linkBlockId: string) => { - if (blockId) { - if (linkBlockId === ADD_NEW_SUB_PAGE) { - handleAddSubPage(); - return; - } - if (linkBlockId === ADD_NEW_PAGE) { - setIsNewPage(true); - return; - } - if (isNewPage) { - const newPage = await services.api.editorBlock.create({ - workspace: editor.workspace, - type: 'page' as const, - }); - await services.api.pageTree.addChildPageToWorkspace( - editor.workspace, - linkBlockId, - newPage.id - ); - linkBlockId = newPage.id; - } - editor.blockHelper.setSelectDoubleLinkSearchSlash(blockId); + const insertDoubleLink = useCallback( + async (pageId: string) => { + editor.blockHelper.setSelectDoubleLinkSearchSlash(curBlockId); await editor.blockHelper.insertDoubleLink( editor.workspace, - linkBlockId, - blockId + pageId, + curBlockId ); hideMenu(); + }, + [editor, curBlockId, hideMenu] + ); + + const addSubPage = useCallback( + async (parentPageId: string) => { + const newPage = await services.api.editorBlock.create({ + workspace: editor.workspace, + type: 'page' as const, + }); + services.api.editorBlock.update({ + id: newPage.id, + workspace: editor.workspace, + properties: { + text: { value: [{ text: searchText }] }, + }, + }); + await services.api.pageTree.addChildPageToWorkspace( + editor.workspace, + parentPageId, + newPage.id + ); + return newPage.id; + }, + [searchText, editor] + ); + + const handleSelected = async (id: string) => { + if (curBlockId) { + if (id === ADD_NEW_PAGE) { + setInAddNewPage(true); + setTimeout(() => { + newPageSearchRef.current?.focus(); + }); + return; + } + if (id === ADD_NEW_SUB_PAGE) { + const pageId = await addSubPage(getPageId()); + insertDoubleLink(pageId); + return; + } + if (inAddNewPage) { + const pageId = await addSubPage(id); + insertDoubleLink(pageId); + } else { + insertDoubleLink(id); + } } }; - const handleClose = () => { - blockId && editor.blockHelper.removeDoubleLinkSearchSlash(blockId); - }; + const handleFilterChange = useCallback( + async (e: ChangeEvent) => { + const text = e.target.value; - const handleAddSubPage = async () => { - const newPage = await services.api.editorBlock.create({ - workspace: editor.workspace, - type: 'page' as const, - }); - setIsNewPage(false); - services.api.editorBlock.update({ - id: newPage.id, - workspace: editor.workspace, - properties: { - text: { value: [{ text: searchText }] }, - }, - }); - await services.api.pageTree.addChildPageToWorkspace( - editor.workspace, - getPageId(), - newPage.id - ); - handleSelected(newPage.id); - }; + await setFilterText(text); + }, + [] + ); return (
hideMenu()}> - - - {}} + {inAddNewPage && ( + + - - - + + )} + )} @@ -332,15 +342,6 @@ export const DoubleLinkMenu = ({ ); }; -const DoubleLinkMenuWrapper = styled('div')({ - zIndex: 1, -}); - -const SearchContainer = styled('div')({ - padding: '8px 8px', - input: { - height: '28px', - padding: '5px 10px', - with: '300px', - }, +const NewPageSearchContainer = styled('div')({ + padding: '8px 8px 0px 8px', }); From 438d814d49ff3421a0941db2c14ac6f7a99c2318 Mon Sep 17 00:00:00 2001 From: xiaodong zuo Date: Fri, 19 Aug 2022 06:17:30 +0800 Subject: [PATCH 18/58] feat: Intra-line double link interaction --- .../common/src/lib/text/EditableText.tsx | 4 +-- .../src/menu/double-link-menu/Container.tsx | 3 +- .../menu/double-link-menu/DoubleLinkMenu.tsx | 33 +++++++++++++++++-- .../editor-plugins/src/search/Search.tsx | 15 ++++----- 4 files changed, 38 insertions(+), 17 deletions(-) diff --git a/libs/components/common/src/lib/text/EditableText.tsx b/libs/components/common/src/lib/text/EditableText.tsx index 7bc6c3904a..8637246d7d 100644 --- a/libs/components/common/src/lib/text/EditableText.tsx +++ b/libs/components/common/src/lib/text/EditableText.tsx @@ -1,5 +1,4 @@ /* eslint-disable max-lines */ -import { SearchIcon } from '@toeverything/components/icons'; import { ErrorBoundary, isEqual } from '@toeverything/utils'; import isHotkey from 'is-hotkey'; import isUrl from 'is-url'; @@ -844,8 +843,7 @@ const EditorLeaf = ({ attributes, children, leaf }: any) => { if (leaf.doubleLinkSearch) { customChildren = ( - - + {customChildren} ); diff --git a/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx b/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx index 2fa8c71ba2..dd62fd1def 100644 --- a/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx +++ b/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx @@ -166,7 +166,6 @@ export const DoubleLinkMenuContainer = ({ const RootContainer = styled('div')(({ theme }) => ({ zIndex: 1, - maxHeight: '525px', borderRadius: '10px', boxShadow: theme.affine.shadows.shadow1, backgroundColor: '#fff', @@ -176,5 +175,5 @@ const RootContainer = styled('div')(({ theme }) => ({ const ContentContainer = styled('div')(({ theme }) => ({ display: 'flex', overflow: 'hidden', - maxHeight: '493px', + maxHeight: '300px', })); diff --git a/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx b/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx index e79ab7b90b..21fb7c1afc 100644 --- a/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx +++ b/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx @@ -56,7 +56,7 @@ export const DoubleLinkMenu = ({ }); const [curBlockId, setCurBlockId] = useState(); - const [searchText, setSearchText] = useState(''); + const [searchText, setSearchText] = useState(); const [inAddNewPage, setInAddNewPage] = useState(false); const [filterText, setFilterText] = useState(''); const [searchResultBlocks, setSearchResultBlocks] = useState( @@ -85,7 +85,13 @@ export const DoubleLinkMenu = ({ }); items.push( ...(searchResultBlocks?.map( - block => ({ block } as CommonListItem) + block => + ({ + block: { + ...block, + content: block.content || 'Untitled', + }, + } as CommonListItem) ) || []) ); } @@ -199,11 +205,32 @@ export const DoubleLinkMenu = ({ const handleKeyDown = useCallback( (event: React.KeyboardEvent) => { + if (!isOpen) { + return; + } if (event.code === 'Escape') { hideMenu(); } + const { type, anchorNode } = editor.selection.currentSelectInfo; + if ( + type === 'Range' && + anchorNode && + editor.blockHelper.isSelectionCollapsed(anchorNode.id) + ) { + const text = editor.blockHelper.getBlockTextBeforeSelection( + anchorNode.id + ); + if (text.endsWith('[[')) { + if (event.key === 'Backspace') { + event.preventDefault(); + event.stopPropagation(); + hideMenu(); + return; + } + } + } }, - [hideMenu] + [hideMenu, editor, isOpen] ); useEffect(() => { diff --git a/libs/components/editor-plugins/src/search/Search.tsx b/libs/components/editor-plugins/src/search/Search.tsx index 6b02b6334e..b689345f64 100644 --- a/libs/components/editor-plugins/src/search/Search.tsx +++ b/libs/components/editor-plugins/src/search/Search.tsx @@ -1,16 +1,15 @@ -import { useCallback, useEffect, useState } from 'react'; -import { useNavigate, useParams } from 'react-router'; -import style9 from 'style9'; - import { BlockPreview } from '@toeverything/components/common'; import { - TransitionsModal, MuiBox as Box, MuiBox, styled, + TransitionsModal, } from '@toeverything/components/ui'; -import { Virgo, BlockEditor } from '@toeverything/framework/virgo'; +import { BlockEditor, Virgo } from '@toeverything/framework/virgo'; import { throttle } from '@toeverything/utils'; +import { useCallback, useEffect, useState } from 'react'; +import { useNavigate, useParams } from 'react-router'; +import style9 from 'style9'; const styles = style9.create({ wrapper: { @@ -37,9 +36,7 @@ const query_blocks = ( search: string, callback: (result: QueryResult) => void ) => { - (editor as BlockEditor) - .search(search) - .then(pages => callback(pages.filter(b => !!b.content))); + (editor as BlockEditor).search(search).then(pages => callback(pages)); }; export const QueryBlocks = throttle(query_blocks, 500); From f0f60654e839dc1b730cc123a59917a4dcad4f7a Mon Sep 17 00:00:00 2001 From: xiaodong zuo Date: Fri, 19 Aug 2022 09:57:04 +0800 Subject: [PATCH 19/58] feat: Intra-line double link interaction --- .../src/lib/text/plugins/DoubleLink.tsx | 1 + .../common/src/lib/text/slate-utils.ts | 4 ++ .../menu/double-link-menu/DoubleLinkMenu.tsx | 62 ++++++++++--------- 3 files changed, 38 insertions(+), 29 deletions(-) diff --git a/libs/components/common/src/lib/text/plugins/DoubleLink.tsx b/libs/components/common/src/lib/text/plugins/DoubleLink.tsx index 8160731bf2..822b684323 100644 --- a/libs/components/common/src/lib/text/plugins/DoubleLink.tsx +++ b/libs/components/common/src/lib/text/plugins/DoubleLink.tsx @@ -20,6 +20,7 @@ export const DoubleLinkComponent = ({ attributes, children, element }: any) => { {children} diff --git a/libs/components/common/src/lib/text/slate-utils.ts b/libs/components/common/src/lib/text/slate-utils.ts index 9b1fff664c..a1cf6f2c95 100644 --- a/libs/components/common/src/lib/text/slate-utils.ts +++ b/libs/components/common/src/lib/text/slate-utils.ts @@ -599,6 +599,10 @@ class SlateUtils { const textChildren: Text[] = []; for (const child of fragmentChildren) { + if ((child as any).type === 'link') { + textChildren.push(child as Text); + continue; + } if (!('text' in child)) { console.error('Debug information:', point1, point2, fragment); throw new Error('Fragment exists nested!'); diff --git a/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx b/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx index 21fb7c1afc..c012010eb1 100644 --- a/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx +++ b/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx @@ -11,7 +11,6 @@ import { } from '@toeverything/components/ui'; import { services } from '@toeverything/datasource/db-service'; import { HookType, PluginHooks, Virgo } from '@toeverything/framework/virgo'; -import { getPageId } from '@toeverything/utils'; import React, { ChangeEvent, useCallback, @@ -20,12 +19,13 @@ import React, { useRef, useState, } from 'react'; +import { useParams } from 'react-router-dom'; import { QueryBlocks, QueryResult } from '../../search'; import { DoubleLinkMenuContainer } from './Container'; const ADD_NEW_SUB_PAGE = 'AddNewSubPage'; const ADD_NEW_PAGE = 'AddNewPage'; -const ARRAY_KEYS = ['ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown']; +const ARRAY_CODES = ['ArrowRight', 'ArrowLeft', 'ArrowUp', 'ArrowDown']; export type DoubleLinkMenuProps = { editor: Virgo; @@ -44,6 +44,7 @@ export const DoubleLinkMenu = ({ hooks, style, }: DoubleLinkMenuProps) => { + const { page_id: curPageId } = useParams(); const [isOpen, setIsOpen] = useState(false); const [anchorEl, setAnchorEl] = useState(null); const dialogRef = useRef(); @@ -120,9 +121,12 @@ export const DoubleLinkMenu = ({ useEffect(() => { const text = inAddNewPage ? filterText : searchText; QueryBlocks(editor, text, result => { + if (!inAddNewPage) { + result = result.filter(item => item.id !== curPageId); + } setSearchResultBlocks(result); }); - }, [editor, searchText, filterText, inAddNewPage]); + }, [editor, searchText, filterText, inAddNewPage, curPageId]); const hideMenu = useCallback(() => { setIsOpen(false); @@ -133,23 +137,31 @@ export const DoubleLinkMenu = ({ const searchChange = useCallback( async (event: React.KeyboardEvent) => { - if (ARRAY_KEYS.includes(event.key)) { + if (ARRAY_CODES.includes(event.code)) { return; } + if (event.code === 'Backspace') { + const searchText = + editor.blockHelper.getDoubleLinkSearchSlashText(curBlockId); + if (!searchText || searchText === '[[') { + hideMenu(); + event.preventDefault(); + event.stopPropagation(); + return; + } + } const { type, anchorNode } = editor.selection.currentSelectInfo; if ( - type === 'Range' && - anchorNode && - editor.blockHelper.isSelectionCollapsed(anchorNode.id) + !isOpen || + (type === 'Range' && + anchorNode && + anchorNode.id !== curBlockId && + editor.blockHelper.isSelectionCollapsed(anchorNode.id)) ) { const text = editor.blockHelper.getBlockTextBeforeSelection( anchorNode.id ); if (text.endsWith('[[')) { - if (event.key === 'Backspace') { - hideMenu(); - return; - } editor.blockHelper.removeDoubleLinkSearchSlash(curBlockId); setCurBlockId(anchorNode.id); setSearchText(''); @@ -211,26 +223,18 @@ export const DoubleLinkMenu = ({ if (event.code === 'Escape') { hideMenu(); } - const { type, anchorNode } = editor.selection.currentSelectInfo; - if ( - type === 'Range' && - anchorNode && - editor.blockHelper.isSelectionCollapsed(anchorNode.id) - ) { - const text = editor.blockHelper.getBlockTextBeforeSelection( - anchorNode.id - ); - if (text.endsWith('[[')) { - if (event.key === 'Backspace') { - event.preventDefault(); - event.stopPropagation(); - hideMenu(); - return; - } + + if (event.code === 'Backspace') { + const searchText = + editor.blockHelper.getDoubleLinkSearchSlashText(curBlockId); + if (!searchText || searchText === '[[') { + event.preventDefault(); + event.stopPropagation(); + return; } } }, - [hideMenu, editor, isOpen] + [hideMenu, editor, isOpen, curBlockId] ); useEffect(() => { @@ -294,7 +298,7 @@ export const DoubleLinkMenu = ({ return; } if (id === ADD_NEW_SUB_PAGE) { - const pageId = await addSubPage(getPageId()); + const pageId = await addSubPage(curPageId); insertDoubleLink(pageId); return; } From 1820135f3a4603ec11b4d89919b1de46b6595453 Mon Sep 17 00:00:00 2001 From: xiaodong zuo Date: Fri, 19 Aug 2022 10:27:26 +0800 Subject: [PATCH 20/58] feat: Intra-line double link interaction --- libs/components/common/src/lib/index.ts | 47 +++++++++---------- .../src/lib/text/plugins/DoubleLink.tsx | 9 ++++ 2 files changed, 32 insertions(+), 24 deletions(-) diff --git a/libs/components/common/src/lib/index.ts b/libs/components/common/src/lib/index.ts index 9a1eea5191..f42927223e 100644 --- a/libs/components/common/src/lib/index.ts +++ b/libs/components/common/src/lib/index.ts @@ -1,5 +1,6 @@ import { BaseEditor } from 'slate'; import { ReactEditor } from 'slate-react'; +import { DoubleLinkElement } from './text/plugins/DoubleLink'; import { LinkElement } from './text/plugins/link'; import { RefLinkElement } from './text/plugins/reflink'; @@ -8,7 +9,8 @@ export type CustomElement = | { type: string; children: CustomElement[] } | CustomText | LinkElement - | RefLinkElement; + | RefLinkElement + | DoubleLinkElement; declare module 'slate' { interface CustomTypes { Editor: BaseEditor & ReactEditor; @@ -19,35 +21,32 @@ declare module 'slate' { export { BlockPreview, StyledBlockPreview } from './block-preview'; export { default as Button } from './button'; -export type { CommonListItem } from './list'; -export { CommonList, BackLink, commonListContainer } from './list'; -export * from './Logo'; -export { default as Toolbar } from './toolbar'; export { CollapsibleTitle } from './collapsible-title'; - -export * from './text'; - +export * from './comming-soon/CommingSoon'; export { - NewpageIcon, + AddIcon, ClockIcon, - ViewSidebarIcon, + CloseIcon, + CodeBlockInlineIcon, + DocumentIcon, + FilterIcon, + FullScreenIcon, + HighlighterDuotoneIcon, + KanbanIcon, ListIcon, - SpaceIcon, + NewpageIcon, + PagesIcon, PencilDotDuotoneIcon, PencilDuotoneIcon, - HighlighterDuotoneIcon, - CodeBlockInlineIcon, - PagesIcon, - CloseIcon, - DocumentIcon, - TodoListIcon, - KanbanIcon, - TableIcon, - AddIcon, - FilterIcon, SorterIcon, - FullScreenIcon, + SpaceIcon, + TableIcon, + TodoListIcon, UnGroupIcon, + ViewSidebarIcon, } from './icon'; - -export * from './comming-soon/CommingSoon'; +export { BackLink, CommonList, commonListContainer } from './list'; +export type { CommonListItem } from './list'; +export * from './Logo'; +export * from './text'; +export { default as Toolbar } from './toolbar'; diff --git a/libs/components/common/src/lib/text/plugins/DoubleLink.tsx b/libs/components/common/src/lib/text/plugins/DoubleLink.tsx index 822b684323..3bacd92f5f 100644 --- a/libs/components/common/src/lib/text/plugins/DoubleLink.tsx +++ b/libs/components/common/src/lib/text/plugins/DoubleLink.tsx @@ -1,6 +1,15 @@ import { PagesIcon } from '@toeverything/components/icons'; import React, { useCallback } from 'react'; import { useNavigate } from 'react-router-dom'; +import { Descendant } from 'slate'; + +export type DoubleLinkElement = { + type: 'link'; + workspaceId: string; + blockId: string; + children: Descendant[]; + id: string; +}; export const DoubleLinkComponent = ({ attributes, children, element }: any) => { const navigate = useNavigate(); From 22883de54eff4d135edbb9d7edae1a44b1f7c1d5 Mon Sep 17 00:00:00 2001 From: DiamondThree Date: Fri, 19 Aug 2022 10:49:30 +0800 Subject: [PATCH 21/58] fix:shapaes bidings error --- libs/components/affine-board/src/Board.tsx | 23 +++++++++++-------- .../affine-board/src/hooks/use-shapes.ts | 16 ------------- 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/libs/components/affine-board/src/Board.tsx b/libs/components/affine-board/src/Board.tsx index d6cb1240bd..5150feb919 100644 --- a/libs/components/affine-board/src/Board.tsx +++ b/libs/components/affine-board/src/Board.tsx @@ -64,9 +64,6 @@ const AffineBoard = ({ workspace, rootBlockId }: AffineBoardProps) => { set_app(app); }, async onChangePage(app, shapes, bindings, assets) { - console.log('shapes, bindings: ', shapes, bindings); - // - await Promise.all( Object.entries(shapes).map(async ([id, shape]) => { if (shape === undefined) { @@ -110,7 +107,7 @@ const AffineBoard = ({ workspace, rootBlockId }: AffineBoardProps) => { bindings[bilingKey].toId = block.id; } }); - return services.api.editorBlock.update({ + return await services.api.editorBlock.update({ workspace: shape.workspace, id: block.id, properties: { @@ -122,19 +119,27 @@ const AffineBoard = ({ workspace, rootBlockId }: AffineBoardProps) => { } }) ); - // let pageBindings = services.api.editorBlock.get({workspace: workspace,ids:[rootBlockId]})?[0] - let block = ( + let pageBindingsString = ( await services.api.editorBlock.get({ workspace: workspace, ids: [rootBlockId], }) - )?.[0]; + )?.[0].properties.bindings.value; + let pageBindings = JSON.parse(pageBindingsString ?? '{}'); + Object.keys(bindings).forEach(bindingsKey => { + if (bindings[bindingsKey] === undefined) { + delete pageBindings[bindingsKey]; + } else { + Object.assign(pageBindings, bindings); + } + }); + console.log(pageBindings); services.api.editorBlock.update({ workspace: workspace, - id: block.id, + id: rootBlockId, properties: { bindings: { - value: JSON.stringify(bindings), + value: JSON.stringify(pageBindings), }, }, }); diff --git a/libs/components/affine-board/src/hooks/use-shapes.ts b/libs/components/affine-board/src/hooks/use-shapes.ts index c7f22744ed..5167ed5ccb 100644 --- a/libs/components/affine-board/src/hooks/use-shapes.ts +++ b/libs/components/affine-board/src/hooks/use-shapes.ts @@ -115,19 +115,3 @@ export const useShapes = (workspace: string, rootBlockId: string) => { bindings: JSON.parse(blocks?.bindings ?? '{}'), }; }; - -export const useBindings = (workspace: string, rootBlockId: string) => { - const [bindings, setBindings] = useState(); - useEffect(() => { - services.api.editorBlock - .get({ - workspace: workspace, - ids: [rootBlockId], - }) - .then(blcoks => { - setBindings(blcoks[0].properties.bindings?.value); - }); - return () => {}; - }, [workspace, rootBlockId]); - return bindings ? JSON.parse(bindings) : {}; -}; From 2406f9556fdc5e72127b64d07a5ecf46a4874d78 Mon Sep 17 00:00:00 2001 From: xiaodong zuo Date: Fri, 19 Aug 2022 11:13:15 +0800 Subject: [PATCH 22/58] feat: Intra-line double link interaction --- .../common/src/lib/text/slate-utils.ts | 9 ++- .../src/editor/block/async-block.ts | 28 ++++--- .../menu/double-link-menu/DoubleLinkMenu.tsx | 75 ++++++++++--------- 3 files changed, 57 insertions(+), 55 deletions(-) diff --git a/libs/components/common/src/lib/text/slate-utils.ts b/libs/components/common/src/lib/text/slate-utils.ts index a1cf6f2c95..476883a2c9 100644 --- a/libs/components/common/src/lib/text/slate-utils.ts +++ b/libs/components/common/src/lib/text/slate-utils.ts @@ -597,10 +597,11 @@ class SlateUtils { const fragmentChildren = firstFragment.children; - const textChildren: Text[] = []; - for (const child of fragmentChildren) { - if ((child as any).type === 'link') { - textChildren.push(child as Text); + const textChildren = []; + for (let i = 0; i < fragmentChildren.length; i++) { + const child = fragmentChildren[i]; + if ('type' in child && child.type === 'link') { + i !== fragmentChildren.length - 1 && textChildren.push(child); continue; } if (!('text' in child)) { diff --git a/libs/components/editor-core/src/editor/block/async-block.ts b/libs/components/editor-core/src/editor/block/async-block.ts index 9eb156852e..73db5de087 100644 --- a/libs/components/editor-core/src/editor/block/async-block.ts +++ b/libs/components/editor-core/src/editor/block/async-block.ts @@ -508,21 +508,19 @@ export class AsyncBlock { id: item.blockId, }); - if (linkBlock) { - let children = linkBlock.getProperties().text?.value || []; - if (children.length === 1 && !children[0].text) { - children = [{ text: 'Untitled' }]; - } - if ( - children.map(v => v.text).join('') !== - (item.children || []).map((v: any) => v.text).join('') - ) { - const newItem = { - ...item, - children: children, - }; - values.splice(i, 1, newItem); - } + let children = linkBlock?.getProperties().text?.value || []; + if (children.length === 1 && !children[0].text) { + children = [{ text: 'Untitled' }]; + } + if ( + children.map(v => v.text).join('') !== + (item.children || []).map((v: any) => v.text).join('') + ) { + const newItem = { + ...item, + children: children, + }; + values.splice(i, 1, newItem); } } } diff --git a/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx b/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx index c012010eb1..eae70b40f4 100644 --- a/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx +++ b/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx @@ -135,6 +135,44 @@ export const DoubleLinkMenu = ({ editor.scrollManager.unLock(); }, [curBlockId, editor]); + const resetState = useCallback( + (preNodeId: string, nextNodeId: string) => { + editor.blockHelper.removeDoubleLinkSearchSlash(preNodeId); + setCurBlockId(nextNodeId); + setSearchText(''); + setIsOpen(true); + editor.scrollManager.lock(); + const clientRect = + editor.selection.currentSelectInfo?.browserSelection + ?.getRangeAt(0) + ?.getBoundingClientRect(); + if (clientRect) { + const rectTop = clientRect.top; + const { top, left } = editor.container.getBoundingClientRect(); + setDoubleLinkMenuStyle({ + top: rectTop - top, + left: clientRect.left - left, + height: clientRect.height, + }); + setAnchorEl(dialogRef.current); + } + setTimeout(() => { + const textSelection = editor.blockHelper.selectionToSlateRange( + nextNodeId, + editor.selection.currentSelectInfo.browserSelection + ); + if (textSelection) { + const { anchor } = textSelection; + editor.blockHelper.setDoubleLinkSearchSlash( + nextNodeId, + anchor + ); + } + }); + }, + [editor] + ); + const searchChange = useCallback( async (event: React.KeyboardEvent) => { if (ARRAY_CODES.includes(event.code)) { @@ -162,41 +200,7 @@ export const DoubleLinkMenu = ({ anchorNode.id ); if (text.endsWith('[[')) { - editor.blockHelper.removeDoubleLinkSearchSlash(curBlockId); - setCurBlockId(anchorNode.id); - setSearchText(''); - setIsOpen(true); - editor.scrollManager.lock(); - const clientRect = - editor.selection.currentSelectInfo?.browserSelection - ?.getRangeAt(0) - ?.getBoundingClientRect(); - if (clientRect) { - const rectTop = clientRect.top; - const { top, left } = - editor.container.getBoundingClientRect(); - setDoubleLinkMenuStyle({ - top: rectTop - top, - left: clientRect.left - left, - height: clientRect.height, - }); - setAnchorEl(dialogRef.current); - } - setTimeout(() => { - const textSelection = - editor.blockHelper.selectionToSlateRange( - anchorNode.id, - editor.selection.currentSelectInfo - .browserSelection - ); - if (textSelection) { - const { anchor } = textSelection; - editor.blockHelper.setDoubleLinkSearchSlash( - anchorNode.id, - anchor - ); - } - }); + resetState(curBlockId, anchorNode.id); } } if (isOpen) { @@ -372,7 +376,6 @@ export const DoubleLinkMenu = ({
); }; - const NewPageSearchContainer = styled('div')({ padding: '8px 8px 0px 8px', }); From 9411422faf5596579600c1daa9f4df5c7e20f412 Mon Sep 17 00:00:00 2001 From: xiaodong zuo Date: Fri, 19 Aug 2022 11:41:53 +0800 Subject: [PATCH 23/58] feat: Intra-line double link interaction --- .../src/menu/double-link-menu/Container.tsx | 47 ++++++++----------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx b/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx index dd62fd1def..d7bcfa9e19 100644 --- a/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx +++ b/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx @@ -19,14 +19,10 @@ export type DoubleLinkMenuContainerProps = { items?: CommonListItem[]; }; -export const DoubleLinkMenuContainer = ({ - hooks, - onSelected, - onClose, - types, - style, - items, -}: DoubleLinkMenuContainerProps) => { +export const DoubleLinkMenuContainer = ( + props: DoubleLinkMenuContainerProps +) => { + const { hooks, onSelected, onClose, types, style, items } = props; const menuRef = useRef(null); const [currentItem, setCurrentItem] = useState(); const [needCheckIntoView, setNeedCheckIntoView] = useState(false); @@ -79,42 +75,37 @@ export const DoubleLinkMenuContainer = ({ } }, [types, currentItem]); - const handleClickUp = useCallback( + const handleUpDownKey = useCallback( (event: React.KeyboardEvent) => { - if (types && event.code === 'ArrowUp') { + if (types && ['ArrowUp', 'ArrowDown'].includes(event.code)) { event.preventDefault(); + const isUpkey = event.code === 'ArrowUp'; if (!currentItem && types.length) { - setCurrentItem(types[types.length - 1]); + setCurrentItem(types[isUpkey ? types.length - 1 : 0]); } if (currentItem) { const idx = types.indexOf(currentItem); - if (idx > 0) { + if (isUpkey ? idx > 0 : idx < types.length - 1) { setNeedCheckIntoView(true); - setCurrentItem(types[idx - 1]); + setCurrentItem(types[isUpkey ? idx - 1 : idx + 1]); } } } }, - [types, currentItem] + [currentItem, types] + ); + const handleClickUp = useCallback( + (event: React.KeyboardEvent) => { + handleUpDownKey(event); + }, + [handleUpDownKey] ); const handleClickDown = useCallback( (event: React.KeyboardEvent) => { - if (types && event.code === 'ArrowDown') { - event.preventDefault(); - if (!currentItem && types.length) { - setCurrentItem(types[0]); - } - if (currentItem) { - const idx = types.indexOf(currentItem); - if (idx < types.length - 1) { - setNeedCheckIntoView(true); - setCurrentItem(types[idx + 1]); - } - } - } + handleUpDownKey(event); }, - [types, currentItem] + [handleUpDownKey] ); const handleClickEnter = useCallback( From c67d961d662cf99e9bf798dbc62cf02a69f04b8b Mon Sep 17 00:00:00 2001 From: xiaodong zuo Date: Fri, 19 Aug 2022 11:56:57 +0800 Subject: [PATCH 24/58] feat: Intra-line double link interaction --- .../src/menu/double-link-menu/Container.tsx | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx b/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx index d7bcfa9e19..7294a909b7 100644 --- a/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx +++ b/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx @@ -30,23 +30,22 @@ export const DoubleLinkMenuContainer = ( useEffect(() => { if (needCheckIntoView) { if (currentItem && menuRef.current) { - const itemEle = + const itemElement = menuRef.current.querySelector( `.item-${currentItem}` ); - const scrollEle = + const scrollElement = menuRef.current.querySelector( `.${commonListContainer}` ); - if (itemEle) { - const itemRect = domToRect(itemEle); - const scrollRect = domToRect(scrollEle); + if (itemElement) { + const itemRect = domToRect(itemElement); + const scrollRect = domToRect(scrollElement); if ( itemRect.top < scrollRect.top || itemRect.bottom > scrollRect.bottom ) { - // IMP: may be do it with self function - itemEle.scrollIntoView({ + itemElement.scrollIntoView({ block: 'nearest', }); } @@ -80,12 +79,16 @@ export const DoubleLinkMenuContainer = ( if (types && ['ArrowUp', 'ArrowDown'].includes(event.code)) { event.preventDefault(); const isUpkey = event.code === 'ArrowUp'; + const indexBound = isUpkey ? types.length - 1 : 0; if (!currentItem && types.length) { - setCurrentItem(types[isUpkey ? types.length - 1 : 0]); + setCurrentItem(types[indexBound]); } if (currentItem) { const idx = types.indexOf(currentItem); - if (isUpkey ? idx > 0 : idx < types.length - 1) { + const needChange = isUpkey + ? idx > indexBound + : idx < indexBound; + if (needChange) { setNeedCheckIntoView(true); setCurrentItem(types[isUpkey ? idx - 1 : idx + 1]); } From 33d8b551d4cb1ed8bb1c843c23ac9b4aae846c6d Mon Sep 17 00:00:00 2001 From: xiaodong zuo Date: Fri, 19 Aug 2022 12:06:50 +0800 Subject: [PATCH 25/58] feat: Intra-line double link interaction --- .../src/menu/double-link-menu/Container.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx b/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx index 7294a909b7..147f154129 100644 --- a/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx +++ b/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx @@ -79,16 +79,12 @@ export const DoubleLinkMenuContainer = ( if (types && ['ArrowUp', 'ArrowDown'].includes(event.code)) { event.preventDefault(); const isUpkey = event.code === 'ArrowUp'; - const indexBound = isUpkey ? types.length - 1 : 0; if (!currentItem && types.length) { - setCurrentItem(types[indexBound]); + setCurrentItem(types[isUpkey ? types.length - 1 : 0]); } if (currentItem) { const idx = types.indexOf(currentItem); - const needChange = isUpkey - ? idx > indexBound - : idx < indexBound; - if (needChange) { + if (isUpkey ? idx > 0 : idx < types.length - 1) { setNeedCheckIntoView(true); setCurrentItem(types[isUpkey ? idx - 1 : idx + 1]); } From 60059ea00a1d6f6323d7514da4fab72d07962dc0 Mon Sep 17 00:00:00 2001 From: Wang Yu Date: Fri, 19 Aug 2022 14:17:46 +0800 Subject: [PATCH 26/58] fix: remove unused executor svgOptimize (#296) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: ็Ž‹ๆ˜ฑ --- tools/executors/svgOptimize/executor.json | 9 -- tools/executors/svgOptimize/package.json | 3 - tools/executors/svgOptimize/schema.json | 11 -- tools/executors/svgOptimize/svgo.js | 133 ---------------------- 4 files changed, 156 deletions(-) delete mode 100644 tools/executors/svgOptimize/executor.json delete mode 100644 tools/executors/svgOptimize/package.json delete mode 100644 tools/executors/svgOptimize/schema.json delete mode 100644 tools/executors/svgOptimize/svgo.js diff --git a/tools/executors/svgOptimize/executor.json b/tools/executors/svgOptimize/executor.json deleted file mode 100644 index 1c19a2f9c5..0000000000 --- a/tools/executors/svgOptimize/executor.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "executors": { - "svgOptimize": { - "implementation": "./svgo.js", - "schema": "./schema.json", - "description": "Run `svgo` (to optimize svg)." - } - } -} diff --git a/tools/executors/svgOptimize/package.json b/tools/executors/svgOptimize/package.json deleted file mode 100644 index 721ff1df5d..0000000000 --- a/tools/executors/svgOptimize/package.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "executors": "./executor.json" -} diff --git a/tools/executors/svgOptimize/schema.json b/tools/executors/svgOptimize/schema.json deleted file mode 100644 index dc2fdc029b..0000000000 --- a/tools/executors/svgOptimize/schema.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "http://json-schema.org/schema", - "type": "object", - "cli": "nx", - "properties": { - "svgOptimize": { - "type": "string", - "description": "optimize svg" - } - } -} diff --git a/tools/executors/svgOptimize/svgo.js b/tools/executors/svgOptimize/svgo.js deleted file mode 100644 index a0f6c21539..0000000000 --- a/tools/executors/svgOptimize/svgo.js +++ /dev/null @@ -1,133 +0,0 @@ -const path = require('path'); -const svgo = require('svgo'); -const { readdir, readFile, writeFile, exists } = require('fs/promises'); -const { pascalCase, paramCase } = require('change-case'); -const svgr = require('@svgr/core'); - -async function optimizeSvg(folder) { - try { - const icons = await readdir(folder); - const generateIcons = icons - .filter(n => n.endsWith('.svg')) - .map(async icon => { - let originSvg; - try { - originSvg = await readFile(path.resolve(folder, icon)); - } catch (err) { - console.error(err); - } - let optimizedSvg; - try { - const data = optimize(originSvg); - optimizedSvg = data.data; - } catch (err) { - console.error(err); - } - - const JSXContent = await getJSXContent( - pascalCase(icon), - optimizedSvg - ); - - const iconName = path.basename(icon, '.svg'); - await writeFile( - path.resolve(folder, `${iconName}.tsx`), - JSXContent, - { encoding: 'utf8', flag: '' } - ); - - console.log('Generated:', iconName); - }); - - await Promise.allSettled([ - ...generateIcons, - generateImportEntry(icons, folder), - ]); - } catch (err) { - console.error(err); - } -} - -function optimize(input) { - return svgo.optimize(input, { - plugins: [ - 'preset-default', - 'prefixIds', - { - name: 'sortAttrs', - params: { - xmlnsOrder: 'alphabetical', - }, - }, - ], - }); -} - -/** - * get icon component template - * - * @param {string} name - */ -async function getJSXContent(name, svgCode) { - let svgrContent = ''; - try { - svgrContent = await svgr.transform( - svgCode, - { - icon: true, - typescript: true, - }, - { componentName: `${name}Icon1` } - ); - } catch (err) { - console.error(err); - } - let matcher = svgrContent.match(/]+)>([\s\S]*?)<\/svg>/); - return ` -import { SvgIcon, SvgIconProps } from '@mui/material'; -export const ${name}Icon = (props: SvgIconProps) => ( - - ${matcher[2]} - -); -`; -} - -async function generateImportEntry(iconNodes, folder) { - const fileWithImportsPath = path.resolve(folder, 'index.ts'); - - const importsContent = iconNodes - .map(iconNode => { - const iconName = paramCase(iconNode.name); - if (!iconName) { - return `// Error: ${iconNode.name}`; - } - - return `export * from './${iconName}/${iconName}';`; - }) - .join('\n'); - - await fs.writeFile( - fileWithImportsPath, - `export const timestamp = ${Date.now()};\n${importsContent}`, - { encoding: 'utf8' } - ); -} - -/** - * @param {*} options - * @param {array} options.assets - * @param {string} options.assets.folder - * @param {*} context - * @returns - */ -exports['default'] = async function svgo(options, context) { - const libRoot = context.workspace.projects[context.projectName].root; - await Promise.allSettled( - (options.assets || []).map(async (asset, index) => { - await optimizeSvg(path.resolve(libRoot, asset.folder)); - }) - ); - - return { success: true }; -}; From 2eaf26c40f59f6651db8819055b7af1ca0c0a251 Mon Sep 17 00:00:00 2001 From: DiamondThree Date: Fri, 19 Aug 2022 16:37:04 +0800 Subject: [PATCH 27/58] fix:shapaes --- libs/components/affine-board/src/Board.tsx | 5 +- .../affine-board/src/hooks/use-shapes.ts | 50 ++++++++----------- 2 files changed, 23 insertions(+), 32 deletions(-) diff --git a/libs/components/affine-board/src/Board.tsx b/libs/components/affine-board/src/Board.tsx index 5150feb919..db969d29da 100644 --- a/libs/components/affine-board/src/Board.tsx +++ b/libs/components/affine-board/src/Board.tsx @@ -45,8 +45,6 @@ const AffineBoard = ({ workspace, rootBlockId }: AffineBoardProps) => { }); const { shapes, bindings } = useShapes(workspace, rootBlockId); - - // const bindings = useBindings(workspace, rootBlockId); useEffect(() => { if (app) { app.replacePageContent(shapes || {}, bindings, {}); @@ -124,7 +122,7 @@ const AffineBoard = ({ workspace, rootBlockId }: AffineBoardProps) => { workspace: workspace, ids: [rootBlockId], }) - )?.[0].properties.bindings.value; + )?.[0].properties.bindings?.value; let pageBindings = JSON.parse(pageBindingsString ?? '{}'); Object.keys(bindings).forEach(bindingsKey => { if (bindings[bindingsKey] === undefined) { @@ -133,7 +131,6 @@ const AffineBoard = ({ workspace, rootBlockId }: AffineBoardProps) => { Object.assign(pageBindings, bindings); } }); - console.log(pageBindings); services.api.editorBlock.update({ workspace: workspace, id: rootBlockId, diff --git a/libs/components/affine-board/src/hooks/use-shapes.ts b/libs/components/affine-board/src/hooks/use-shapes.ts index 5167ed5ccb..beb8c50efa 100644 --- a/libs/components/affine-board/src/hooks/use-shapes.ts +++ b/libs/components/affine-board/src/hooks/use-shapes.ts @@ -5,6 +5,17 @@ import { services } from '@toeverything/datasource/db-service'; import { usePageClientWidth } from '@toeverything/datasource/state'; import { useEffect, useState } from 'react'; +const getBindings = (workspace: string, rootBlockId: string) => { + return services.api.editorBlock + .get({ + workspace: workspace, + ids: [rootBlockId], + }) + .then(blcoks => { + return blcoks[0].properties.bindings?.value; + }); +}; + export const useShapes = (workspace: string, rootBlockId: string) => { const { pageClientWidth } = usePageClientWidth(); // page padding left and right total 300px @@ -30,28 +41,20 @@ export const useShapes = (workspace: string, rootBlockId: string) => { }) ); return shapes; - // setBlocks(shapes); }), ]).then(shapes => { - console.log(shapes); - services.api.editorBlock - .get({ - workspace: workspace, - ids: [rootBlockId], - }) - .then(blcoks => { - setBlocks({ - shapes, - bindings: blcoks[0].properties.bindings?.value, - }); - // setBindings(blcoks[0].properties.bindings?.value); + getBindings(workspace, rootBlockId).then(bindings => { + setBlocks({ + shapes, + bindings: bindings, }); + }); }); let unobserve: () => void; services.api.editorBlock .observe({ workspace, id: rootBlockId }, async blockData => { - const shapes = await Promise.all( + Promise.all( (blockData?.children || []).map(async childId => { const childBlock = ( await services.api.editorBlock.get({ @@ -62,22 +65,13 @@ export const useShapes = (workspace: string, rootBlockId: string) => { return childBlock; }) ).then(shapes => { - console.log(shapes); - services.api.editorBlock - .get({ - workspace: workspace, - ids: [rootBlockId], - }) - .then(blcoks => { - setBlocks({ - shapes: [shapes], - bindings: blcoks[0].properties.bindings?.value, - }); - // setBindings(blcoks[0].properties.bindings?.value); + getBindings(workspace, rootBlockId).then(bindings => { + setBlocks({ + shapes: [shapes], + bindings: bindings, }); + }); }); - return shapes; - // setBlocks(shapes); }) .then(cb => { unobserve = cb; From 3570aab4e807e3ff895ed19c96026bc2e080c8bb Mon Sep 17 00:00:00 2001 From: xiaodong zuo Date: Fri, 19 Aug 2022 18:22:57 +0800 Subject: [PATCH 28/58] feat: Intra-line double link interaction --- .../src/lib/text/plugins/DoubleLink.tsx | 13 ++--- .../src/editor/block/async-block.ts | 1 - .../src/menu/double-link-menu/Container.tsx | 50 +------------------ .../menu/double-link-menu/DoubleLinkMenu.tsx | 21 +++----- 4 files changed, 16 insertions(+), 69 deletions(-) diff --git a/libs/components/common/src/lib/text/plugins/DoubleLink.tsx b/libs/components/common/src/lib/text/plugins/DoubleLink.tsx index 3bacd92f5f..e4bcb9bec2 100644 --- a/libs/components/common/src/lib/text/plugins/DoubleLink.tsx +++ b/libs/components/common/src/lib/text/plugins/DoubleLink.tsx @@ -2,6 +2,7 @@ import { PagesIcon } from '@toeverything/components/icons'; import React, { useCallback } from 'react'; import { useNavigate } from 'react-router-dom'; import { Descendant } from 'slate'; +import { RenderElementProps } from 'slate-react'; export type DoubleLinkElement = { type: 'link'; @@ -11,17 +12,17 @@ export type DoubleLinkElement = { id: string; }; -export const DoubleLinkComponent = ({ attributes, children, element }: any) => { +export const DoubleLinkComponent = (props: RenderElementProps) => { + const { attributes, children, element } = props; + const doubleLinkElement = element as DoubleLinkElement; const navigate = useNavigate(); const handleClickLinkText = useCallback( (event: React.MouseEvent) => { - event.preventDefault(); - event.stopPropagation(); - const { workspaceId, blockId } = element; + const { workspaceId, blockId } = doubleLinkElement; navigate(`/${workspaceId}/${blockId}`); }, - [element, navigate] + [doubleLinkElement, navigate] ); return ( @@ -30,7 +31,7 @@ export const DoubleLinkComponent = ({ attributes, children, element }: any) => { {children} diff --git a/libs/components/editor-core/src/editor/block/async-block.ts b/libs/components/editor-core/src/editor/block/async-block.ts index 73db5de087..52dbae6ec8 100644 --- a/libs/components/editor-core/src/editor/block/async-block.ts +++ b/libs/components/editor-core/src/editor/block/async-block.ts @@ -162,7 +162,6 @@ export class AsyncBlock { const oldData = this.raw_data; this.raw_data = blockData; this.raw_data = await this.filterPageInvalidChildren(blockData); - this.raw_data = await this.updateDoubleLinkBlock(this.raw_data); this.emit('update', { block: this, oldData }); } ); diff --git a/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx b/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx index 147f154129..ec5f52be08 100644 --- a/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx +++ b/libs/components/editor-plugins/src/menu/double-link-menu/Container.tsx @@ -1,11 +1,6 @@ -import { - CommonList, - commonListContainer, - CommonListItem, -} from '@toeverything/components/common'; +import { CommonList, CommonListItem } from '@toeverything/components/common'; import { styled } from '@toeverything/components/ui'; import { HookType, PluginHooks, Virgo } from '@toeverything/framework/virgo'; -import { domToRect } from '@toeverything/utils'; import React, { useCallback, useEffect, useRef, useState } from 'react'; export type DoubleLinkMenuContainerProps = { @@ -25,35 +20,6 @@ export const DoubleLinkMenuContainer = ( const { hooks, onSelected, onClose, types, style, items } = props; const menuRef = useRef(null); const [currentItem, setCurrentItem] = useState(); - const [needCheckIntoView, setNeedCheckIntoView] = useState(false); - - useEffect(() => { - if (needCheckIntoView) { - if (currentItem && menuRef.current) { - const itemElement = - menuRef.current.querySelector( - `.item-${currentItem}` - ); - const scrollElement = - menuRef.current.querySelector( - `.${commonListContainer}` - ); - if (itemElement) { - const itemRect = domToRect(itemElement); - const scrollRect = domToRect(scrollElement); - if ( - itemRect.top < scrollRect.top || - itemRect.bottom > scrollRect.bottom - ) { - itemElement.scrollIntoView({ - block: 'nearest', - }); - } - } - } - setNeedCheckIntoView(false); - } - }, [needCheckIntoView, currentItem]); useEffect(() => { if (types && !currentItem) { @@ -61,19 +27,6 @@ export const DoubleLinkMenuContainer = ( } }, [currentItem, onClose, types]); - useEffect(() => { - if (types) { - if (!types.includes(currentItem)) { - setNeedCheckIntoView(true); - if (types.length) { - setCurrentItem(types[0]); - } else { - setCurrentItem(undefined); - } - } - } - }, [types, currentItem]); - const handleUpDownKey = useCallback( (event: React.KeyboardEvent) => { if (types && ['ArrowUp', 'ArrowDown'].includes(event.code)) { @@ -85,7 +38,6 @@ export const DoubleLinkMenuContainer = ( if (currentItem) { const idx = types.indexOf(currentItem); if (isUpkey ? idx > 0 : idx < types.length - 1) { - setNeedCheckIntoView(true); setCurrentItem(types[isUpkey ? idx - 1 : idx + 1]); } } diff --git a/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx b/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx index eae70b40f4..a81e8b3122 100644 --- a/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx +++ b/libs/components/editor-plugins/src/menu/double-link-menu/DoubleLinkMenu.tsx @@ -156,19 +156,14 @@ export const DoubleLinkMenu = ({ }); setAnchorEl(dialogRef.current); } - setTimeout(() => { - const textSelection = editor.blockHelper.selectionToSlateRange( - nextNodeId, - editor.selection.currentSelectInfo.browserSelection - ); - if (textSelection) { - const { anchor } = textSelection; - editor.blockHelper.setDoubleLinkSearchSlash( - nextNodeId, - anchor - ); - } - }); + const textSelection = editor.blockHelper.selectionToSlateRange( + nextNodeId, + editor.selection.currentSelectInfo?.browserSelection + ); + if (textSelection) { + const { anchor } = textSelection; + editor.blockHelper.setDoubleLinkSearchSlash(nextNodeId, anchor); + } }, [editor] ); From 6bc78b35ec2a8e6a9729c71ea64e9e86f8091880 Mon Sep 17 00:00:00 2001 From: xiaodong zuo Date: Fri, 19 Aug 2022 18:30:52 +0800 Subject: [PATCH 29/58] feat: Intra-line double link interaction --- libs/components/editor-core/src/editor/block/async-block.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/components/editor-core/src/editor/block/async-block.ts b/libs/components/editor-core/src/editor/block/async-block.ts index 52dbae6ec8..73db5de087 100644 --- a/libs/components/editor-core/src/editor/block/async-block.ts +++ b/libs/components/editor-core/src/editor/block/async-block.ts @@ -162,6 +162,7 @@ export class AsyncBlock { const oldData = this.raw_data; this.raw_data = blockData; this.raw_data = await this.filterPageInvalidChildren(blockData); + this.raw_data = await this.updateDoubleLinkBlock(this.raw_data); this.emit('update', { block: this, oldData }); } ); From b53581aae5dae96f371e53d7b330f0dea4db5d4b Mon Sep 17 00:00:00 2001 From: xiaodong zuo Date: Fri, 19 Aug 2022 18:42:46 +0800 Subject: [PATCH 30/58] feat: Intra-line double link interaction --- libs/components/common/src/lib/text/slate-utils.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libs/components/common/src/lib/text/slate-utils.ts b/libs/components/common/src/lib/text/slate-utils.ts index 476883a2c9..fd1de5f674 100644 --- a/libs/components/common/src/lib/text/slate-utils.ts +++ b/libs/components/common/src/lib/text/slate-utils.ts @@ -11,6 +11,7 @@ import { Transforms, } from 'slate'; import { ReactEditor } from 'slate-react'; +import type { CustomElement } from '..'; import { fontBgColorPalette, fontColorPalette, @@ -597,7 +598,7 @@ class SlateUtils { const fragmentChildren = firstFragment.children; - const textChildren = []; + const textChildren: CustomElement[] = []; for (let i = 0; i < fragmentChildren.length; i++) { const child = fragmentChildren[i]; if ('type' in child && child.type === 'link') { From 01339fc77d0272b110116d901a3fa77a271532c9 Mon Sep 17 00:00:00 2001 From: Whitewater Date: Fri, 19 Aug 2022 18:44:26 +0800 Subject: [PATCH 31/58] docs: update contributors (#300) --- .all-contributorsrc | 37 +++++++++++++++++++++++++++++++++++++ README.md | 8 +++++++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 01e5d122de..8993984505 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -266,6 +266,43 @@ "contributions": [ "doc" ] + }, + { + "login": "LuciNyan", + "name": "ๅญ็žป Luci", + "avatar_url": "https://avatars.githubusercontent.com/u/22126563?v=4", + "profile": "https://github.com/LuciNyan", + "contributions": [ + "code" + ] + }, + { + "login": "m1911star", + "name": "Horus", + "avatar_url": "https://avatars.githubusercontent.com/u/4948120?v=4", + "profile": "http://blog.ipili.me/", + "contributions": [ + "code", + "platform" + ] + }, + { + "login": "fanshyiis", + "name": "Super.x", + "avatar_url": "https://avatars.githubusercontent.com/u/15103283?v=4", + "profile": "https://segmentfault.com/u/qzuser_584786517d31a", + "contributions": [ + "code" + ] + }, + { + "login": "wangyu-1999", + "name": "Wang Yu", + "avatar_url": "https://avatars.githubusercontent.com/u/80874770?v=4", + "profile": "https://wangyu-1999.github.io/", + "contributions": [ + "code" + ] } ] } diff --git a/README.md b/README.md index 5352732aa9..e0ce3c8b45 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ See https://github.com/all-?/all-contributors/issues/361#issuecomment-637166066 --> -[all-contributors-badge]: https://img.shields.io/badge/all_contributors-27-orange.svg?style=flat-square +[all-contributors-badge]: https://img.shields.io/badge/all_contributors-31-orange.svg?style=flat-square @@ -228,6 +228,12 @@ For help, discussion about best practices, or any other conversation that would
Simon Li

๐Ÿ’ป
Bob Hu

๐Ÿ’ป
Quavo

๐Ÿ“– +
ๅญ็žป Luci

๐Ÿ’ป + + +
Horus

๐Ÿ’ป ๐Ÿ“ฆ +
Super.x

๐Ÿ’ป +
Wang Yu

๐Ÿ’ป From 27a35ea6a2a5c4ee60eb5910f60d3f71aea51733 Mon Sep 17 00:00:00 2001 From: DiamondThree Date: Fri, 19 Aug 2022 20:06:44 +0800 Subject: [PATCH 32/58] feat add jump shapes --- libs/components/affine-board/src/Board.tsx | 9 ++- .../src/components/command-panel/ArrowTo.tsx | 78 +++++++++++++++++++ .../components/command-panel/CommandPanel.tsx | 7 ++ .../command-panel/FontSizeConfig.tsx | 4 +- libs/components/board-state/src/tldraw-app.ts | 11 ++- 5 files changed, 97 insertions(+), 12 deletions(-) create mode 100644 libs/components/board-draw/src/components/command-panel/ArrowTo.tsx diff --git a/libs/components/affine-board/src/Board.tsx b/libs/components/affine-board/src/Board.tsx index 497720d2bd..af9e8982fe 100644 --- a/libs/components/affine-board/src/Board.tsx +++ b/libs/components/affine-board/src/Board.tsx @@ -109,10 +109,8 @@ const AffineBoard = ({ }); } shape.affineId = block.id; + Object.keys(bindings).forEach(bilingKey => { - if (!bindings[bilingKey]) { - delete bindings[bilingKey]; - } if ( bindings[bilingKey]?.fromId === shape.id ) { @@ -142,9 +140,12 @@ const AffineBoard = ({ ids: [rootBlockId], }) )?.[0].properties.bindings?.value; + console.log(123123123); let pageBindings = JSON.parse(pageBindingsString ?? '{}'); + console.log(pageBindings, 3333, bindings); Object.keys(bindings).forEach(bindingsKey => { - if (bindings[bindingsKey] === undefined) { + console.log(345345345345345); + if (!bindings[bindingsKey]) { delete pageBindings[bindingsKey]; } else { Object.assign(pageBindings, bindings); diff --git a/libs/components/board-draw/src/components/command-panel/ArrowTo.tsx b/libs/components/board-draw/src/components/command-panel/ArrowTo.tsx new file mode 100644 index 0000000000..21f37a9fbc --- /dev/null +++ b/libs/components/board-draw/src/components/command-panel/ArrowTo.tsx @@ -0,0 +1,78 @@ +import type { TldrawApp } from '@toeverything/components/board-state'; +import type { + ArrowBinding, + TDShape, +} from '@toeverything/components/board-types'; +import { ConnectorIcon } from '@toeverything/components/icons'; +import { IconButton, Popover, Tooltip } from '@toeverything/components/ui'; +import { useEffect, useState } from 'react'; +import { ListItemContainer, ListItemTitle } from './FontSizeConfig'; + +interface GroupAndUnGroupProps { + app: TldrawApp; + shapes: TDShape[]; +} + +export const ArrowTo = ({ app, shapes }: GroupAndUnGroupProps) => { + const [arrowToArr, setarrowToArr] = useState([]); + useEffect(() => { + let allShape = app.shapes; + let bindings = app.page.bindings; + let activeShape = shapes[0]; + let toNextShapBindings: ArrowBinding[] = []; + let bindingId = ''; + Object.keys(bindings).forEach(key => { + if (bindings[key].toId === activeShape.id) { + bindingId = bindings[key].fromId; + } + }); + Object.keys(bindings).forEach(key => { + if (bindings[key].fromId === bindingId) { + toNextShapBindings.push(bindings[key]); + } + }); + let ArrowToArr: TDShape[] = []; + toNextShapBindings.forEach(binding => { + if (binding.toId !== activeShape.id) { + allShape.forEach(item => { + console.log(item); + if (item.id === binding.toId) { + ArrowToArr.push(item); + } + }); + } + }); + setarrowToArr(ArrowToArr); + return () => {}; + }, [app.page.bindings, app.shapes]); + const jumpToNextShap = (shape: TDShape) => { + app.zoomToShapes([shape]); + }; + + return ( + + {arrowToArr.map((arrow: any) => { + return ( + jumpToNextShap(arrow)} + > + {arrow.name} + + ); + })} + + } + > + + + + + + + ); +}; diff --git a/libs/components/board-draw/src/components/command-panel/CommandPanel.tsx b/libs/components/board-draw/src/components/command-panel/CommandPanel.tsx index c07bfa88b4..94e28bdc2f 100644 --- a/libs/components/board-draw/src/components/command-panel/CommandPanel.tsx +++ b/libs/components/board-draw/src/components/command-panel/CommandPanel.tsx @@ -2,6 +2,7 @@ import { TLDR, TldrawApp } from '@toeverything/components/board-state'; import { Divider, Popover, styled } from '@toeverything/components/ui'; import { Fragment } from 'react'; import { AlignOperation } from './AlignOperation'; +import { ArrowTo } from './ArrowTo'; import { BorderColorConfig } from './BorderColorConfig'; import { DeleteShapes } from './DeleteOperation'; import { FillColorConfig } from './FillColorConfig'; @@ -106,6 +107,12 @@ export const CommandPanel = ({ app }: { app: TldrawApp }) => { shapes={config.deleteShapes.selectedShapes} > ) : null, + toNextShap: ( + + ), }; const nodes = Object.entries(configNodes).filter(([key, node]) => !!node); diff --git a/libs/components/board-draw/src/components/command-panel/FontSizeConfig.tsx b/libs/components/board-draw/src/components/command-panel/FontSizeConfig.tsx index c35226911c..38fbbfae22 100644 --- a/libs/components/board-draw/src/components/command-panel/FontSizeConfig.tsx +++ b/libs/components/board-draw/src/components/command-panel/FontSizeConfig.tsx @@ -86,7 +86,7 @@ export const FontSizeConfig = ({ app, shapes }: FontSizeConfigProps) => { ); }; -const ListItemContainer = styled('div')(({ theme }) => ({ +export const ListItemContainer = styled('div')(({ theme }) => ({ display: 'flex', alignItems: 'center', cursor: 'pointer', @@ -100,7 +100,7 @@ const ListItemContainer = styled('div')(({ theme }) => ({ }, })); -const ListItemTitle = styled('span')(({ theme }) => ({ +export const ListItemTitle = styled('span')(({ theme }) => ({ marginLeft: '12px', color: theme.affine.palette.primaryText, })); diff --git a/libs/components/board-state/src/tldraw-app.ts b/libs/components/board-state/src/tldraw-app.ts index 49c352c2e9..34a392db72 100644 --- a/libs/components/board-state/src/tldraw-app.ts +++ b/libs/components/board-state/src/tldraw-app.ts @@ -15,13 +15,13 @@ import { TLPointerEventHandler, TLShapeCloneHandler, TLWheelEventHandler, - Utils + Utils, } from '@tldraw/core'; import { Vec } from '@tldraw/vec'; import { clearPrevSize, defaultStyle, - shapeUtils + shapeUtils, } from '@toeverything/components/board-shapes'; import { AlignType, @@ -54,7 +54,7 @@ import { TDUser, TldrawCommand, USER_COLORS, - VIDEO_EXTENSIONS + VIDEO_EXTENSIONS, } from '@toeverything/components/board-types'; import { MIN_PAGE_WIDTH } from '@toeverything/components/editor-core'; import { @@ -67,7 +67,7 @@ import { migrate, openAssetFromFileSystem, openFromFileSystem, - saveToFileSystem + saveToFileSystem, } from './data'; import { getClipboard, setClipboard } from './idb-clipboard'; import { StateManager } from './manager/state-manager'; @@ -865,9 +865,8 @@ export class TldrawApp extends StateManager { return; } - // We only need to update the binding's "from" shape (an arrow) - + const fromDelta = TLDR.update_arrow_bindings(page, fromShape); visitedShapes.add(fromShape); From e1dece05952a60845413d0fec110853d7d2494f5 Mon Sep 17 00:00:00 2001 From: QiShaoXuan Date: Fri, 19 Aug 2022 20:41:09 +0800 Subject: [PATCH 33/58] refactor: change activatable to editable in BaseVeiw --- .../editor-blocks/src/blocks/code/index.ts | 2 +- .../src/blocks/embed-link/index.ts | 2 +- .../editor-blocks/src/blocks/figma/index.ts | 2 +- .../editor-blocks/src/blocks/file/index.ts | 2 +- .../src/blocks/grid-item/index.ts | 2 +- .../editor-blocks/src/blocks/grid/index.ts | 2 +- .../editor-blocks/src/blocks/group/Group.tsx | 2 +- .../editor-blocks/src/blocks/image/index.ts | 2 +- .../editor-blocks/src/blocks/youtube/index.ts | 2 +- .../src/editor/selection/selection.ts | 24 +++++++++---------- .../editor-core/src/editor/views/base-view.ts | 4 ++-- 11 files changed, 23 insertions(+), 23 deletions(-) diff --git a/libs/components/editor-blocks/src/blocks/code/index.ts b/libs/components/editor-blocks/src/blocks/code/index.ts index 9b089d6db5..ce8d7badfb 100644 --- a/libs/components/editor-blocks/src/blocks/code/index.ts +++ b/libs/components/editor-blocks/src/blocks/code/index.ts @@ -16,7 +16,7 @@ import { ComponentType } from 'react'; export class CodeBlock extends BaseView { type = Protocol.Block.Type.code; public override selectable = true; - public override activatable = false; + public override editable = false; // View = CodeView; View = CodeView; override async onCreate(block: AsyncBlock): Promise { diff --git a/libs/components/editor-blocks/src/blocks/embed-link/index.ts b/libs/components/editor-blocks/src/blocks/embed-link/index.ts index 731ae801d6..947763ee16 100644 --- a/libs/components/editor-blocks/src/blocks/embed-link/index.ts +++ b/libs/components/editor-blocks/src/blocks/embed-link/index.ts @@ -8,7 +8,7 @@ import { EmbedLinkView } from './EmbedLinkView'; export class EmbedLinkBlock extends BaseView { public override selectable = true; - public override activatable = false; + public override editable = false; type = Protocol.Block.Type.embedLink; View = EmbedLinkView; diff --git a/libs/components/editor-blocks/src/blocks/figma/index.ts b/libs/components/editor-blocks/src/blocks/figma/index.ts index 3ed44c9c85..4eb9d6047f 100644 --- a/libs/components/editor-blocks/src/blocks/figma/index.ts +++ b/libs/components/editor-blocks/src/blocks/figma/index.ts @@ -8,7 +8,7 @@ import { FigmaView } from './FigmaView'; export class FigmaBlock extends BaseView { public override selectable = true; - public override activatable = false; + public override editable = false; type = Protocol.Block.Type.figma; View = FigmaView; diff --git a/libs/components/editor-blocks/src/blocks/file/index.ts b/libs/components/editor-blocks/src/blocks/file/index.ts index e55eed7721..e3119e9a16 100644 --- a/libs/components/editor-blocks/src/blocks/file/index.ts +++ b/libs/components/editor-blocks/src/blocks/file/index.ts @@ -12,7 +12,7 @@ import { FileView } from './FileView'; export class FileBlock extends BaseView { public override selectable = true; - public override activatable = false; + public override editable = false; type = Protocol.Block.Type.file; View = FileView; diff --git a/libs/components/editor-blocks/src/blocks/grid-item/index.ts b/libs/components/editor-blocks/src/blocks/grid-item/index.ts index 7f51c47a05..2c6598d18d 100644 --- a/libs/components/editor-blocks/src/blocks/grid-item/index.ts +++ b/libs/components/editor-blocks/src/blocks/grid-item/index.ts @@ -6,7 +6,7 @@ import { GridItemRender } from './GridItemRender'; export class GridItemBlock extends BaseView { public override selectable = false; - public override activatable = false; + public override editable = false; public override allowPendant = false; public override layoutOnly = true; diff --git a/libs/components/editor-blocks/src/blocks/grid/index.ts b/libs/components/editor-blocks/src/blocks/grid/index.ts index 582014376f..a74bb130f9 100644 --- a/libs/components/editor-blocks/src/blocks/grid/index.ts +++ b/libs/components/editor-blocks/src/blocks/grid/index.ts @@ -7,7 +7,7 @@ export { GRID_PROPERTY_KEY, removePercent } from './Grid'; export class GridBlock extends BaseView { public override selectable = false; - public override activatable = false; + public override editable = false; public override allowPendant = false; public override layoutOnly = true; diff --git a/libs/components/editor-blocks/src/blocks/group/Group.tsx b/libs/components/editor-blocks/src/blocks/group/Group.tsx index ac194d7eab..787c537f18 100644 --- a/libs/components/editor-blocks/src/blocks/group/Group.tsx +++ b/libs/components/editor-blocks/src/blocks/group/Group.tsx @@ -9,7 +9,7 @@ import { GroupView } from './GroupView'; export class Group extends BaseView { public override selectable = true; - public override activatable = false; + public override editable = false; public override allowPendant = false; type = Protocol.Block.Type.group; diff --git a/libs/components/editor-blocks/src/blocks/image/index.ts b/libs/components/editor-blocks/src/blocks/image/index.ts index 8f56468b41..e5c33514e2 100644 --- a/libs/components/editor-blocks/src/blocks/image/index.ts +++ b/libs/components/editor-blocks/src/blocks/image/index.ts @@ -8,7 +8,7 @@ import { ImageView } from './ImageView'; export class ImageBlock extends BaseView { public override selectable = true; - public override activatable = false; + public override editable = false; type = Protocol.Block.Type.image; View = ImageView; diff --git a/libs/components/editor-blocks/src/blocks/youtube/index.ts b/libs/components/editor-blocks/src/blocks/youtube/index.ts index 42f22bcda4..f04e241d88 100644 --- a/libs/components/editor-blocks/src/blocks/youtube/index.ts +++ b/libs/components/editor-blocks/src/blocks/youtube/index.ts @@ -8,7 +8,7 @@ import { YoutubeView } from './YoutubeView'; export class YoutubeBlock extends BaseView { public override selectable = true; - public override activatable = false; + public override editable = false; type = Protocol.Block.Type.youtube; View = YoutubeView; diff --git a/libs/components/editor-core/src/editor/selection/selection.ts b/libs/components/editor-core/src/editor/selection/selection.ts index e6c1f94c83..c33eb6d64c 100644 --- a/libs/components/editor-core/src/editor/selection/selection.ts +++ b/libs/components/editor-core/src/editor/selection/selection.ts @@ -408,13 +408,13 @@ export class SelectionManager implements VirgoSelection { /** * - * get previous activatable blockNode + * get previous editable blockNode * @private * @param {AsyncBlock} node * @return {*} {(Promise)} * @memberof SelectionManager */ - private async _getPreviousActivatableBlockNode( + private async _getPreviousEditableBlockNode( node: AsyncBlock ): Promise { const preNode = await node.physicallyPerviousSibling(); @@ -422,8 +422,8 @@ export class SelectionManager implements VirgoSelection { if (!preNode) { return null; } - const { activatable, selectable } = this._editor.getView(preNode.type); - if (activatable) { + const { editable, selectable } = this._editor.getView(preNode.type); + if (editable) { this.setSelectedNodesIds([]); return preNode; } @@ -432,18 +432,18 @@ export class SelectionManager implements VirgoSelection { (document.activeElement as HTMLInputElement)?.blur(); return null; } - return this._getPreviousActivatableBlockNode(preNode); + return this._getPreviousEditableBlockNode(preNode); } /** * - * get next activatable blockNode + * get next editable blockNode * @private * @param {AsyncBlock} node * @return {*} {(Promise)} * @memberof SelectionManager */ - private async _getNextActivatableBlockNode( + private async _getNextEditableBlockNode( node: AsyncBlock, ignoreSelf = true ): Promise { @@ -482,8 +482,8 @@ export class SelectionManager implements VirgoSelection { } } - const { activatable, selectable } = this._editor.getView(nextNode.type); - if (activatable) { + const { editable, selectable } = this._editor.getView(nextNode.type); + if (editable) { this.setSelectedNodesIds([]); return nextNode; } @@ -492,7 +492,7 @@ export class SelectionManager implements VirgoSelection { (document.activeElement as HTMLInputElement)?.blur(); return null; } - return this._getNextActivatableBlockNode(nextNode); + return this._getNextEditableBlockNode(nextNode); } /** @@ -513,7 +513,7 @@ export class SelectionManager implements VirgoSelection { return; } } - preNode = await this._getPreviousActivatableBlockNode(node); + preNode = await this._getPreviousEditableBlockNode(node); if (preNode) { this.activeNodeByNodeId(preNode.id, position); } @@ -622,7 +622,7 @@ export class SelectionManager implements VirgoSelection { } } - nextNode = await this._getNextActivatableBlockNode(node); + nextNode = await this._getNextEditableBlockNode(node); if (nextNode) { this.activeNodeByNodeId(nextNode.id, position); } diff --git a/libs/components/editor-core/src/editor/views/base-view.ts b/libs/components/editor-core/src/editor/views/base-view.ts index eb5c293243..2b3002f500 100644 --- a/libs/components/editor-core/src/editor/views/base-view.ts +++ b/libs/components/editor-core/src/editor/views/base-view.ts @@ -36,10 +36,10 @@ export abstract class BaseView { abstract type: string; /** - * activatable means can be focused + * editable means can be focused * @memberof BaseView */ - public activatable = true; + public editable = true; public selectable = true; From 8de387295afec9f0f390a85f3ff8ae6a6d2adfaf Mon Sep 17 00:00:00 2001 From: JimmFly Date: Fri, 19 Aug 2022 21:49:54 +0800 Subject: [PATCH 34/58] chore: update dependencies --- apps/venus/package.json | 8 +++--- pnpm-lock.yaml | 55 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/apps/venus/package.json b/apps/venus/package.json index fe69da1b8e..321da2b80d 100644 --- a/apps/venus/package.json +++ b/apps/venus/package.json @@ -7,16 +7,18 @@ "keywords": [], "author": "DarkSky ", "dependencies": { - "@mui/joy": "^5.0.0-alpha.39", "@emotion/react": "^11.10.0", "@emotion/styled": "^11.10.0", - "lozad": "^1.16.0" + "@mui/joy": "^5.0.0-alpha.39", + "i18next": "^21.9.1", + "lozad": "^1.16.0", + "react-i18next": "^11.18.4" }, "devDependencies": { - "mini-css-extract-plugin": "^2.6.1", "image-minimizer-webpack-plugin": "^3.2.3", "imagemin": "^8.0.1", "imagemin-optipng": "^8.0.0", + "mini-css-extract-plugin": "^2.6.1", "webpack": "^5.74.0" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d2d0c70750..fb9b238428 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -220,17 +220,21 @@ importers: '@emotion/react': ^11.10.0 '@emotion/styled': ^11.10.0 '@mui/joy': ^5.0.0-alpha.39 + i18next: ^21.9.1 image-minimizer-webpack-plugin: ^3.2.3 imagemin: ^8.0.1 imagemin-optipng: ^8.0.0 lozad: ^1.16.0 mini-css-extract-plugin: ^2.6.1 + react-i18next: ^11.18.4 webpack: ^5.74.0 dependencies: '@emotion/react': 11.10.0 '@emotion/styled': 11.10.0_@emotion+react@11.10.0 '@mui/joy': 5.0.0-alpha.39_72v32ofbtgpmxm7mhvtx474vfu + i18next: 21.9.1 lozad: 1.16.0 + react-i18next: 11.18.4_i18next@21.9.1 devDependencies: image-minimizer-webpack-plugin: 3.2.3_5emixpjl54fjyhdvj76qjbw4py imagemin: 8.0.1 @@ -9563,20 +9567,30 @@ packages: '@typescript-eslint/parser': optional: true dependencies: + '@babel/runtime': 7.18.6 '@typescript-eslint/parser': 5.30.5_4x5o4skxv6sl53vpwefgt23khm + aria-query: 4.2.2 array-includes: 3.1.5 array.prototype.flat: 1.3.0 + ast-types-flow: 0.0.7 + axe-core: 4.4.2 + axobject-query: 2.2.0 + damerau-levenshtein: 1.0.8 debug: 2.6.9 doctrine: 2.1.0 + emoji-regex: 9.2.2 eslint: 8.19.0 eslint-import-resolver-node: 0.3.6 eslint-module-utils: 2.7.3_ea34krk32wbcqzxapvwr7rsjs4 has: 1.0.3 is-core-module: 2.9.0 is-glob: 4.0.3 + jsx-ast-utils: 3.3.1 + language-tags: 1.0.5 minimatch: 3.1.2 object.values: 1.1.5 resolve: 1.22.1 + semver: 6.3.0 tsconfig-paths: 3.14.1 transitivePeerDependencies: - eslint-import-resolver-typescript @@ -11121,6 +11135,12 @@ packages: terser: 5.14.1 dev: true + /html-parse-stringify/3.0.1: + resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==} + dependencies: + void-elements: 3.1.0 + dev: false + /html-webpack-plugin/5.5.0_webpack@5.74.0: resolution: {integrity: sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==} engines: {node: '>=10.13.0'} @@ -11306,6 +11326,12 @@ packages: hasBin: true dev: true + /i18next/21.9.1: + resolution: {integrity: sha512-ITbDrAjbRR73spZAiu6+ex5WNlHRr1mY+acDi2ioTHuUiviJqSz269Le1xHAf0QaQ6GgIHResUhQNcxGwa/PhA==} + dependencies: + '@babel/runtime': 7.18.6 + dev: false + /iconv-lite/0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -15149,7 +15175,7 @@ packages: dev: true /proxy-from-env/1.0.0: - resolution: {integrity: sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4=} + resolution: {integrity: sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==} dev: true /prr/1.0.1: @@ -15345,6 +15371,26 @@ packages: hotkeys-js: 3.9.3 dev: false + /react-i18next/11.18.4_i18next@21.9.1: + resolution: {integrity: sha512-gK/AylAQC5DvCD5YLNCHW4PNzpCfrWIyVAXbSMl+/5QXzlDP8VdBoqE2s2niGHB+zIXwBV9hRXbDrVuupbgHcg==} + peerDependencies: + i18next: '>= 19.0.0' + react: '>= 16.8.0' + react-dom: '*' + react-native: '*' + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + react-native: + optional: true + dependencies: + '@babel/runtime': 7.18.6 + html-parse-stringify: 3.0.1 + i18next: 21.9.1 + dev: false + /react-is/16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -17592,7 +17638,7 @@ packages: dev: true /verror/1.10.0: - resolution: {integrity: sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=} + resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} engines: {'0': node >=0.6.0} dependencies: assert-plus: 1.0.0 @@ -17600,6 +17646,11 @@ packages: extsprintf: 1.3.0 dev: true + /void-elements/3.1.0: + resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} + engines: {node: '>=0.10.0'} + dev: false + /w3c-hr-time/1.0.2: resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} dependencies: From 4eb1c51be59fe718b45611a0cfa80df819c1cb2d Mon Sep 17 00:00:00 2001 From: JimmFly Date: Fri, 19 Aug 2022 21:50:24 +0800 Subject: [PATCH 35/58] feat: add i18n --- apps/venus/src/app/i18n/index.ts | 25 +++++++ apps/venus/src/app/i18n/resources/en.json | 34 ++++++++++ apps/venus/src/app/i18n/resources/zh.json | 34 ++++++++++ apps/venus/src/app/index.tsx | 80 ++++++++++++----------- apps/venus/src/index.tsx | 1 + 5 files changed, 135 insertions(+), 39 deletions(-) create mode 100644 apps/venus/src/app/i18n/index.ts create mode 100644 apps/venus/src/app/i18n/resources/en.json create mode 100644 apps/venus/src/app/i18n/resources/zh.json diff --git a/apps/venus/src/app/i18n/index.ts b/apps/venus/src/app/i18n/index.ts new file mode 100644 index 0000000000..9ddaa8330d --- /dev/null +++ b/apps/venus/src/app/i18n/index.ts @@ -0,0 +1,25 @@ +import i18next from 'i18next'; +import { initReactI18next } from 'react-i18next'; +import en_US from './resources/en.json'; +import zh_CN from './resources/zh.json'; + +const resources = { + en: en_US, + zh: zh_CN, +} as const; + +i18next.use(initReactI18next).init({ + lng: 'en', + fallbackLng: 'en', + resources, + interpolation: { + escapeValue: false, // not needed for react as it escapes by default + }, +}); + +export const options = [ + { value: 'en', text: 'English' }, + { value: 'zh', text: '็ฎ€ไฝ“ไธญๆ–‡' }, +]; + +export { i18next }; diff --git a/apps/venus/src/app/i18n/resources/en.json b/apps/venus/src/app/i18n/resources/en.json new file mode 100644 index 0000000000..cd7a377352 --- /dev/null +++ b/apps/venus/src/app/i18n/resources/en.json @@ -0,0 +1,34 @@ +{ + "translation": { + "Open Source": "Open Source", + "Privacy First": "Privacy First", + "Alternative": "Alternative", + "Check GitHub": "Check GitHub", + "Try it Online": "Try it Online", + "description1": { + "part1": "Affine is the next-generation collaborative knowledge base for professionals.", + "part2": "It's not just a collection of Docs, whiteboard, and tables.", + "part3": "Transform any building block as you like.", + "part4": "Say goodbye to redundancy. Store your data once, and keep your data as you like it." + }, + "description2": { + "part1": "Shape Your Page", + "part2": "Docs, Kanbans, and Databases are all fully functional anywhere, anytime. A truly what-you-see-is-what-you-get environment for your data.", + "part3": "All pages come with a document (Paper Mode) and whiteboard (Edgeless Mode) view." + }, + "description3": { + "part1": "Plan Your Task", + "part2": "No more chaos managing multiple views.", + "part3": "Set a TODO with Markdown, and seamlessly edit it within a Kanban.", + "part4": "Managing multi-dimensional tables should be this simple - and now it is." + }, + "description4": { + "part1": "Privacy-first, and collaborative. No compromises whatsoever.", + "part2": "We don't like being locked-in, and neither should you. Privacy is at the foundation of everything we do, but it should not limit us that's why there are no compromises.", + "part3": "Your data is yours;it is always locally stored and secured - available to you always. While still being able to enjoy collaboration features such as real-time editing and sharing with others, without any cloud setup." + }, + "BuildFor": "Build for an open and semantic future", + "KeepUpdated": "Keep Updated on", + "Join": "Join Our Community" + } +} diff --git a/apps/venus/src/app/i18n/resources/zh.json b/apps/venus/src/app/i18n/resources/zh.json new file mode 100644 index 0000000000..eb4cf432dd --- /dev/null +++ b/apps/venus/src/app/i18n/resources/zh.json @@ -0,0 +1,34 @@ +{ + "translation": { + "Open Source": "ๅผ€ๆบ", + "Privacy First": "้š็ง็ฌฌไธ€", + "Alternative": "็š„ๅฆไธ€็ง้€‰ๆ‹ฉ", + "Check GitHub": "GitHubไธญๆŸฅ็œ‹", + "Try it Online": "ๅœจ็บฟไธŠ่ฏ•่ฏ•", + "description1": { + "part1": "Affineๆ˜ฏ้ขๅ‘ไธ“ไธšไบบๅฃซ็š„ไธ‹ไธ€ไปฃๅๅŒ็Ÿฅ่ฏ†ๅบ“", + "part2": "ๅฎƒไธไป…ไป…ๆ˜ฏไธ€ไธชๆ–‡ๆกฃใ€็™ฝๆฟๅ’Œ่กจๆ ผ็š„้›†ๅˆใ€‚", + "part3": "ๅฏไปฅๆ นๆฎ้œ€่ฆ่ฝฌๆขไปปไฝ•ๆž„ๅปบๅ—ใ€‚", + "part4": "ๅ‘ๅ†—ไฝ™่ฏดๅ†่งๅงใ€‚ๅฐ†ๆ•ฐๆฎๅญ˜ๅ‚จไธ€ๆฌก๏ผŒๅนถไฟ็•™ๆ‚จๅ–œๆฌข็š„ๆ•ฐๆฎใ€‚" + }, + "description2": { + "part1": "ๅก‘้€ ๆ‚จ็š„้กต้ข", + "part2": "ๆ–‡ๆกฃใ€็œ‹ๆฟๅ’Œๆ•ฐๆฎๅบ“ๅœจไปปไฝ•ๅœฐๆ–นใ€ไปปไฝ•ๆ—ถๅ€™้ƒฝๆ˜ฏๅฎŒๅ…จๅฏ็”จ็š„๏ผŒไธ€ไธช็œŸๆญฃ็š„โ€œๆ‰€่งๅณๆ‰€ๅพ—โ€็š„ๆ•ฐๆฎ็Žฏๅขƒใ€‚", + "part3": "ๆ‰€ๆœ‰้กต้ข้ƒฝๆœ‰ไธ€ไธชๆ–‡ๆกฃ(็บธๅผ ๆจกๅผ)ๅ’Œ็™ฝๆฟ(ๆ— ่พน็ผ˜ๆจกๅผ)่ง†ๅ›พใ€‚" + }, + "description3": { + "part1": "่ฎกๅˆ’ๆ‚จ็š„ไปปๅŠก", + "part2": "ไธๅ†ๆททไนฑๅœฐ็ฎก็†ๅคšไธช่ง†ๅ›พใ€‚", + "part3": "ไฝฟ็”จ Markdown ่ฎพ็ฝฎ TODO๏ผŒๅนถๅœจ็œ‹ๆฟไธญๆ— ็ผๅœฐ็ผ–่พ‘ๅฎƒใ€‚", + "part4": "็ฎก็†ๅคš็ปด่กจๆ ผๆœฌๅบ”่ฏฅๅฐฑ่ฟ™ไนˆ็ฎ€ๅ•โ€”โ€”็Žฐๅœจ็š„ๅฎƒๅฐฑๆ˜ฏ่ฟ™ไนˆ็ฎ€ๅ•ใ€‚" + }, + "description4": { + "part1": "้š็ง็ฌฌไธ€๏ผŒๅˆไฝœๆ— ้—ด๏ผŒ็ปไธๅฆฅๅใ€‚", + "part2": "ๆˆ‘ไปฌไธๅ–œๆฌข่ขซๅ…ณ่ตทๆฅ๏ผŒๆ‚จไนŸไธๅบ”่ฏฅใ€‚้š็งๆ˜ฏๆˆ‘ไปฌๅšไปปไฝ•ไบ‹ๆƒ…็š„ๅŸบ็ก€๏ผŒไฝ†ๅฎƒไธๅบ”่ฏฅ้™ๅˆถๆˆ‘ไปฌ๏ผŒ่ฟ™ๅฐฑๆ˜ฏไธบไป€ไนˆๆˆ‘ไปฌๅ†ณไธๅฆฅๅใ€‚", + "part3": "ๆ‚จ็š„ๆ•ฐๆฎๆ˜ฏๆ‚จ่‡ชๅทฑ็š„๏ผŒๅฎƒๆ€ปๆ˜ฏๅฎ‰ๅ…จ็š„ๅœจๆœฌๅœฐๅญ˜ๅ‚จๅนถ้šๆ—ถไพ›ๆ‚จไฝฟ็”จใ€‚ๆ‚จไธ้œ€่ฆไปปไฝ•ไบ‘่ฎพ็ฝฎๅฐฑๅฏไปฅไบซๅ—ๅไฝœๅŠŸ่ƒฝ๏ผŒๅณๆ—ถ็ผ–่พ‘ๅ’ŒไธŽไป–ไบบๅ…ฑไบซใ€‚" + }, + "BuildFor": "ๆž„ๅปบไธ€ไธชๅผ€ๆ”พๅ’Œ่ฏญไน‰ๅŒ–็š„ๆœชๆฅ", + "KeepUpdated": "ๆŒ็ปญๆ›ดๆ–ฐๅœจ", + "Join": "ๅŠ ๅ…ฅๆˆ‘ไปฌ็š„็คพๅŒบ" + } +} diff --git a/apps/venus/src/app/index.tsx b/apps/venus/src/app/index.tsx index 71db02985e..038da7373d 100644 --- a/apps/venus/src/app/index.tsx +++ b/apps/venus/src/app/index.tsx @@ -7,12 +7,15 @@ import GitHubIcon from '@mui/icons-material/GitHub'; import RedditIcon from '@mui/icons-material/Reddit'; import TelegramIcon from '@mui/icons-material/Telegram'; import { Box, Button, Container, Grid, SvgIcon, Typography } from '@mui/joy'; +import Option from '@mui/joy/Option'; +import Select from '@mui/joy/Select'; import { CssVarsProvider, styled } from '@mui/joy/styles'; import { LogoIcon } from '@toeverything/components/icons'; // eslint-disable-next-line no-restricted-imports import { useMediaQuery } from '@mui/material'; - +import { useTranslation } from 'react-i18next'; import CollaborationImage from './collaboration.png'; +import { options } from './i18n'; import LogoImage from './logo.png'; import PageImage from './page.png'; import ShapeImage from './shape.png'; @@ -199,6 +202,7 @@ const AffineImage = styled('img')({ const GitHub = (props: { center?: boolean; flat?: boolean }) => { const matches = useMediaQuery('(max-width: 1024px)'); + const { t } = useTranslation(); return ( ); }; const AFFiNEOnline = (props: { center?: boolean; flat?: boolean }) => { const matches = useMediaQuery('(max-width: 1024px)'); - + const { t } = useTranslation(); return ( ); }; export function App() { const matches = useMediaQuery('(max-width: 1024px)'); + const { t, i18n } = useTranslation(); + const changeLanguage = (event: any) => { + i18n.changeLanguage(event); + }; return ( Blog + - Open Source, + {t('Open Source')}, - Privacy First + {t('Privacy First')} @@ -413,7 +428,7 @@ export function App() { }, }} > - Alternative + {t('Alternative')} @@ -432,8 +447,7 @@ export function App() { fontWeight={'400'} sx={{ color: '#888' }} > - Affine is the next-generation collaborative - knowledge base for professionals. + {t('description1.part1')} @@ -488,8 +502,7 @@ export function App() { level={matches ? 'h2' : 'h1'} fontWeight={'bold'} > - Itโ€™s not just a collection of Docs, whiteboard, and - tables. + {t('description1.part2')} @@ -506,11 +519,10 @@ export function App() { }} > - Transform any building block as you like. + {t('description1.part3')} - Say goodbye to redundancy. Store your data once, and - keep your data as you like it. + {t('description1.part4')} @@ -547,23 +559,19 @@ export function App() { fontWeight={'bold'} style={{ marginBottom: '0.5em' }} > - Shape Your Page + {t('description2.part1')} - Docs, Kanbans, and Databases are all fully - functional anywhere, anytime. A truly - what-you-see-is-what-you-get environment for - your data. + {t('description2.part2')} - All pages come with a document (Paper Mode) and - whiteboard (Edgeless Mode) view. + {t('description2.part3')} @@ -625,27 +633,25 @@ export function App() { fontWeight={'bold'} style={{ marginBottom: '0.5em' }} > - Plan Your Task + {t('description3.part1')} - No more chaos managing multiple views. + {t('description3.part2')} - Set a TODO with Markdown, and seamlessly edit it - within a Kanban. + {t('description3.part3')} - Managing multi-dimensional tables should be this - simple โ€“ and now it is. + {t('description3.part4')} @@ -697,17 +703,13 @@ export function App() { fontWeight={'bold'} style={{ marginBottom: '0.5em' }} > - Privacy-first, and collaborative. No compromises - whatsoever. + {t('description4.part1')} - We donโ€™t like being locked-in, and neither should - you. Privacy is at the foundation of everything we - do, but it should not limit us thatโ€™s+ why there are - no compromises. + {t('description4.part2')} Your data is yours; it is always locally stored and secured - available to you always. While still being - able to enjoy collaboration features such as - real-time editing and sharing with others, without - any cloud setup. + able enjoy collaboration features such as real-time + editing and sharing with others, without any cloud + setup. @@ -762,7 +764,7 @@ export function App() { }} > - Build for an open and semantic future + {t('BuildFor')} @@ -778,7 +780,7 @@ export function App() { > - Keep Updated on + {t('KeepUpdated')} @@ -795,7 +797,7 @@ export function App() { }} > - Join Our Community + {t('Join')} diff --git a/apps/venus/src/index.tsx b/apps/venus/src/index.tsx index f76f9a6f20..5fdc926e59 100644 --- a/apps/venus/src/index.tsx +++ b/apps/venus/src/index.tsx @@ -1,6 +1,7 @@ import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import { BrowserRouter } from 'react-router-dom'; +import './app/i18n'; import App from './app'; From 6846f23e7de116ce0fa21c923a5249987bd32d27 Mon Sep 17 00:00:00 2001 From: JimmFly Date: Fri, 19 Aug 2022 22:08:23 +0800 Subject: [PATCH 36/58] update i18n --- apps/venus/src/app/index.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/apps/venus/src/app/index.tsx b/apps/venus/src/app/index.tsx index 038da7373d..e4d9c7854e 100644 --- a/apps/venus/src/app/index.tsx +++ b/apps/venus/src/app/index.tsx @@ -238,7 +238,7 @@ const GitHub = (props: { center?: boolean; flat?: boolean }) => { startIcon={} size="lg" > - {t(`${props.center ? 'Check ' : ''}GitHub`)} + {props.center ? t('Check GitHub') : t('GitHub')} ); }; @@ -715,11 +715,7 @@ export function App() { fontSize="1.2em" style={{ marginBottom: '0.25em' }} > - Your data is yours; it is always locally stored and - secured - available to you always. While still being - able enjoy collaboration features such as real-time - editing and sharing with others, without any cloud - setup. + {t('description4.part3')} From 945b5ff5ad3a0838c0084bdb20c60d61749290eb Mon Sep 17 00:00:00 2001 From: HeJiachen-PM <79301703+HeJiachen-PM@users.noreply.github.com> Date: Sun, 21 Aug 2022 01:41:39 +0800 Subject: [PATCH 37/58] Uploaded roadmap --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e0ce3c8b45..396bfe008e 100644 --- a/README.md +++ b/README.md @@ -123,7 +123,7 @@ Please view the path Contribute-to-AFFiNE/Software-Contributions/Quick-Start in # Roadmap -Coming Soon... +Yes! Permanent storage, collaboration, stable release is planned! Check it [here](https://github.com/toeverything/AFFiNE/issues/293) # Releases From 7c117e5f8fb80930fb3277fa6a2b0468e57723db Mon Sep 17 00:00:00 2001 From: Yipei Wei <79373028+Yipei-Operation@users.noreply.github.com> Date: Sun, 21 Aug 2022 21:33:26 +0800 Subject: [PATCH 38/58] Update README.md add contact email --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 396bfe008e..d4e8eb9953 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,8 @@ Get quick help on [Telegram](https://t.me/affineworkos) or [Discord](https://dis Our latest news can be found on [Twitter](https://twitter.com/AffineOfficial), [Medium](https://medium.com/@affineworkos) and the [AFFiNE Blog](https://blog.affine.pro/). +Our contact email address is contact@toeverything.info. + # The Philosophy of AFFiNE Timothy Berners-Lee once taught us about the idea of the semantic web, where all the data can be interpreted in any form while the "truth" is kept. This gives our best image of an ideal knowledge base by far, that sorting of information, planning of project and goals as well as creating of knowledge can be all together. From 7822c4a0fda2e1208ba424c21065cd75a8db6d63 Mon Sep 17 00:00:00 2001 From: Yipei Wei <79373028+Yipei-Operation@users.noreply.github.com> Date: Sun, 21 Aug 2022 21:40:06 +0800 Subject: [PATCH 39/58] Update README.md add contact info of founder --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 396bfe008e..a7ac8da75e 100644 --- a/README.md +++ b/README.md @@ -139,6 +139,10 @@ Get quick help on [Telegram](https://t.me/affineworkos) or [Discord](https://dis Our latest news can be found on [Twitter](https://twitter.com/AffineOfficial), [Medium](https://medium.com/@affineworkos) and the [AFFiNE Blog](https://blog.affine.pro/). +# Contact Us +The contact info for AFFiNE Founder is here: hejiachen@toeverything.info + + # The Philosophy of AFFiNE Timothy Berners-Lee once taught us about the idea of the semantic web, where all the data can be interpreted in any form while the "truth" is kept. This gives our best image of an ideal knowledge base by far, that sorting of information, planning of project and goals as well as creating of knowledge can be all together. From 96b3a2c0d5d1787ff81f5de330ed7ec21565c40b Mon Sep 17 00:00:00 2001 From: Chi Zhang Date: Sun, 21 Aug 2022 21:53:00 +0800 Subject: [PATCH 40/58] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index eec49318e0..919fcf4114 100644 --- a/README.md +++ b/README.md @@ -139,10 +139,9 @@ Get quick help on [Telegram](https://t.me/affineworkos) or [Discord](https://dis Our latest news can be found on [Twitter](https://twitter.com/AffineOfficial), [Medium](https://medium.com/@affineworkos) and the [AFFiNE Blog](https://blog.affine.pro/). - # Contact Us -The contact info for AFFiNE Founder is here: hejiachen@toeverything.info +The contact info for AFFiNE Founder is here: hejiachen@toeverything.info # The Philosophy of AFFiNE From e61b3ce4e40e3e4266783165c26512eb81fba521 Mon Sep 17 00:00:00 2001 From: zuomeng wang Date: Mon, 22 Aug 2022 15:02:33 +0800 Subject: [PATCH 41/58] feat: add get-started template (#309) --- .../src/services/editor-block/templates/template-factory.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/datasource/db-service/src/services/editor-block/templates/template-factory.ts b/libs/datasource/db-service/src/services/editor-block/templates/template-factory.ts index 6c8d5a5643..4cdf62676d 100644 --- a/libs/datasource/db-service/src/services/editor-block/templates/template-factory.ts +++ b/libs/datasource/db-service/src/services/editor-block/templates/template-factory.ts @@ -29,7 +29,7 @@ const groupTemplateMap = { const defaultTemplateList: Array = [ { name: 'New From Quick Start', - groupKeys: ['todolist'], + groupKeys: ['getStartedGroup0', 'getStartedGroup1', 'getStartedGroup2'], }, { name: 'New From Grid System', groupKeys: ['grid'] }, { name: 'New From Blog', groupKeys: ['blog'] }, From 7b4999225a6526b09e6ed5c391c549fc92e96920 Mon Sep 17 00:00:00 2001 From: HeJiachen-PM <79301703+HeJiachen-PM@users.noreply.github.com> Date: Mon, 22 Aug 2022 22:58:16 +0800 Subject: [PATCH 42/58] hided my personal email --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 919fcf4114..718d32c94d 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ Our latest news can be found on [Twitter](https://twitter.com/AffineOfficial), [ # Contact Us -The contact info for AFFiNE Founder is here: hejiachen@toeverything.info +You may contact us by emailing to: contact@toeverything.info # The Philosophy of AFFiNE From a13e2a59d3c30f5908cc18c73913e8327b85d9e9 Mon Sep 17 00:00:00 2001 From: tzhangchi Date: Tue, 23 Aug 2022 16:51:41 +0800 Subject: [PATCH 43/58] docs(readme): update readme.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 718d32c94d..19e0db1307 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ Our latest news can be found on [Twitter](https://twitter.com/AffineOfficial), [ # Contact Us -You may contact us by emailing to: contact@toeverything.info +You may contact us by emailing to: contact@toeverything.info # The Philosophy of AFFiNE From eedb4864df81d80830e7d5b9912da6110cff0b72 Mon Sep 17 00:00:00 2001 From: austaras Date: Tue, 23 Aug 2022 12:04:32 +0800 Subject: [PATCH 44/58] mod(whiteboard): close tool panel when select tool --- README.md | 2 +- libs/components/affine-board/src/Board.tsx | 7 ++-- .../src/components/tools-panel/LineTools.tsx | 6 +++- .../src/components/tools-panel/ShapeTools.tsx | 6 +++- .../src/components/tools-panel/ToolsPanel.tsx | 36 +++++++++---------- .../tools-panel/pen-tools/PenTools.tsx | 17 ++++++--- libs/components/ui/src/cascader/Cascader.tsx | 2 +- libs/components/ui/src/popper/Popper.tsx | 11 ++++-- libs/components/ui/src/popper/interface.ts | 2 ++ 9 files changed, 55 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 718d32c94d..19e0db1307 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ Our latest news can be found on [Twitter](https://twitter.com/AffineOfficial), [ # Contact Us -You may contact us by emailing to: contact@toeverything.info +You may contact us by emailing to: contact@toeverything.info # The Philosophy of AFFiNE diff --git a/libs/components/affine-board/src/Board.tsx b/libs/components/affine-board/src/Board.tsx index af9e8982fe..101d54d37b 100644 --- a/libs/components/affine-board/src/Board.tsx +++ b/libs/components/affine-board/src/Board.tsx @@ -134,17 +134,14 @@ const AffineBoard = ({ } }) ); - let pageBindingsString = ( + const pageBindingsString = ( await services.api.editorBlock.get({ workspace: workspace, ids: [rootBlockId], }) )?.[0].properties.bindings?.value; - console.log(123123123); - let pageBindings = JSON.parse(pageBindingsString ?? '{}'); - console.log(pageBindings, 3333, bindings); + const pageBindings = JSON.parse(pageBindingsString ?? '{}'); Object.keys(bindings).forEach(bindingsKey => { - console.log(345345345345345); if (!bindings[bindingsKey]) { delete pageBindings[bindingsKey]; } else { diff --git a/libs/components/board-draw/src/components/tools-panel/LineTools.tsx b/libs/components/board-draw/src/components/tools-panel/LineTools.tsx index 3ef546ca3c..ce6cb97574 100644 --- a/libs/components/board-draw/src/components/tools-panel/LineTools.tsx +++ b/libs/components/board-draw/src/components/tools-panel/LineTools.tsx @@ -35,6 +35,7 @@ const activeToolSelector = (s: TDSnapshot) => s.appState.activeTool; export const LineTools = ({ app }: { app: TldrawApp }) => { const activeTool = app.useStore(activeToolSelector); + const [visible, setVisible] = useState(false); const [lastActiveTool, setLastActiveTool] = useState( TDShapeType.Line @@ -51,8 +52,10 @@ export const LineTools = ({ app }: { app: TldrawApp }) => { return ( setVisible(prev => !prev)} + onClickAway={() => setVisible(false)} content={ {shapes.map(({ type, label, tooltip, icon: Icon }) => ( @@ -60,6 +63,7 @@ export const LineTools = ({ app }: { app: TldrawApp }) => { { app.selectTool(type); + setVisible(false); setLastActiveTool(type); }} > diff --git a/libs/components/board-draw/src/components/tools-panel/ShapeTools.tsx b/libs/components/board-draw/src/components/tools-panel/ShapeTools.tsx index eb2fb5c564..0c04126c95 100644 --- a/libs/components/board-draw/src/components/tools-panel/ShapeTools.tsx +++ b/libs/components/board-draw/src/components/tools-panel/ShapeTools.tsx @@ -71,6 +71,7 @@ const activeToolSelector = (s: TDSnapshot) => s.appState.activeTool; export const ShapeTools = ({ app }: { app: TldrawApp }) => { const activeTool = app.useStore(activeToolSelector); + const [visible, setVisible] = useState(false); const [lastActiveTool, setLastActiveTool] = useState( TDShapeType.Rectangle @@ -87,8 +88,10 @@ export const ShapeTools = ({ app }: { app: TldrawApp }) => { return ( setVisible(prev => !prev)} + onClickAway={() => setVisible(false)} content={ {shapes.map(({ type, label, tooltip, icon: Icon }) => ( @@ -96,6 +99,7 @@ export const ShapeTools = ({ app }: { app: TldrawApp }) => { { app.selectTool(type); + setVisible(false); setLastActiveTool(type); }} > diff --git a/libs/components/board-draw/src/components/tools-panel/ToolsPanel.tsx b/libs/components/board-draw/src/components/tools-panel/ToolsPanel.tsx index f659fdff1c..82a5315816 100644 --- a/libs/components/board-draw/src/components/tools-panel/ToolsPanel.tsx +++ b/libs/components/board-draw/src/components/tools-panel/ToolsPanel.tsx @@ -12,12 +12,12 @@ import { import { IconButton, PopoverContainer, + styled, // MuiIconButton as IconButton, // MuiTooltip as Tooltip, Tooltip, useTheme, } from '@toeverything/components/ui'; -import style9 from 'style9'; import { TldrawApp } from '@toeverything/components/board-state'; import { @@ -90,8 +90,8 @@ export const ToolsPanel = ({ app }: { app: TldrawApp }) => { }} direction="none" > -
-
+ + {tools.map( ({ type, @@ -127,24 +127,22 @@ export const ToolsPanel = ({ app }: { app: TldrawApp }) => { ) )} -
-
+ + ); }; -const styles = style9.create({ - container: { - display: 'flex', - flexDirection: 'column', - justifyContent: 'center', - height: '100%', - }, - toolBar: { - display: 'flex', - flexDirection: 'column', - backgroundColor: '#ffffff', - borderRadius: '10px', - padding: '4px 4px', - }, +const Container = styled('div')({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + height: '100%', +}); +const ToolBar = styled('div')({ + display: 'flex', + flexDirection: 'column', + backgroundColor: '#ffffff', + borderRadius: '10px', + padding: '4px 4px', }); diff --git a/libs/components/board-draw/src/components/tools-panel/pen-tools/PenTools.tsx b/libs/components/board-draw/src/components/tools-panel/pen-tools/PenTools.tsx index 0536acfce1..c955afba0d 100644 --- a/libs/components/board-draw/src/components/tools-panel/pen-tools/PenTools.tsx +++ b/libs/components/board-draw/src/components/tools-panel/pen-tools/PenTools.tsx @@ -12,7 +12,7 @@ import { styled, Tooltip, } from '@toeverything/components/ui'; -import { ReactElement, type CSSProperties } from 'react'; +import { useState, type CSSProperties, type ReactElement } from 'react'; import { Palette } from '../../palette'; import { Pen } from './Pen'; @@ -106,6 +106,7 @@ const PENCIL_CONFIGS_MAP = PENCIL_CONFIGS.reduce< export const PenTools = ({ app }: { app: TldrawApp }) => { const appCurrentTool = app.useStore(state => state.appState.activeTool); + const [visible, setVisible] = useState(false); const chosenPen = PENCIL_CONFIGS.find(config => config.key === appCurrentTool) || PENCIL_CONFIGS[0]; @@ -134,8 +135,10 @@ export const PenTools = ({ app }: { app: TldrawApp }) => { return ( setVisible(prev => !prev)} + onClickAway={() => setVisible(false)} content={ @@ -153,7 +156,10 @@ export const PenTools = ({ app }: { app: TldrawApp }) => { name={title} primaryColor={color_vars['--color-0']} secondaryColor={color_vars['--color-1']} - onClick={() => setPen(key)} + onClick={() => { + setVisible(false); + setPen(key); + }} /> ); } @@ -163,7 +169,10 @@ export const PenTools = ({ app }: { app: TldrawApp }) => { setPenColor(color)} + onSelect={color => { + setVisible(false); + setPenColor(color); + }} />
diff --git a/libs/components/ui/src/cascader/Cascader.tsx b/libs/components/ui/src/cascader/Cascader.tsx index 1ba44aab6b..7bf43413f2 100644 --- a/libs/components/ui/src/cascader/Cascader.tsx +++ b/libs/components/ui/src/cascader/Cascader.tsx @@ -1,5 +1,5 @@ import { ArrowRightIcon } from '@toeverything/components/icons'; -import { ReactElement, useRef, useState } from 'react'; +import { useRef, useState, type ReactElement } from 'react'; import { Divider } from '../divider'; import { MuiGrow as Grow, diff --git a/libs/components/ui/src/popper/Popper.tsx b/libs/components/ui/src/popper/Popper.tsx index 924e3be8fd..55d5692927 100644 --- a/libs/components/ui/src/popper/Popper.tsx +++ b/libs/components/ui/src/popper/Popper.tsx @@ -35,6 +35,8 @@ export const Popper = ({ offset = [0, 5], showArrow = false, popperHandlerRef, + onClick, + onClickAway, ...popperProps }: PopperProps) => { const [anchorEl, setAnchorEl] = useState(null); @@ -97,15 +99,20 @@ export const Popper = ({ return ( { - setVisible(false); + if (visibleControlledByParent) { + onClickAway?.(); + } else { + setVisible(false); + } }} > {isAnchorCustom ? null : (
setAnchorEl(dom)} - onClick={() => { + onClick={e => { if (!hasClickTrigger || visibleControlledByParent) { + onClick?.(e); return; } setVisible(!visible); diff --git a/libs/components/ui/src/popper/interface.ts b/libs/components/ui/src/popper/interface.ts index b449eff61f..1f7473ebf4 100644 --- a/libs/components/ui/src/popper/interface.ts +++ b/libs/components/ui/src/popper/interface.ts @@ -62,4 +62,6 @@ export type PopperProps = { showArrow?: boolean; popperHandlerRef?: Ref; + + onClickAway?: () => void; } & Omit; From 6df2676c8807916110fb77d0cc29df69ae265089 Mon Sep 17 00:00:00 2001 From: DarkSky Date: Tue, 23 Aug 2022 17:07:16 +0800 Subject: [PATCH 45/58] refactor: jwt internal version migration --- libs/datasource/jwt/package.json | 2 +- libs/datasource/jwt/src/block/abstract.ts | 35 +++--- libs/datasource/jwt/src/block/base.ts | 38 +++--- libs/datasource/jwt/src/block/indexer.ts | 33 +++-- libs/datasource/jwt/src/index.ts | 117 +++++++++++------- libs/datasource/jwt/src/types/block.ts | 6 +- libs/datasource/jwt/src/utils/event-bus.ts | 2 +- libs/datasource/jwt/src/utils/index.ts | 4 +- .../jwt/src/{adapter => }/yjs/binary.ts | 6 +- .../jwt/src/{adapter => }/yjs/block.ts | 17 +-- .../jwt/src/{adapter => }/yjs/gatekeeper.ts | 2 +- .../jwt/src/{adapter => }/yjs/history.ts | 5 +- .../jwt/src/{adapter => }/yjs/index.ts | 42 ++++--- .../jwt/src/{adapter => }/yjs/listener.ts | 3 +- .../jwt/src/{adapter => }/yjs/operation.ts | 38 ++++-- .../jwt/src/{adapter => }/yjs/provider.ts | 6 +- .../src/{adapter/index.ts => yjs/types.ts} | 6 +- pnpm-lock.yaml | 57 ++++++++- 18 files changed, 274 insertions(+), 145 deletions(-) rename libs/datasource/jwt/src/{adapter => }/yjs/binary.ts (96%) rename libs/datasource/jwt/src/{adapter => }/yjs/block.ts (95%) rename libs/datasource/jwt/src/{adapter => }/yjs/gatekeeper.ts (95%) rename libs/datasource/jwt/src/{adapter => }/yjs/history.ts (95%) rename libs/datasource/jwt/src/{adapter => }/yjs/index.ts (95%) rename libs/datasource/jwt/src/{adapter => }/yjs/listener.ts (98%) rename libs/datasource/jwt/src/{adapter => }/yjs/operation.ts (93%) rename libs/datasource/jwt/src/{adapter => }/yjs/provider.ts (97%) rename libs/datasource/jwt/src/{adapter/index.ts => yjs/types.ts} (97%) diff --git a/libs/datasource/jwt/package.json b/libs/datasource/jwt/package.json index dd8f6f6761..b43942b6ee 100644 --- a/libs/datasource/jwt/package.json +++ b/libs/datasource/jwt/package.json @@ -12,7 +12,7 @@ "file-selector": "^0.6.0", "flexsearch": "^0.7.21", "lib0": "^0.2.52", - "lru-cache": "^7.13.2", + "lru-cache": "^7.14.0", "ts-debounce": "^4.0.0" }, "dependencies": { diff --git a/libs/datasource/jwt/src/block/abstract.ts b/libs/datasource/jwt/src/block/abstract.ts index 38ee415e05..55249514b3 100644 --- a/libs/datasource/jwt/src/block/abstract.ts +++ b/libs/datasource/jwt/src/block/abstract.ts @@ -1,3 +1,10 @@ +import { + BlockFlavorKeys, + BlockFlavors, + BlockTypeKeys, + BlockTypes, +} from '../types'; +import { getLogger } from '../utils'; import { BlockInstance, BlockListener, @@ -6,14 +13,7 @@ import { ContentTypes, HistoryManager, MapOperation, -} from '../adapter'; -import { - BlockFlavorKeys, - BlockFlavors, - BlockTypeKeys, - BlockTypes, -} from '../types'; -import { getLogger } from '../utils'; +} from '../yjs/types'; declare const JWT_DEV: boolean; const logger = getLogger('BlockDB:block'); @@ -29,10 +29,10 @@ export class AbstractBlock< private readonly _id: string; private readonly _block: BlockInstance; private readonly _history: HistoryManager; - private readonly _root?: AbstractBlock; + private readonly _root: AbstractBlock | undefined; private readonly _parentListener: Map; - private _parent?: AbstractBlock; + private _parent: AbstractBlock | undefined; private _changeParent?: () => void; constructor( @@ -48,7 +48,9 @@ export class AbstractBlock< this._parentListener = new Map(); JWT_DEV && logger_debug(`init: exists ${this._id}`); - if (parent) this._refreshParent(parent); + if (parent) { + this._refreshParent(parent); + } } public get root() { @@ -146,7 +148,7 @@ export class AbstractBlock< return new Date(timestamp) .toISOString() .split('T')[0] - .replace(/-/g, ''); + ?.replace(/-/g, ''); } // eslint-disable-next-line no-empty } catch (e) {} @@ -259,7 +261,7 @@ export class AbstractBlock< } /** - * Insert sub-Block + * Insert children block * @param block Block instance * @param position Insertion position, if it is empty, it will be inserted at the end. If the block already exists, the position will be moved * @returns @@ -270,9 +272,12 @@ export class AbstractBlock< ) { JWT_DEV && logger(`insertChildren: start`); - if (block.id === this._id) return; // avoid self-reference + if (block.id === this._id) { + // avoid self-reference + return; + } if ( - this.type !== BlockTypes.block || // binary cannot insert subblocks + this.type !== BlockTypes.block || // binary cannot insert children blocks (block.type !== BlockTypes.block && this.flavor !== BlockFlavors.workspace) // binary can only be inserted into workspace ) { diff --git a/libs/datasource/jwt/src/block/base.ts b/libs/datasource/jwt/src/block/base.ts index 72183187b1..b5872980db 100644 --- a/libs/datasource/jwt/src/block/base.ts +++ b/libs/datasource/jwt/src/block/base.ts @@ -1,3 +1,5 @@ +import { BlockItem } from '../types'; +import { getLogger } from '../utils'; import { ArrayOperation, BlockInstance, @@ -5,9 +7,7 @@ import { ContentTypes, InternalPlainObject, MapOperation, -} from '../adapter'; -import { BlockItem } from '../types'; -import { getLogger } from '../utils'; +} from '../yjs/types'; import { AbstractBlock } from './abstract'; import { BlockCapability } from './capability'; @@ -23,8 +23,8 @@ export interface Decoration extends InternalPlainObject { type Validator = (value: T | undefined) => boolean | void; export type IndexMetadata = Readonly<{ - content?: string; - reference?: string; + content: string | undefined; + reference: string | undefined; tags: string[]; }>; export type QueryMetadata = Readonly< @@ -51,7 +51,7 @@ export class BaseBlock< B extends BlockInstance, C extends ContentOperation > extends AbstractBlock { - private readonly _exporters?: Exporters; + private readonly _exporters: Exporters | undefined; private readonly _contentExportersGetter: () => Map< string, ReadableContentExporter @@ -68,7 +68,7 @@ export class BaseBlock< ReadableContentExporter >; - validators: Map = new Map(); + private readonly _validators: Map = new Map(); constructor( block: B, @@ -157,14 +157,14 @@ export class BaseBlock< setValidator(key: string, validator?: Validator) { if (validator) { - this.validators.set(key, validator); + this._validators.set(key, validator); } else { - this.validators.delete(key); + this._validators.delete(key); } } private validate(key: string, value: unknown): boolean { - const validate = this.validators.get(key); + const validate = this._validators.get(key); if (validate) { return validate(value) === false ? false : true; } @@ -179,7 +179,7 @@ export class BaseBlock< } /** - * Get an instance of the child Block + * Get an instance of the child block * @param blockId block id */ private get_children_instance(blockId?: string): BaseBlock[] { @@ -201,9 +201,15 @@ export class BaseBlock< } try { const parent_page = this._getParentPage(false); - if (parent_page) metadata['page'] = parent_page; - if (this.group) metadata['group'] = this.group.id; - if (this.parent) metadata['parent'] = this.parent.id; + if (parent_page) { + metadata['page'] = parent_page; + } + if (this.group) { + metadata['group'] = this.group.id; + } + if (this.parent) { + metadata['parent'] = this.parent.id; + } } catch (e) { logger(`Failed to export default metadata`, e); } @@ -228,7 +234,9 @@ export class BaseBlock< for (const [name, exporter] of this._contentExportersGetter()) { try { const content = exporter(this.getContent()); - if (content) contents.push(content); + if (content) { + contents.push(content); + } } catch (err) { logger(`Failed to export content: ${name}`, err); } diff --git a/libs/datasource/jwt/src/block/indexer.ts b/libs/datasource/jwt/src/block/indexer.ts index dfee685b7e..ed57465dbc 100644 --- a/libs/datasource/jwt/src/block/indexer.ts +++ b/libs/datasource/jwt/src/block/indexer.ts @@ -7,14 +7,14 @@ import produce from 'immer'; import LRUCache from 'lru-cache'; import sift, { Query } from 'sift'; +import { BlockFlavors } from '../types'; +import { BlockEventBus, getLogger } from '../utils'; import { AsyncDatabaseAdapter, BlockInstance, ChangedStates, ContentOperation, -} from '../adapter'; -import { BlockFlavors } from '../types'; -import { BlockEventBus, getLogger } from '../utils'; +} from '../yjs/types'; import { BaseBlock, IndexMetadata, QueryMetadata } from './base'; @@ -315,7 +315,9 @@ export class BlockIndexer< private _testMetaKey(key: string) { try { const metadata = this._blockMetadata.values().next().value; - if (!metadata || typeof metadata !== 'object') return false; + if (!metadata || typeof metadata !== 'object') { + return false; + } return !!(key in metadata); } catch (e) { return false; @@ -324,8 +326,11 @@ export class BlockIndexer< private _getSortedMetadata(sort: string, desc?: boolean) { const sorter = naturalSort(Array.from(this._blockMetadata.entries())); - if (desc) return sorter.desc(([, m]) => m[sort]); - else return sorter.asc(([, m]) => m[sort]); + if (desc) { + return sorter.desc(([, m]) => m[sort]); + } else { + return sorter.asc(([, m]) => m[sort]); + } } public query(query: QueryIndexMetadata) { @@ -337,15 +342,23 @@ export class BlockIndexer< if ($sort && this._testMetaKey($sort)) { const metadata = this._getSortedMetadata($sort, $desc); metadata.forEach(([key, value]) => { - if (matches.length > limit) return; - if (filter(value)) matches.push(key); + if (matches.length > limit) { + return; + } + if (filter(value)) { + matches.push(key); + } }); return matches; } else { this._blockMetadata.forEach((value, key) => { - if (matches.length > limit) return; - if (filter(value)) matches.push(key); + if (matches.length > limit) { + return; + } + if (filter(value)) { + matches.push(key); + } }); return matches; diff --git a/libs/datasource/jwt/src/index.ts b/libs/datasource/jwt/src/index.ts index 664e0f21fa..e08bdc1e16 100644 --- a/libs/datasource/jwt/src/index.ts +++ b/libs/datasource/jwt/src/index.ts @@ -1,26 +1,7 @@ /* eslint-disable max-lines */ import { DocumentSearchOptions } from 'flexsearch'; import LRUCache from 'lru-cache'; -import { - AsyncDatabaseAdapter, - BlockInstance, - BlockListener, - ChangedStates, - Connectivity, - ContentOperation, - ContentTypes, - DataExporter, - getDataExporter, - HistoryManager, - YjsAdapter, - YjsContentOperation, - YjsInitOptions, -} from './adapter'; -import { - getYjsProviders, - YjsBlockInstance, - YjsProviderOptions, -} from './adapter/yjs'; + import { BaseBlock, BlockIndexer, @@ -39,6 +20,26 @@ import { UUID, } from './types'; import { BlockEventBus, genUUID, getLogger } from './utils'; +import { + getYjsProviders, + YjsAdapter, + YjsBlockInstance, + YjsContentOperation, + YjsInitOptions, + YjsProviderOptions, +} from './yjs'; +import { + AsyncDatabaseAdapter, + BlockInstance, + BlockListener, + ChangedStates, + Connectivity, + ContentOperation, + ContentTypes, + DataExporter, + getDataExporter, + HistoryManager, +} from './yjs/types'; declare const JWT_DEV: boolean; @@ -157,8 +158,11 @@ export class BlockClient< public addBlockListener(tag: string, listener: BlockListener) { const bus = this._eventBus.topic('updated'); - if (tag !== 'index' || !bus.has(tag)) bus.on(tag, listener); - else console.error(`block listener ${tag} is reserved or exists`); + if (tag !== 'index' || !bus.has(tag)) { + bus.on(tag, listener); + } else { + console.error(`block listener ${tag} is reserved or exists`); + } } public removeBlockListener(tag: string) { @@ -170,8 +174,11 @@ export class BlockClient< listener: BlockListener> ) { const bus = this._eventBus.topic>>('editing'); - if (tag !== 'index' || !bus.has(tag)) bus.on(tag, listener); - else console.error(`editing listener ${tag} is reserved or exists`); + if (tag !== 'index' || !bus.has(tag)) { + bus.on(tag, listener); + } else { + console.error(`editing listener ${tag} is reserved or exists`); + } } public removeEditingListener(tag: string) { @@ -184,15 +191,18 @@ export class BlockClient< ) { const bus = this._eventBus.topic>('connectivity'); - if (tag !== 'index' || !bus.has(tag)) bus.on(tag, listener); - else + if (tag !== 'index' || !bus.has(tag)) { + bus.on(tag, listener); + } else { console.error(`connectivity listener ${tag} is reserved or exists`); + } } public removeConnectivityListener(tag: string) { this._eventBus.topic('connectivity').off(tag); } + // @ts-ignore private inspector() { return { ...this._adapter.inspector(), @@ -220,7 +230,9 @@ export class BlockClient< this.addBlockListener('index', async states => { await Promise.allSettled( Array.from(states.entries()).map(([id, state]) => { - if (state === 'delete') this._blockCaches.delete(id); + if (state === 'delete') { + this._blockCaches.delete(id); + } return this._blockIndexer.refreshIndex(id, state); }) ); @@ -255,7 +267,7 @@ export class BlockClient< } /** - * research all + * Full text search * @param part_of_title_or_content Title or content keyword, support Chinese * @param part_of_title_or_content.index search range, optional values: title, ttl, content, reference * @param part_of_title_or_content.tag tag, string or array of strings, supports multiple tags @@ -295,7 +307,9 @@ export class BlockClient< this.search(part_of_title_or_content).flatMap(({ result }) => result.map(async id => { const page = this._pageMapping.get(id as string); - if (page) return page; + if (page) { + return page; + } const block = await this.get(id as BlockTypeKeys); return this.set_page(block); }) @@ -307,9 +321,10 @@ export class BlockClient< } return Promise.all( this._blockIndexer.getMetadata(pages).map(async page => ({ - content: this.get_decoded_content( - await this._adapter.getBlock(page.id) - ), + content: + this.get_decoded_content( + await this._adapter.getBlock(page.id) + ) || '', ...page, })) ); @@ -327,9 +342,10 @@ export class BlockClient< const ids = this.query(query); return Promise.all( this._blockIndexer.getMetadata(ids).map(async page => ({ - content: this.get_decoded_content( - await this._adapter.getBlock(page.id) - ), + content: + this.get_decoded_content( + await this._adapter.getBlock(page.id) + ) || '', ...page, })) ); @@ -378,7 +394,7 @@ export class BlockClient< private async get_parent(id: string) { const parents = this._parentMapping.get(id); - if (parents) { + if (parents && parents[0]) { const parent_block_id = parents[0]; if (!this._blockCaches.has(parent_block_id)) { this._blockCaches.set( @@ -405,7 +421,9 @@ export class BlockClient< private set_page(block: BaseBlock) { const page = this._pageMapping.get(block.id); - if (page) return page; + if (page) { + return page; + } const parent_page = block.parent_page; if (parent_page) { this._pageMapping.set(block.id, parent_page); @@ -472,8 +490,9 @@ export class BlockClient< matched += 1; } } - if (matched === conditions.length) + if (matched === conditions.length) { exporters.push([name, exporter] as const); + } } return exporters; @@ -487,7 +506,9 @@ export class BlockClient< ); if (exporter) { const op = block.content.asMap(); - if (op) return exporter[1](op); + if (op) { + return exporter[1](op); + } } } return undefined; @@ -566,7 +587,9 @@ export class BlockClient< this.set_page(abstract_block); abstract_block.on('parent', 'client_hook', state => { const [parent] = state.keys(); - this.set_parent(parent, abstract_block.id); + if (parent) { + this.set_parent(parent, abstract_block.id); + } this.set_page(abstract_block); }); this._blockCaches.set(abstract_block.id, abstract_block); @@ -650,13 +673,6 @@ export type BlockInitOptions = NonNullable< Parameters[1] >; -export type { - ArrayOperation, - ChangedStates, - Connectivity, - MapOperation, - TextOperation, -} from './adapter'; export type { BlockSearchItem, Decoration as BlockDecoration, @@ -665,4 +681,11 @@ export type { export { BlockTypes, BucketBackend as BlockBackend } from './types'; export type { BlockTypeKeys } from './types'; export { isBlock } from './utils'; +export type { + ArrayOperation, + ChangedStates, + Connectivity, + MapOperation, + TextOperation, +} from './yjs/types'; export type { QueryIndexMetadata }; diff --git a/libs/datasource/jwt/src/types/block.ts b/libs/datasource/jwt/src/types/block.ts index 3b04dc7830..d1867f1ef9 100644 --- a/libs/datasource/jwt/src/types/block.ts +++ b/libs/datasource/jwt/src/types/block.ts @@ -1,4 +1,4 @@ -import { ContentOperation } from '../adapter'; +import { ContentOperation } from '../yjs/types'; import { RefMetadata } from './metadata'; import { UUID } from './uuid'; // base type of block @@ -60,8 +60,8 @@ export type BlockItem = { flavor: typeof BlockFlavors[BlockFlavorKeys]; children: string[]; readonly created: number; // creation time, UTC timestamp - readonly updated?: number; // update time, UTC timestamp - readonly creator?: string; // creator id + readonly updated?: number | undefined; // update time, UTC timestamp + readonly creator?: string | undefined; // creator id content: C; // Essentially what is stored here is either Uint8Array (binary resource) or YDoc (structured resource) }; diff --git a/libs/datasource/jwt/src/utils/event-bus.ts b/libs/datasource/jwt/src/utils/event-bus.ts index 50f5363390..85096dd6ed 100644 --- a/libs/datasource/jwt/src/utils/event-bus.ts +++ b/libs/datasource/jwt/src/utils/event-bus.ts @@ -81,7 +81,7 @@ class BlockScopedEventBus extends BlockEventBus { options?: ListenerOptions ) { if (options?.debounce) { - const { wait, maxWait } = options.debounce; + const { wait, maxWait = 500 } = options.debounce; const debounced = debounce(listener, wait, { maxWait }); this.on_listener(this._topic, name, e => { debounced((e as CustomEvent)?.detail); diff --git a/libs/datasource/jwt/src/utils/index.ts b/libs/datasource/jwt/src/utils/index.ts index f19e5633a1..3d0d3bb101 100644 --- a/libs/datasource/jwt/src/utils/index.ts +++ b/libs/datasource/jwt/src/utils/index.ts @@ -39,7 +39,9 @@ export function getLogger(namespace: string) { if (JWT_DEV) { const logger = debug(namespace); logger.log = console.log.bind(console); - if (JWT_DEV === ('testing' as any)) logger.enabled = true; + if (JWT_DEV === ('testing' as any)) { + logger.enabled = true; + } return logger; } else { return () => {}; diff --git a/libs/datasource/jwt/src/adapter/yjs/binary.ts b/libs/datasource/jwt/src/yjs/binary.ts similarity index 96% rename from libs/datasource/jwt/src/adapter/yjs/binary.ts rename to libs/datasource/jwt/src/yjs/binary.ts index 468710ac4a..c156452c78 100644 --- a/libs/datasource/jwt/src/adapter/yjs/binary.ts +++ b/libs/datasource/jwt/src/yjs/binary.ts @@ -25,7 +25,7 @@ export class YjsRemoteBinaries { } else { // TODO: Remote Load try { - const file = await this._remoteStorage?.instance.getBuffData( + const file = await this._remoteStorage?.instance?.getBuffData( name ); console.log(file); @@ -44,11 +44,11 @@ export class YjsRemoteBinaries { this._binaries.set(name, binary); if (this._remoteStorage) { // TODO: Remote Save, if there is an object with the same name remotely, the upload is skipped, because the file name is the hash of the file content - const has_file = this._remoteStorage.instance.exist(name); + const has_file = this._remoteStorage.instance?.exist(name); if (!has_file) { const upload_file = new File(binary.toArray(), name); await this._remoteStorage.instance - .upload(upload_file) + ?.upload(upload_file) .catch(err => { throw new Error(`${err} upload error`); }); diff --git a/libs/datasource/jwt/src/adapter/yjs/block.ts b/libs/datasource/jwt/src/yjs/block.ts similarity index 95% rename from libs/datasource/jwt/src/adapter/yjs/block.ts rename to libs/datasource/jwt/src/yjs/block.ts index 3f2b756799..513016f90e 100644 --- a/libs/datasource/jwt/src/adapter/yjs/block.ts +++ b/libs/datasource/jwt/src/yjs/block.ts @@ -5,8 +5,8 @@ import { transact, } from 'yjs'; -import { BlockItem, BlockTypes } from '../../types'; -import { BlockInstance, BlockListener, HistoryManager } from '../index'; +import { BlockItem, BlockTypes } from '../types'; +import { BlockInstance, BlockListener, HistoryManager } from './types'; import { YjsHistoryManager } from './history'; import { ChildrenListenerHandler, ContentListenerHandler } from './listener'; @@ -34,7 +34,7 @@ type YjsBlockInstanceProps = { export class YjsBlockInstance implements BlockInstance { private readonly _id: string; private readonly _block: YMap; - private readonly _binary?: YArray; + private readonly _binary: YArray | undefined; private readonly _children: YArray; private readonly _setBlock: ( id: string, @@ -48,8 +48,7 @@ export class YjsBlockInstance implements BlockInstance { private readonly _childrenListeners: Map; private readonly _contentListeners: Map; - // eslint-disable-next-line @typescript-eslint/naming-convention - _childrenMap: Map; + private _childrenMap: Map; constructor(props: YjsBlockInstanceProps) { this._id = props.id; @@ -184,7 +183,9 @@ export class YjsBlockInstance implements BlockInstance { } hasChildren(id: string): boolean { - if (this.children.includes(id)) return true; + if (this.children.includes(id)) { + return true; + } return this.getChildren().some(block => block.hasChildren(id)); } @@ -263,7 +264,9 @@ export class YjsBlockInstance implements BlockInstance { break; } } - if (id) failed.push(id); + if (id) { + failed.push(id); + } } this._childrenMap = getMapFromYArray(this._children); diff --git a/libs/datasource/jwt/src/adapter/yjs/gatekeeper.ts b/libs/datasource/jwt/src/yjs/gatekeeper.ts similarity index 95% rename from libs/datasource/jwt/src/adapter/yjs/gatekeeper.ts rename to libs/datasource/jwt/src/yjs/gatekeeper.ts index 7e02c5a09e..9acf1becf5 100644 --- a/libs/datasource/jwt/src/adapter/yjs/gatekeeper.ts +++ b/libs/datasource/jwt/src/yjs/gatekeeper.ts @@ -32,7 +32,7 @@ export class GateKeeper { return creator === this._userId || !!this._common.get(block_id); } - checkDeleteLists(block_ids: string[]) { + checkDeleteLists(block_ids: string[]): [string[], string[]] { const success = []; const fail = []; for (const block_id of block_ids) { diff --git a/libs/datasource/jwt/src/adapter/yjs/history.ts b/libs/datasource/jwt/src/yjs/history.ts similarity index 95% rename from libs/datasource/jwt/src/adapter/yjs/history.ts rename to libs/datasource/jwt/src/yjs/history.ts index 6739cf9a50..5c6f5c4001 100644 --- a/libs/datasource/jwt/src/adapter/yjs/history.ts +++ b/libs/datasource/jwt/src/yjs/history.ts @@ -1,10 +1,11 @@ import { Map as YMap, UndoManager } from 'yjs'; -import { HistoryCallback, HistoryManager } from '../../adapter'; +import { HistoryCallback, HistoryManager } from './types'; type StackItem = UndoManager['undoStack'][0]; export class YjsHistoryManager implements HistoryManager { + // @ts-ignore private readonly _blocks: YMap; private readonly _historyManager: UndoManager; private readonly _pushListeners: Map>; @@ -56,7 +57,7 @@ export class YjsHistoryManager implements HistoryManager { } break(): void { - // this.#history_manager. + // this._historyManager. } undo(): Map | undefined { diff --git a/libs/datasource/jwt/src/adapter/yjs/index.ts b/libs/datasource/jwt/src/yjs/index.ts similarity index 95% rename from libs/datasource/jwt/src/adapter/yjs/index.ts rename to libs/datasource/jwt/src/yjs/index.ts index ec201c2d84..7d0f30e4e3 100644 --- a/libs/datasource/jwt/src/adapter/yjs/index.ts +++ b/libs/datasource/jwt/src/yjs/index.ts @@ -18,15 +18,15 @@ import { transact, } from 'yjs'; +import { BlockItem, BlockTypes } from '../types'; +import { getLogger, sha3, sleep } from '../utils'; import { AsyncDatabaseAdapter, BlockListener, ChangedStateKeys, Connectivity, HistoryManager, -} from '../../adapter'; -import { BlockItem, BlockTypes } from '../../types'; -import { getLogger, sha3, sleep } from '../../utils'; +} from './types'; import { YjsRemoteBinaries } from './binary'; import { YjsBlockInstance } from './block'; @@ -40,6 +40,7 @@ import { import { YjsProvider } from './provider'; declare const JWT_DEV: boolean; +// @ts-ignore const logger = getLogger('BlockDB:yjs'); type ConnectivityListener = ( @@ -54,7 +55,7 @@ type YjsProviders = { gatekeeper: GateKeeper; connListener: { listeners?: ConnectivityListener }; userId: string; - remoteToken?: string; // remote storage token + remoteToken: string | undefined; // remote storage token }; const _yjsDatabaseInstance = new Map(); @@ -70,8 +71,8 @@ async function _initYjsDatabase( workspace: string, options: { userId: string; - token?: string; - provider?: Record; + token?: string | undefined; + provider?: Record | undefined; } ): Promise { if (_asyncInitLoading.has(workspace)) { @@ -243,9 +244,10 @@ export class YjsAdapter implements AsyncDatabaseAdapter { typeof updated === 'number' && updated + 1000 * 10 > Date.now() ) { - if (!editing_mapping[editing]) + if (!editing_mapping[editing]) { editing_mapping[editing] = []; - editing_mapping[editing].push(userId); + } + editing_mapping[editing]?.push(userId); } } listener( @@ -338,7 +340,7 @@ export class YjsAdapter implements AsyncDatabaseAdapter { ], }); const [file] = (await fromEvent(handles)) as File[]; - const binary = await file.arrayBuffer(); + const binary = await file?.arrayBuffer(); // await this._provider.idb.clearData(); const doc = new Doc({ autoLoad: true, shouldLoad: true }); let updated = 0; @@ -348,7 +350,9 @@ export class YjsAdapter implements AsyncDatabaseAdapter { updated += 1; }); setInterval(() => { - if (updated > 0) updated -= 1; + if (updated > 0) { + updated -= 1; + } }, 500); const update_check = new Promise(resolve => { @@ -362,8 +366,10 @@ export class YjsAdapter implements AsyncDatabaseAdapter { }); // await new IndexedDBProvider(this._provider.idb.name, doc) // .whenSynced; - applyUpdate(doc, new Uint8Array(binary)); - await update_check; + if (binary) { + applyUpdate(doc, new Uint8Array(binary)); + await update_check; + } console.log('load success'); }, parse: () => this._doc.toJSON(), @@ -409,8 +415,8 @@ export class YjsAdapter implements AsyncDatabaseAdapter { async createBlock( options: Pick, 'type' | 'flavor'> & { - uuid?: string; - binary?: ArrayBufferLike; + uuid: string | undefined; + binary: ArrayBufferLike | undefined; } ): Promise { const uuid = options.uuid || `affine${nanoid(16)}`; @@ -481,7 +487,9 @@ export class YjsAdapter implements AsyncDatabaseAdapter { async getBlock(id: string): Promise { const block_instance = this.get_block_sync(id); - if (block_instance) return block_instance; + if (block_instance) { + return block_instance; + } const block = this._blocks.get(id); if (block && block.get('type') === BlockTypes.binary) { const binary = await this._binaries.get( @@ -540,7 +548,9 @@ export class YjsAdapter implements AsyncDatabaseAdapter { let uploaded: Promise | undefined; if (!block.size) { const content = item.content[INTO_INNER](); - if (!content) return reject(); + if (!content) { + return reject(); + } const children = new YArray(); children.push(item.children); diff --git a/libs/datasource/jwt/src/adapter/yjs/listener.ts b/libs/datasource/jwt/src/yjs/listener.ts similarity index 98% rename from libs/datasource/jwt/src/adapter/yjs/listener.ts rename to libs/datasource/jwt/src/yjs/listener.ts index 36c203bbce..a109862b20 100644 --- a/libs/datasource/jwt/src/adapter/yjs/listener.ts +++ b/libs/datasource/jwt/src/yjs/listener.ts @@ -1,7 +1,8 @@ import { produce } from 'immer'; import { debounce } from 'ts-debounce'; import { YEvent } from 'yjs'; -import { BlockListener, ChangedStateKeys } from '../index'; + +import { BlockListener, ChangedStateKeys } from './types'; let listener_suspend = false; diff --git a/libs/datasource/jwt/src/adapter/yjs/operation.ts b/libs/datasource/jwt/src/yjs/operation.ts similarity index 93% rename from libs/datasource/jwt/src/adapter/yjs/operation.ts rename to libs/datasource/jwt/src/yjs/operation.ts index a8dfdaffa4..8d1bac4723 100644 --- a/libs/datasource/jwt/src/adapter/yjs/operation.ts +++ b/libs/datasource/jwt/src/yjs/operation.ts @@ -6,6 +6,7 @@ import { Text as YText, } from 'yjs'; +import { ChildrenListenerHandler, ContentListenerHandler } from './listener'; import { ArrayOperation, BaseTypes, @@ -16,21 +17,29 @@ import { Operable, TextOperation, TextToken, -} from '../index'; -import { ChildrenListenerHandler, ContentListenerHandler } from './listener'; +} from './types'; const INTO_INNER = Symbol('INTO_INNER'); export const DO_NOT_USE_THIS_OR_YOU_WILL_BE_FIRED_SYMBOL_INTO_INNER: typeof INTO_INNER = INTO_INNER; -function auto_get(root: ContentOperation, key: string): unknown | undefined { +function auto_get( + root: ContentOperation, + key: string | undefined +): unknown | undefined { const array = root.asArray(); - if (array && !Number.isNaN(Number(key))) return array.get(Number(key)); + if (array && !Number.isNaN(Number(key))) { + return array.get(Number(key)); + } const map = root.asMap(); - if (map) return map.get(key); + if (map && key) { + return map.get(key); + } const text = root.asText(); - if (text) return text.toString(); + if (text) { + return text.toString(); + } console.error('auto_get unknown root', root, key); return undefined; } @@ -150,7 +159,9 @@ export class YjsContentOperation implements ContentOperation { if (root instanceof YjsContentOperation) { if (path.length === 1) { const [key] = path; - if (key) return auto_set(root, key, data); + if (key) { + return auto_set(root, key, data); + } console.error('autoSet unknown path', root, path, data); return; } @@ -191,6 +202,7 @@ export class YjsContentOperation implements ContentOperation { } // eslint-disable-next-line @typescript-eslint/naming-convention + // @ts-ignore private toJSON() { return this._content.toJSON(); } @@ -283,7 +295,9 @@ class YjsArrayOperation get(index: number): Operable | undefined { const content = this._arrayContent.get(index); - if (content) return this.to_operable(content); + if (content) { + return this.to_operable(content); + } return undefined; } @@ -368,7 +382,9 @@ class YjsMapOperation set(key: string, value: Operable): void { if (value instanceof YjsContentOperation) { const content = value[INTO_INNER](); - if (content) this._mapContent.set(key, content as unknown as T); + if (content) { + this._mapContent.set(key, content as unknown as T); + } } else { this._mapContent.set(key, value as T); } @@ -376,7 +392,9 @@ class YjsMapOperation get(key: string): Operable | undefined { const content = this._mapContent.get(key); - if (content) return this.to_operable(content); + if (content) { + return this.to_operable(content); + } return undefined; } diff --git a/libs/datasource/jwt/src/adapter/yjs/provider.ts b/libs/datasource/jwt/src/yjs/provider.ts similarity index 97% rename from libs/datasource/jwt/src/adapter/yjs/provider.ts rename to libs/datasource/jwt/src/yjs/provider.ts index ba1835cc52..99a09fd69c 100644 --- a/libs/datasource/jwt/src/adapter/yjs/provider.ts +++ b/libs/datasource/jwt/src/yjs/provider.ts @@ -7,13 +7,13 @@ import { WebsocketProvider, } from '@toeverything/datasource/jwt-rpc'; -import { Connectivity } from '../../adapter'; -import { BucketBackend } from '../../types'; +import { BucketBackend } from '../types'; +import { Connectivity } from './types'; type YjsDefaultInstances = { awareness: Awareness; doc: Doc; - token?: string; + token?: string | undefined; workspace: string; emitState: (connectivity: Connectivity) => void; }; diff --git a/libs/datasource/jwt/src/adapter/index.ts b/libs/datasource/jwt/src/yjs/types.ts similarity index 97% rename from libs/datasource/jwt/src/adapter/index.ts rename to libs/datasource/jwt/src/yjs/types.ts index 2d7176e6be..b23c685e5c 100644 --- a/libs/datasource/jwt/src/adapter/index.ts +++ b/libs/datasource/jwt/src/yjs/types.ts @@ -139,8 +139,8 @@ interface AsyncDatabaseAdapter { reload(): void; createBlock( options: Pick, 'type' | 'flavor'> & { - binary?: ArrayBuffer; - uuid?: string; + binary: ArrayBuffer | undefined; + uuid: string | undefined; } ): Promise>; getBlock(id: string): Promise | undefined>; @@ -184,8 +184,6 @@ export const getDataExporter = () => { return { importData, exportData, hasExporter, installExporter }; }; -export { YjsAdapter } from './yjs'; -export type { YjsContentOperation, YjsInitOptions } from './yjs'; export type { AsyncDatabaseAdapter, BlockPosition, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 802d964374..e9f182f211 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -184,7 +184,7 @@ importers: yjs: ^13.5.41 dependencies: authing-js-sdk: 4.23.35 - firebase-admin: 11.0.1_@firebase+app-types@0.7.0 + firebase-admin: 11.0.1 lib0: 0.2.52 lru-cache: 7.13.2 nanoid: 4.0.0 @@ -566,6 +566,9 @@ importers: dependencies: ffc-js-client-side-sdk: 1.1.5 + libs/datasource/jwst/pkg: + specifiers: {} + libs/datasource/jwt: specifiers: '@types/debug': ^4.1.7 @@ -583,7 +586,7 @@ importers: idb-keyval: ^6.2.0 immer: ^9.0.15 lib0: ^0.2.52 - lru-cache: ^7.13.2 + lru-cache: ^7.14.0 nanoid: ^4.0.0 sha3: ^2.1.4 sift: ^16.0.0 @@ -614,7 +617,7 @@ importers: file-selector: 0.6.0 flexsearch: 0.7.21 lib0: 0.2.52 - lru-cache: 7.13.2 + lru-cache: 7.14.0 ts-debounce: 4.0.0 libs/datasource/jwt-rpc: @@ -3180,6 +3183,15 @@ packages: - utf-8-validate dev: true + /@firebase/auth-interop-types/0.1.6_@firebase+util@1.6.3: + resolution: {integrity: sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g==} + peerDependencies: + '@firebase/app-types': 0.x + '@firebase/util': 1.x + dependencies: + '@firebase/util': 1.6.3 + dev: false + /@firebase/auth-interop-types/0.1.6_pbfwexsq7uf6mrzcwnikj3g37m: resolution: {integrity: sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g==} peerDependencies: @@ -3188,6 +3200,7 @@ packages: dependencies: '@firebase/app-types': 0.7.0 '@firebase/util': 1.6.3 + dev: true /@firebase/auth-types/0.11.0_pbfwexsq7uf6mrzcwnikj3g37m: resolution: {integrity: sha512-q7Bt6cx+ySj9elQHTsKulwk3+qDezhzRBFC9zlQ1BjgMueUOnGMcvqmU0zuKlQ4RhLSH7MNAdBV2znVaoN3Vxw==} @@ -3223,6 +3236,19 @@ packages: '@firebase/util': 1.6.3 tslib: 2.4.0 + /@firebase/database-compat/0.2.4: + resolution: {integrity: sha512-VtsGixO5mTjNMJn6PwxAJEAR70fj+3blCXIdQKel3q+eYGZAfdqxox1+tzZDnf9NWBJpaOgAHPk3JVDxEo9NFQ==} + dependencies: + '@firebase/component': 0.5.17 + '@firebase/database': 0.13.4 + '@firebase/database-types': 0.9.12 + '@firebase/logger': 0.3.3 + '@firebase/util': 1.6.3 + tslib: 2.4.0 + transitivePeerDependencies: + - '@firebase/app-types' + dev: false + /@firebase/database-compat/0.2.4_@firebase+app-types@0.7.0: resolution: {integrity: sha512-VtsGixO5mTjNMJn6PwxAJEAR70fj+3blCXIdQKel3q+eYGZAfdqxox1+tzZDnf9NWBJpaOgAHPk3JVDxEo9NFQ==} dependencies: @@ -3234,6 +3260,7 @@ packages: tslib: 2.4.0 transitivePeerDependencies: - '@firebase/app-types' + dev: true /@firebase/database-types/0.9.10: resolution: {integrity: sha512-2ji6nXRRsY+7hgU6zRhUtK0RmSjVWM71taI7Flgaw+BnopCo/lDF5HSwxp8z7LtiHlvQqeRA3Ozqx5VhlAbiKg==} @@ -3248,6 +3275,19 @@ packages: '@firebase/app-types': 0.7.0 '@firebase/util': 1.6.3 + /@firebase/database/0.13.4: + resolution: {integrity: sha512-NW7bOoiaC4sJCj6DY/m9xHoFNa0CK32YPMCh6FiMweLCDQbOZM8Ql/Kn6yyuxCb7K7ypz9eSbRlCWQJsJRQjhg==} + dependencies: + '@firebase/auth-interop-types': 0.1.6_@firebase+util@1.6.3 + '@firebase/component': 0.5.17 + '@firebase/logger': 0.3.3 + '@firebase/util': 1.6.3 + faye-websocket: 0.11.4 + tslib: 2.4.0 + transitivePeerDependencies: + - '@firebase/app-types' + dev: false + /@firebase/database/0.13.4_@firebase+app-types@0.7.0: resolution: {integrity: sha512-NW7bOoiaC4sJCj6DY/m9xHoFNa0CK32YPMCh6FiMweLCDQbOZM8Ql/Kn6yyuxCb7K7ypz9eSbRlCWQJsJRQjhg==} dependencies: @@ -3259,6 +3299,7 @@ packages: tslib: 2.4.0 transitivePeerDependencies: - '@firebase/app-types' + dev: true /@firebase/firestore-compat/0.1.23_53yvy43rwpg2c45kgeszsxtrca: resolution: {integrity: sha512-QfcuyMAavp//fQnjSfCEpnbWi7spIdKaXys1kOLu7395fLr+U6ykmto1HUMCSz8Yus9cEr/03Ujdi2SUl2GUAA==} @@ -10332,12 +10373,12 @@ packages: semver-regex: 2.0.0 dev: true - /firebase-admin/11.0.1_@firebase+app-types@0.7.0: + /firebase-admin/11.0.1: resolution: {integrity: sha512-rL3wlZbi2Kb/KJgcmj1YHlD4ZhfmhfgRO2YJialxAllm0tj1IQea878hHuBLGmv4DpbW9t9nLvX9kddNR2Y65Q==} engines: {node: '>=14'} dependencies: '@fastify/busboy': 1.1.0 - '@firebase/database-compat': 0.2.4_@firebase+app-types@0.7.0 + '@firebase/database-compat': 0.2.4 '@firebase/database-types': 0.9.10 '@types/node': 18.0.1 jsonwebtoken: 8.5.1 @@ -13573,6 +13614,12 @@ packages: /lru-cache/7.13.2: resolution: {integrity: sha512-VJL3nIpA79TodY/ctmZEfhASgqekbT574/c4j3jn4bKXbSCnTTCH/KltZyvL2GlV+tGSMtsWyem8DCX7qKTMBA==} engines: {node: '>=12'} + dev: false + + /lru-cache/7.14.0: + resolution: {integrity: sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==} + engines: {node: '>=12'} + dev: true /lru-memoizer/2.1.4: resolution: {integrity: sha512-IXAq50s4qwrOBrXJklY+KhgZF+5y98PDaNo0gi/v2KQBFLyWr+JyFvijZXkGKjQj/h9c0OwoE+JZbwUXce76hQ==} From 8a95f6e05b8bb463ff870ac7cbd3ae9aba54462d Mon Sep 17 00:00:00 2001 From: CJSS Date: Tue, 23 Aug 2022 17:38:19 +0800 Subject: [PATCH 46/58] Update README and documentation (#314) * Update README.md Introduction update * Update README.md Sections updated: Stars Getting Started * Update README.md License section updated * Rename CONTRIBUTING.md to docs/CONTRIBUTING.md Move CONTRIBUTING to docs folder. * Rename CODE_OF_CONDUCT.md to docs/CODE_OF_CONDUCT.md Move CODE_OF_CONDUCT to docs folder. * Update CONTRIBUTING.md Title error * Update README.md Table of contents removed Useful links added * Update README.md Create your story moved and updated * Update README.md Useful links - added communities (removed FAQ) * Update README.md Fixed contribution and code of conduct links * Update CONTRIBUTING.md * Update CONTRIBUTING.md Labels link update * Create types-of-contributions.md * Update types-of-contributions.md README link fixed * Update types-of-contributions.md Punctuation * Update README.md Update useful links - added descriptions * chore: format * chore: format Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com> Co-authored-by: Whitewater --- README.md | 119 +++++------------- CODE_OF_CONDUCT.md => docs/CODE_OF_CONDUCT.md | 0 CONTRIBUTING.md => docs/CONTRIBUTING.md | 12 +- docs/types-of-contributions.md | 31 +++++ 4 files changed, 70 insertions(+), 92 deletions(-) rename CODE_OF_CONDUCT.md => docs/CODE_OF_CONDUCT.md (100%) rename CONTRIBUTING.md => docs/CONTRIBUTING.md (84%) create mode 100644 docs/types-of-contributions.md diff --git a/README.md b/README.md index 19e0db1307..b2507efa5b 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,13 @@ AFFiNE.PRO
- The Next-Gen Knowledge Base to Replace Notion & Miro. + The Next-Gen Collaborative Knowledge Base

-Planning, Sorting and Creating all Together. Open-source, Privacy-First, and Free to use. +Open-source and privacy-first.
+A free replacement for Notion & Miro.

@@ -22,9 +23,10 @@ See https://github.com/all-?/all-contributors/issues/361#issuecomment-637166066 -[![affine.pro](https://img.shields.io/static/v1?label=live%20demo&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAhpJREFUWEdjZEACtnl3MxgY/0YzMjAaMzAwcCLLUYH9/T/D/7MM/5mXHp6kPANmHiOI4Zx9Xfg3C+tKBob/zlSwiAgjGPey/vkdvneq5luwA+zy7+yhn+Vwv+89NFHFhREU7IyM/6YT4WyqK/n/nymT0Tb/1mFGBkYbqptOhIH/Gf4fYbTLv/2NBgmOCOvBSr6DHPCfWNW0UEe2A2x1uRlakiXBbtpx6jND+7KXZLmPbAdURokzeJjxwi31rrzH8OX7P5IdQbYDtnUoMXBzMMEt7Fj2imH7qU/0cQBy8MNsPHL5K0P13Of0cQB68MNsJScaSI4CHk4mhq3tSnCf3n36k0FZmh3Mn7L+DcPqgx9ICgWSHeBpxsdQESUGtgRk+eqDH+H8O09/MiR3P6atA1qTJRlsdLnhPgYlPOQQCW96wPDi3R+iHUFSCKAHP8wydEeREg0kOQA9+JOgwR1qL8CQEygC9jWp0UCSA+aVysIT3JqDHxgmr38DtlRCiIVhZZ0CPNhB6QDkEGIA0Q4gZAkuxxFyBNEOQA7ml+/+MIQ1PUAxG1kelAhB6YMYQLQDCPmQUAjhcgxRDiDWcEKOxOYIohyQGyjCEGIvANaPLfhhBiNHA6hmBBXNhABRDgCV/aBQAAFQpYMrn4PUgNTCACiXEMoNRDmAkC8okR8UDhjYRumAN8sHvGMCSkAD2jUDOWDAO6ewbDQQ3XMAy/oxKownQR0AAAAASUVORK5CYII=&color=orange&message=โ†’)](https://affine.pro) +[![affine.pro](https://img.shields.io/static/v1?label=live%20demo&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAhpJREFUWEdjZEACtnl3MxgY/0YzMjAaMzAwcCLLUYH9/T/D/7MM/5mXHp6kPANmHiOI4Zx9Xfg3C+tKBob/zlSwiAgjGPey/vkdvneq5luwA+zy7+yhn+Vwv+89NFHFhREU7IyM/6YT4WyqK/n/nymT0Tb/1mFGBkYbqptOhIH/Gf4fYbTLv/2NBgmOCOvBSr6DHPCfWNW0UEe2A2x1uRlakiXBbtpx6jND+7KXZLmPbAdURokzeJjxwi31rrzH8OX7P5IdQbYDtnUoMXBzMMEt7Fj2imH7qU/0cQBy8MNsPHL5K0P13Of0cQB68MNsJScaSI4CHk4mhq3tSnCf3n36k0FZmh3Mn7L+DcPqgx9ICgWSHeBpxsdQESUGtgRk+eqDH+H8O09/MiR3P6atA1qTJRlsdLnhPgYlPOQQCW96wPDi3R+iHUFSCKAHP8wydEeREg0kOQA9+JOgwR1qL8CQEygC9jWp0UCSA+aVysIT3JqDHxgmr38DtlRCiIVhZZ0CPNhB6QDkEGIA0Q4gZAkuxxFyBNEOQA7ml+/+MIQ1PUAxG1kelAhB6YMYQLQDCPmQUAjhcgxRDiDWcEKOxOYIohyQGyjCEGIvANaPLfhhBiNHA6hmBBXNhABRDgCV/aBQAAFQpYMrn4PUgNTCACiXEMoNRDmAkC8okR8UDhjYRumAN8sHvGMCSkAD2jUDOWDAO6ewbDQQ3XMAy/oxKownQR0AAAAASUVORK5CYII=&color=orange&message=โ†’)](https://livedemo.affine.pro) [![stars](https://img.shields.io/github/stars/toeverything/AFFiNE.svg?style=flat&logo=github&colorB=red&label=stars)](https://github.com/toeverything/AFFiNE) [![All Contributors][all-contributors-badge]](#contributors) +
[![Node](https://img.shields.io/badge/node->=16.0-success)](https://www.typescriptlang.org/) [![React](https://img.shields.io/badge/TypeScript-4.7-3178c6)](https://www.typescriptlang.org/) [![React](https://img.shields.io/badge/React-18-61dafb)](https://reactjs.org/) @@ -35,11 +37,11 @@ See https://github.com/all-?/all-contributors/issues/361#issuecomment-637166066

  - +   - +   - +  

@@ -48,100 +50,53 @@ See https://github.com/all-?/all-contributors/issues/361#issuecomment-637166066

affine_screen

-# Stay Up-to-Date and Support Us +# :star: Support Us and Keep Updated :star: ![952cd7a5-70fe-48ab-b74f-23981d94d2c5](https://user-images.githubusercontent.com/79301703/182365526-df074c64-cee4-45f6-b8e0-b912f17332c6.gif) -# How to use +# Getting Started -

-๐Ÿฅณ๐Ÿฅณ๐Ÿฅณ Our web live demo is ready! ๐Ÿฅณ๐Ÿฅณ๐Ÿฅณ -

+[![affine.pro](https://img.shields.io/static/v1?label=Try%20it%20Online&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAhpJREFUWEdjZEACtnl3MxgY/0YzMjAaMzAwcCLLUYH9/T/D/7MM/5mXHp6kPANmHiOI4Zx9Xfg3C+tKBob/zlSwiAgjGPey/vkdvneq5luwA+zy7+yhn+Vwv+89NFHFhREU7IyM/6YT4WyqK/n/nymT0Tb/1mFGBkYbqptOhIH/Gf4fYbTLv/2NBgmOCOvBSr6DHPCfWNW0UEe2A2x1uRlakiXBbtpx6jND+7KXZLmPbAdURokzeJjxwi31rrzH8OX7P5IdQbYDtnUoMXBzMMEt7Fj2imH7qU/0cQBy8MNsPHL5K0P13Of0cQB68MNsJScaSI4CHk4mhq3tSnCf3n36k0FZmh3Mn7L+DcPqgx9ICgWSHeBpxsdQESUGtgRk+eqDH+H8O09/MiR3P6atA1qTJRlsdLnhPgYlPOQQCW96wPDi3R+iHUFSCKAHP8wydEeREg0kOQA9+JOgwR1qL8CQEygC9jWp0UCSA+aVysIT3JqDHxgmr38DtlRCiIVhZZ0CPNhB6QDkEGIA0Q4gZAkuxxFyBNEOQA7ml+/+MIQ1PUAxG1kelAhB6YMYQLQDCPmQUAjhcgxRDiDWcEKOxOYIohyQGyjCEGIvANaPLfhhBiNHA6hmBBXNhABRDgCV/aBQAAFQpYMrn4PUgNTCACiXEMoNRDmAkC8okR8UDhjYRumAN8sHvGMCSkAD2jUDOWDAO6ewbDQQ3XMAy/oxKownQR0AAAAASUVORK5CYII=&message=%E2%86%92&style=for-the-badge)](https://affine.pro) No installation or registration required! Head over to our website and try it out now. -

-Start to play with AFFiNE web version on our landing page: -

- -

- check_live_demo -

- -If you have experience in front-end development, you may wish to refer to our [documentation](https://docs.affine.pro/affine/basic-documentation/contribute-to-affine) to learn more about deploying your own version or contributing further to development. -Also, thanks to Lee who has made a [desktop build with Tauri](https://github.com/m1911star/affine-client) for you to try out. -Please notice that AFFiNE is still under Alpha stage and is not ready for production use. - -# Table of contents - -- [Stay Up-to-Date and Support Us](#stay-up-to-date-and-support-us) -- [How to Use](#how-to-use) -- [Table of contents](#table-of-contents) - - [Shape your page](#shape-your-page) - - [Plan your task](#plan-your-task) - - [Sort your knowledge](#sort-your-knowledge) - - [Create your story](#create-your-story) -- [Documentation](#documentation) - - [Getting Started with development](#getting-started-with-development) -- [Roadmap](#roadmap) -- [Releases](#releases) -- [Feature requests](#feature-requests) -- [FAQ](#faq) -- [The Philosophy of AFFiNE](#the-philosophy-of-affine) -- [Community](#community) -- [Contributors](#contributors) -- [Acknowledgments](#acknowledgments) -- [License](#license) - -## Shape your page - -![546163d6-4c39-4128-ae7f-55d59bc3b76b](https://user-images.githubusercontent.com/79301703/182365611-b0ba3690-21c0-4d9b-bfbc-0bc15da05aeb.gif) - -## Plan your task - -![41a7b3a4-32f2-4d18-ac6b-57d1e1fda753](https://user-images.githubusercontent.com/79301703/182366553-1f6558a7-f17b-4611-ab95-aea3ec997154.gif) - -## Sort your knowledge - -![c9e1ff46-cec2-411b-b89d-6727a5e6f6c3](https://user-images.githubusercontent.com/79301703/182366602-08e44d28-a031-4097-9904-52fb9b1e9e17.gif) +Want to deploy it yourself? AFFiNE can run just about anywhere. Check our +[documentation](#documentation) +for more information. +

+โš ๏ธ Please note that AFFiNE is still under active development and is not yet ready for production use. โš ๏ธ ## Create your story -We want your data always to be yours, without any sacrifice to your accessibility. Your data is always stored local first, yet we support real-time collaboration on a peer-to-peer basis. We don't think "privacy-first" is a good excuse for not supporting modern web features. -And when it comes to collaboration, these features are not just necessarily for teams -- you can take and insert pictures on your phone, edit them from your desktop, and then share them with your collaborators. -Affine is fully built with web technologies to ensure consistency and accessibility on Mac, Windows and Linux. The local file system support will be available when version 0.0.1beta is released. +There can be more than Notion and Miro. AFFiNE is a next-gen knowledge base that brings planning, sorting and creating all together. Privacy first, open-source, customizable and ready to use, built with web technologies to ensure consistency and accessibility on Mac, Windows and Linux. We want your data always to be yours, without any sacrifice to your accessibility. Your data is always stored local first, with full support for real-time collaboration through peer-to-peer technology. We don't think "privacy-first" is a good excuse for not supporting modern web features. +And when it comes to collaboration, these features are not just necessarily for teams - you can take and insert pictures on your phone, edit them from your desktop, and then share them with your collaborators. -# Documentation +### Shape your page -AFFiNE is not yet ready for production use. For installation, you may check how to build or deploy AFFiNE from our [quick-start](https://docs.affine.pro/affine/basic-documentation/contribute-to-affine/quick-start) guide. Alternatively, you can view our [full documentation](https://docs.affine.pro/affine/). +![546163d6-4c39-4128-ae7f-55d59bc3b76b](https://user-images.githubusercontent.com/79301703/182365611-b0ba3690-21c0-4d9b-bfbc-0bc15da05aeb.gif) -## Getting Started with development +### Plan your task -Please view the path Contribute-to-AFFiNE/Software-Contributions/Quick-Start in the documentation. +![41a7b3a4-32f2-4d18-ac6b-57d1e1fda753](https://user-images.githubusercontent.com/79301703/182366553-1f6558a7-f17b-4611-ab95-aea3ec997154.gif) -# Roadmap +### Sort your knowledge -Yes! Permanent storage, collaboration, stable release is planned! Check it [here](https://github.com/toeverything/AFFiNE/issues/293) +![c9e1ff46-cec2-411b-b89d-6727a5e6f6c3](https://user-images.githubusercontent.com/79301703/182366602-08e44d28-a031-4097-9904-52fb9b1e9e17.gif) -# Releases +# Useful Links -Get our latest [release notes](https://github.com/toeverything/AFFiNE/wiki) from here. +- [AFFiNE Documentation](https://docs.affine.pro/affine/) - More detailed documentation on how to use and develop with AFFiNE -# Feature requests +- [Feature Roadmap](https://github.com/toeverything/AFFiNE/issues/293) - Looking for a feature? It might already be planned for release - you can check here +- [Release Notes](https://github.com/toeverything/AFFiNE/wiki) - Find out what changes we are making and how we are improving AFFiNE -Please go to [feature requests](https://github.com/toeverything/AFFiNE/issues). +- [Contributing Guide](/docs/CONTRIBUTING.md) - Want to help improve AFFiNE? You might not even need to write a line of code. Find out how you can contribute. +- [Code of Conduct](/docs/CODE_OF_CONDUCT.md) - How we promote and maintain a harassment-free experience for everyone in our community. -# FAQ - -Get quick help on [Telegram](https://t.me/affineworkos) or [Discord](https://discord.gg/yz6tGVsf5p) and join our community of developers and contributors. - -Our latest news can be found on [Twitter](https://twitter.com/AffineOfficial), [Medium](https://medium.com/@affineworkos) and the [AFFiNE Blog](https://blog.affine.pro/). +- AFFiNE Communities: [Discord](https://discord.gg/yz6tGVsf5p) | [Telegram](https://t.me/affineworkos) | [Twitter](https://twitter.com/AffineOfficial) | + [Medium](https://medium.com/@affineworkos) | [AFFiNE Blog](https://blog.affine.pro) # Contact Us -You may contact us by emailing to: contact@toeverything.info +Feel free to send us an email: contact@toeverything.info # The Philosophy of AFFiNE @@ -186,12 +141,6 @@ We would also like to give thanks to open-source projects that make affine possi Thanks a lot to the community for providing such powerful and simple libraries, so that we can focus more on the implementation of the product logic, and we hope that in the future our projects will also provide a more easy-to-use knowledge base for everyone. -# Community - -For help, discussion about best practices, or any other conversation that would benefit from being searchable: - -[Discuss AFFiNE on GitHub](https://github.com/toeverything/AFFiNE/discussions) - # Contributors @@ -250,4 +199,4 @@ For help, discussion about best practices, or any other conversation that would AFFiNE is distributed under the terms of MIT license. -See LICENSE for details. +See [LICENSE](/LICENSE) for details. diff --git a/CODE_OF_CONDUCT.md b/docs/CODE_OF_CONDUCT.md similarity index 100% rename from CODE_OF_CONDUCT.md rename to docs/CODE_OF_CONDUCT.md diff --git a/CONTRIBUTING.md b/docs/CONTRIBUTING.md similarity index 84% rename from CONTRIBUTING.md rename to docs/CONTRIBUTING.md index 7b7b63a1a5..cd21902653 100644 --- a/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -1,4 +1,4 @@ -# Welcome to ourcontributing guide +# Welcome to our contributing guide Thank you for investing your time in contributing to our project! Any contribution you make will be reflected on our GitHub :sparkles:. @@ -10,7 +10,7 @@ Use the table of contents icon on the top left corner of this document to get to ## New contributor guide -To get an overview of the project, read the [README](README.md). Here are some resources to help you get started with open source contributions: +To get an overview of the project, read the [README](../README.md). Here are some resources to help you get started with open source contributions: - [Finding ways to contribute to open source on GitHub](https://docs.github.com/en/get-started/exploring-projects-on-github/finding-ways-to-contribute-to-open-source-on-github) - [Set up Git](https://docs.github.com/en/get-started/quickstart/set-up-git) @@ -19,19 +19,17 @@ To get an overview of the project, read the [README](README.md). Here are some r ## Getting started -To navigate our codebase with confidence, see [the introduction to working in the docs repository](/contributing/working-in-docs-repository.md) :confetti_ball:. For more information on how we write our markdown files, see [the GitHub Markdown reference](contributing/content-markup-reference.md). - -Check to see what [types of contributions](/contributing/types-of-contributions.md) we accept before making changes. Some of them don't even require writing a single line of code :sparkles:. +Check to see what [types of contributions](/types-of-contributions.md) we accept before making changes. Some of them don't even require writing a single line of code :sparkles:. ### Issues -#### Create a new issue +#### Create a new issue or feature request If you spot a problem, [search if an issue already exists](https://docs.github.com/en/github/searching-for-information-on-github/searching-on-github/searching-issues-and-pull-requests#search-by-the-title-body-or-comments). If a related issue doesn't exist, you can open a new issue using a relevant [issue form](https://github.com/toeverything/AFFiNE/issues/new/choose). #### Solve an issue -Scan through our [existing issues](https://github.com/toeverything/AFFiNE/issues) to find one that interests you. You can narrow down the search using `labels` as filters. See [Labels](/contributing/how-to-use-labels.md) for more information. As a general rule, we donโ€™t assign issues to anyone. If you find an issue to work on, you are welcome to open a PR with a fix. +Scan through our [existing issues](https://github.com/toeverything/AFFiNE/issues) to find one that interests you. You can narrow down the search using `labels` as filters. See our [Labels](https://github.com/toeverything/AFFiNE/labels) for more information. As a general rule, we donโ€™t assign issues to anyone. If you find an issue to work on, you are welcome to open a PR with a fix. ### Make Changes diff --git a/docs/types-of-contributions.md b/docs/types-of-contributions.md new file mode 100644 index 0000000000..fd448200e9 --- /dev/null +++ b/docs/types-of-contributions.md @@ -0,0 +1,31 @@ +# Types of contributions :memo: + +You can contribute to AFFiNE in several ways. This repo is a place to discuss and collaborate on AFFiNE! + +### :mega: Discussions + +Discussions are where we have conversations. + +If you'd like help troubleshooting a docs PR you're working on, have a great new idea, or want to share something amazing you've learned in our docs, join us in [discussions](https://github.com/toeverything/AFFiNE/discussions). + +### :lady_beetle: Issues + +[Issues](https://docs.github.com/en/github/managing-your-work-on-github/about-issues) are used to track tasks that contributors can help with. If an issue has a triage label, we haven't reviewed it yet, and you shouldn't begin work on it. + +If you've found something in the content or the website that should be updated, search open issues to see if someone else has reported the same thing. If it's something new, open an issue using a [template](https://github.com/toeverything/AFFiNE/issues/new/choose). We'll use the issue to have a conversation about the problem you want to fix. + +### :hammer_and_wrench: Pull requests + +A [pull request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests) is a way to suggest changes in our repository. When we merge those changes, they should be deployed to the live site within 24 hours. :earth_africa: +You can [create a new pull request](https://github.com/toeverything/AFFiNE/compare) and view [current pull requests](https://github.com/toeverything/AFFiNE/pulls). + +### :question: Support + +We are a small team working hard to keep up with the documentation demands of a continuously changing product. +You may be able to find additional help and information on our social media platforms and groups - the links to these can be found in our [README](../README.md). + +### :earth_asia: Translations + +AFFiNE is internationalized and available in multiple languages. The source content in this repository is written in English. We integrate with an external localization platform to work with the community in localizing the English content. + +**We do not currently offer this feature**, but we hope to in the future. From 595a29db740769bab14fa6495ebaf27466c877a0 Mon Sep 17 00:00:00 2001 From: CJSS Date: Tue, 23 Aug 2022 20:30:47 +0800 Subject: [PATCH 47/58] Update CONTRIBUTING.md (#316) Fixed types of contributions link --- docs/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index cd21902653..94806e00f8 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -19,7 +19,7 @@ To get an overview of the project, read the [README](../README.md). Here are som ## Getting started -Check to see what [types of contributions](/types-of-contributions.md) we accept before making changes. Some of them don't even require writing a single line of code :sparkles:. +Check to see what [types of contributions](types-of-contributions.md) we accept before making changes. Some of them don't even require writing a single line of code :sparkles:. ### Issues From a6848dda51ae409ffbd8fe1c550db1904f906031 Mon Sep 17 00:00:00 2001 From: Felix Yan Date: Tue, 23 Aug 2022 21:05:20 +0300 Subject: [PATCH 48/58] Correct a typo in README (#317) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b2507efa5b..8789712501 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,7 @@ That's why we are making AFFiNE. Some of the most important features are: - Data is always stored locally by default - CRDTs are applied so that peer-to-peer collaboration is possible. -We appreciate the ideas of Monday, Airtable, and Notion databases. They have inspired us and shaped our product, helping us get it right when it comes to task management. But we also do things differently. We don't like doing things again and again. It's easy to set a todo with Markdown, but then why do you need to repeat and recreate data for a kanban or other databases. This is the power of AFFiNE. With AFFiNE, every block group has infinite views, for you to keep your single source of data, a signle source of truth. +We appreciate the ideas of Monday, Airtable, and Notion databases. They have inspired us and shaped our product, helping us get it right when it comes to task management. But we also do things differently. We don't like doing things again and again. It's easy to set a todo with Markdown, but then why do you need to repeat and recreate data for a kanban or other databases. This is the power of AFFiNE. With AFFiNE, every block group has infinite views, for you to keep your single source of data, a single source of truth. We would like to give special thanks to the innovators and pioneers who greatly inspired us: From eb02e62a0e0b17e58104bfa5c3353837fc1e17d5 Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Wed, 24 Aug 2022 01:20:52 +0800 Subject: [PATCH 49/58] feat: new useBlockRender API --- .../editor-core/src/render-block/Context.tsx | 32 ++++ .../src/render-block/RenderBlock.tsx | 9 +- .../src/render-block/RenderBlockChildren.tsx | 35 +++- .../src/render-block/RenderKanbanBlock.tsx | 56 ++++++ .../src/render-block/WithTreeViewChildren.tsx | 181 ++++++++++++++++++ .../editor-core/src/render-block/index.ts | 2 + 6 files changed, 307 insertions(+), 8 deletions(-) create mode 100644 libs/components/editor-core/src/render-block/Context.tsx create mode 100644 libs/components/editor-core/src/render-block/RenderKanbanBlock.tsx create mode 100644 libs/components/editor-core/src/render-block/WithTreeViewChildren.tsx diff --git a/libs/components/editor-core/src/render-block/Context.tsx b/libs/components/editor-core/src/render-block/Context.tsx new file mode 100644 index 0000000000..8a1b68465c --- /dev/null +++ b/libs/components/editor-core/src/render-block/Context.tsx @@ -0,0 +1,32 @@ +import { genErrorObj } from '@toeverything/utils'; +import { createContext, PropsWithChildren, useContext } from 'react'; +import { RenderBlockProps } from './RenderBlock'; + +type BlockRenderProps = { + blockRender: (args: RenderBlockProps) => JSX.Element | null; +}; + +export const BlockRenderContext = createContext( + genErrorObj( + 'Failed to get BlockChildrenContext! The context only can use under the "render-root"' + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ) as any +); + +export const BlockRenderProvider = ({ + blockRender, + children, +}: PropsWithChildren) => { + return ( + + {children} + + ); +}; + +export const useBlockRender = () => { + const { blockRender } = useContext(BlockRenderContext); + return { + BlockRender: blockRender, + }; +}; diff --git a/libs/components/editor-core/src/render-block/RenderBlock.tsx b/libs/components/editor-core/src/render-block/RenderBlock.tsx index 0a1531a709..1dc945e870 100644 --- a/libs/components/editor-core/src/render-block/RenderBlock.tsx +++ b/libs/components/editor-core/src/render-block/RenderBlock.tsx @@ -4,7 +4,12 @@ import { useCallback, useMemo } from 'react'; import { useEditor } from '../Contexts'; import { useBlock } from '../hooks'; -interface RenderBlockProps { +/** + * Render nothing + */ +export const NullBlockRender = (): null => null; + +export interface RenderBlockProps { blockId: string; hasContainer?: boolean; } @@ -29,7 +34,7 @@ export function RenderBlock({ if (block?.type) { return editor.getView(block.type).View; } - return () => null; + return (): null => null; }, [editor, block?.type]); if (!block) { diff --git a/libs/components/editor-core/src/render-block/RenderBlockChildren.tsx b/libs/components/editor-core/src/render-block/RenderBlockChildren.tsx index 4c87ccc8e8..d79d0cd002 100644 --- a/libs/components/editor-core/src/render-block/RenderBlockChildren.tsx +++ b/libs/components/editor-core/src/render-block/RenderBlockChildren.tsx @@ -1,16 +1,39 @@ +import { styled } from '@toeverything/components/ui'; import type { AsyncBlock } from '../editor'; -import { RenderBlock } from './RenderBlock'; +import { useBlockRender } from './Context'; +import { NullBlockRender } from './RenderBlock'; -interface RenderChildrenProps { +export interface RenderChildrenProps { block: AsyncBlock; + indent?: boolean; } -export const RenderBlockChildren = ({ block }: RenderChildrenProps) => { +export const RenderBlockChildren = ({ + block, + indent = true, +}: RenderChildrenProps) => { + const { BlockRender } = useBlockRender(); + if (BlockRender === NullBlockRender) { + return null; + } + return block.childrenIds.length ? ( - <> + {block.childrenIds.map(childId => { - return ; + return ; })} - + ) : null; }; + +/** + * Indent rendering child nodes + */ +const StyledIdentWrapper = styled('div')<{ indent?: boolean }>( + ({ indent }) => ({ + display: 'flex', + flexDirection: 'column', + // TODO: marginLeft should use theme provided by styled + ...(indent && { marginLeft: '30px' }), + }) +); diff --git a/libs/components/editor-core/src/render-block/RenderKanbanBlock.tsx b/libs/components/editor-core/src/render-block/RenderKanbanBlock.tsx new file mode 100644 index 0000000000..54f9e2276e --- /dev/null +++ b/libs/components/editor-core/src/render-block/RenderKanbanBlock.tsx @@ -0,0 +1,56 @@ +import { styled } from '@toeverything/components/ui'; +import { useBlock } from '../hooks'; +import { BlockRenderProvider } from './Context'; +import { NullBlockRender, RenderBlock, RenderBlockProps } from './RenderBlock'; + +/** + * Render block without children. + */ +const BlockWithoutChildrenRender = ({ blockId }: RenderBlockProps) => { + return ( + + + + ); +}; + +/** + * Render a block, but only one level of children. + */ +const OneLevelBlockRender = ({ blockId }: RenderBlockProps) => { + return ( + + + + ); +}; + +export const KanbanBlockRender = ({ blockId }: RenderBlockProps) => { + const { block } = useBlock(blockId); + + if (!block) { + return ( + + + + ); + } + + return ( + + + {block?.childrenIds.map(childId => ( + + + + ))} + + ); +}; + +const StyledBorder = styled('div')({ + border: '1px solid #E0E6EB', + borderRadius: '5px', + margin: '4px', + padding: '0 4px', +}); diff --git a/libs/components/editor-core/src/render-block/WithTreeViewChildren.tsx b/libs/components/editor-core/src/render-block/WithTreeViewChildren.tsx new file mode 100644 index 0000000000..8c3642ef6d --- /dev/null +++ b/libs/components/editor-core/src/render-block/WithTreeViewChildren.tsx @@ -0,0 +1,181 @@ +import { styled } from '@toeverything/components/ui'; +import type { + ComponentPropsWithoutRef, + ComponentPropsWithRef, + CSSProperties, + ReactElement, +} from 'react'; +import { forwardRef } from 'react'; +import { CreateView } from '../editor'; +import { useBlockRender } from './Context'; +import { NullBlockRender } from './RenderBlock'; + +type WithChildrenConfig = { + indent: CSSProperties['marginLeft']; +}; + +const defaultConfig: WithChildrenConfig = { + indent: '30px', +}; + +const TreeView = forwardRef< + HTMLDivElement, + { lastItem?: boolean } & ComponentPropsWithRef<'div'> +>(({ lastItem = false, children, onClick, ...restProps }, ref) => { + return ( + + + + + {lastItem && } + + {/* maybe need a child wrapper */} + {children} + + ); +}); + +const CollapsedNode = forwardRef< + HTMLDivElement, + ComponentPropsWithoutRef<'div'> +>((props, ref) => { + return ( + + ยทยทยท + + ); +}); + +/** + * Indent rendering child nodes + */ +export const withTreeViewChildren = ( + creator: (props: CreateView) => ReactElement, + customConfig: Partial = {} +) => { + const config = { + ...defaultConfig, + ...customConfig, + }; + + return (props: CreateView) => { + const { block } = props; + const { BlockRender } = useBlockRender(); + const collapsed = block.getProperty('collapsed')?.value; + const childrenIds = block.childrenIds; + const showChildren = + !collapsed && + childrenIds.length > 0 && + BlockRender !== NullBlockRender; + + const handleCollapse = () => { + block.setProperty('collapsed', { value: true }); + }; + + const handleExpand = () => { + block.setProperty('collapsed', { value: false }); + }; + + return ( + <> + {creator(props)} + + {collapsed && ( + + )} + {showChildren && + childrenIds.map((childId, idx) => { + return ( + + + + ); + })} + + ); + }; +}; + +const TREE_COLOR = '#D5DFE6'; +// adjust left and right margins of the the tree line +const TREE_LINE_LEFT_OFFSET = '-16px'; +// determine the position of the horizontal line by the type of the item +const TREE_LINE_TOP_OFFSET = '20px'; // '50%' +const TREE_LINE_WIDTH = '12px'; + +const TreeWrapper = styled('div')({ + position: 'relative', + display: 'flex', +}); + +const StyledTreeView = styled('div')({ + position: 'absolute', + left: TREE_LINE_LEFT_OFFSET, + height: '100%', +}); + +const Line = styled('div')({ + position: 'absolute', + cursor: 'pointer', + backgroundColor: TREE_COLOR, + // somehow tldraw would override this + boxSizing: 'content-box!important' as any, + // See [Can I add background color only for padding?](https://stackoverflow.com/questions/14628601/can-i-add-background-color-only-for-padding) + backgroundClip: 'content-box', + backgroundOrigin: 'content-box', + // Increase click hot spot + padding: '10px', +}); + +const VerticalLine = styled(Line)<{ last: boolean }>(({ last }) => ({ + width: '1px', + height: last ? TREE_LINE_TOP_OFFSET : '100%', + paddingTop: 0, + paddingBottom: 0, + transform: 'translate(-50%, 0)', + + opacity: last ? 0 : 'unset', +})); + +const HorizontalLine = styled(Line)<{ last: boolean }>(({ last }) => ({ + width: TREE_LINE_WIDTH, + height: '1px', + paddingLeft: 0, + paddingRight: 0, + top: TREE_LINE_TOP_OFFSET, + transform: 'translate(0, -50%)', + opacity: last ? 0 : 'unset', +})); + +const Collapsed = styled('div')({ + cursor: 'pointer', + display: 'inline-block', + color: '#98ACBD', + padding: '8px', +}); + +const LastItemRadius = styled('div')({ + boxSizing: 'content-box', + position: 'absolute', + left: '-0.5px', + top: 0, + height: TREE_LINE_TOP_OFFSET, + bottom: '50%', + width: TREE_LINE_WIDTH, + borderWidth: '1px', + borderStyle: 'solid', + borderLeftColor: TREE_COLOR, + borderBottomColor: TREE_COLOR, + borderTop: 'none', + borderRight: 'none', + borderRadius: '0 0 0 3px', + pointerEvents: 'none', +}); diff --git a/libs/components/editor-core/src/render-block/index.ts b/libs/components/editor-core/src/render-block/index.ts index 820bac8b57..0d5c809c4c 100644 --- a/libs/components/editor-core/src/render-block/index.ts +++ b/libs/components/editor-core/src/render-block/index.ts @@ -1,2 +1,4 @@ +export { BlockRenderProvider, useBlockRender } from './Context'; export * from './RenderBlock'; export * from './RenderBlockChildren'; +export { withTreeViewChildren } from './WithTreeViewChildren'; From dd24711f21ef6097c99edade1a40202b23802374 Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Wed, 24 Aug 2022 01:25:25 +0800 Subject: [PATCH 50/58] refactor: update editor --- libs/components/affine-editor/src/Editor.tsx | 5 +- libs/components/editor-core/src/Contexts.tsx | 28 +++++-- .../components/editor-core/src/RenderRoot.tsx | 82 +++++++++---------- libs/components/editor-core/src/index.ts | 27 +++--- .../editor-core/src/kanban/Context.tsx | 10 ++- 5 files changed, 81 insertions(+), 71 deletions(-) diff --git a/libs/components/affine-editor/src/Editor.tsx b/libs/components/affine-editor/src/Editor.tsx index c280bea984..f1edb2ce74 100644 --- a/libs/components/affine-editor/src/Editor.tsx +++ b/libs/components/affine-editor/src/Editor.tsx @@ -1,7 +1,6 @@ import { forwardRef, useEffect, useImperativeHandle, useRef } from 'react'; import { - RenderBlock, RenderRoot, type BlockEditor, } from '@toeverything/components/editor-core'; @@ -88,9 +87,7 @@ export const AffineEditor = forwardRef( editor={editor} editorElement={AffineEditor as any} scrollBlank={scrollBlank} - > - - + /> ); } ); diff --git a/libs/components/editor-core/src/Contexts.tsx b/libs/components/editor-core/src/Contexts.tsx index 418fe0e8b4..0b7c7d2270 100644 --- a/libs/components/editor-core/src/Contexts.tsx +++ b/libs/components/editor-core/src/Contexts.tsx @@ -1,22 +1,34 @@ -import { createContext, useContext } from 'react'; -import type { BlockEditor, AsyncBlock } from './editor'; import { genErrorObj } from '@toeverything/utils'; +import { createContext, PropsWithChildren, useContext } from 'react'; +import type { AsyncBlock, BlockEditor } from './editor'; -const RootContext = createContext<{ +type EditorProps = { editor: BlockEditor; // TODO: Temporary fix, dependencies in the new architecture are bottom-up, editors do not need to be passed down from the top editorElement: () => JSX.Element; -}>( +}; + +const EditorContext = createContext( genErrorObj( - 'Failed to get context! The context only can use under the "render-root"' + 'Failed to get EditorContext! The context only can use under the "render-root"' // eslint-disable-next-line @typescript-eslint/no-explicit-any ) as any ); -export const EditorProvider = RootContext.Provider; - export const useEditor = () => { - return useContext(RootContext); + return useContext(EditorContext); +}; + +export const EditorProvider = ({ + editor, + editorElement, + children, +}: PropsWithChildren) => { + return ( + + {children} + + ); }; /** diff --git a/libs/components/editor-core/src/RenderRoot.tsx b/libs/components/editor-core/src/RenderRoot.tsx index cbafd3ea75..c1f1dd0d49 100644 --- a/libs/components/editor-core/src/RenderRoot.tsx +++ b/libs/components/editor-core/src/RenderRoot.tsx @@ -4,12 +4,12 @@ import { services, type ReturnUnobserve, } from '@toeverything/datasource/db-service'; -import type { PropsWithChildren } from 'react'; import React, { useCallback, useEffect, useRef, useState } from 'react'; import { EditorProvider } from './Contexts'; import type { BlockEditor } from './editor'; import { useIsOnDrag } from './hooks'; import { addNewGroup, appendNewGroup } from './recast-block'; +import { BlockRenderProvider, RenderBlock } from './render-block'; import { SelectionRect, SelectionRef } from './Selection'; interface RenderRootProps { @@ -24,11 +24,7 @@ interface RenderRootProps { const MAX_PAGE_WIDTH = 5000; export const MIN_PAGE_WIDTH = 1480; -export const RenderRoot = ({ - editor, - editorElement, - children, -}: PropsWithChildren) => { +export const RenderRoot = ({ editor, editorElement }: RenderRootProps) => { const selectionRef = useRef(null); const triggeredBySelect = useRef(false); const [pageWidth, setPageWidth] = useState(MIN_PAGE_WIDTH); @@ -158,39 +154,43 @@ export const RenderRoot = ({ }; return ( - - { - if (ref != null && ref !== editor.container) { - editor.container = ref; - editor.getHooks().render(); - } - }} - onMouseMove={onMouseMove} - onMouseDown={onMouseDown} - onMouseUp={onMouseUp} - onMouseLeave={onMouseLeave} - onMouseOut={onMouseOut} - onContextMenu={onContextmenu} - onKeyDown={onKeyDown} - onKeyDownCapture={onKeyDownCapture} - onKeyUp={onKeyUp} - onDragOver={onDragOver} - onDragLeave={onDragLeave} - onDragOverCapture={onDragOverCapture} - onDragEnd={onDragEnd} - onDrop={onDrop} - isOnDrag={isOnDrag} - > - - {children} - - {/** TODO: remove selectionManager insert */} - {editor && } - {editor.isEdgeless ? null : } - {patchedNodes} - + + + { + if (ref != null && ref !== editor.container) { + editor.container = ref; + editor.getHooks().render(); + } + }} + onMouseMove={onMouseMove} + onMouseDown={onMouseDown} + onMouseUp={onMouseUp} + onMouseLeave={onMouseLeave} + onMouseOut={onMouseOut} + onContextMenu={onContextmenu} + onKeyDown={onKeyDown} + onKeyDownCapture={onKeyDownCapture} + onKeyUp={onKeyUp} + onDragOver={onDragOver} + onDragLeave={onDragLeave} + onDragOverCapture={onDragOverCapture} + onDragEnd={onDragEnd} + onDrop={onDrop} + isOnDrag={isOnDrag} + > + + + + {/** TODO: remove selectionManager insert */} + {editor && ( + + )} + {editor.isEdgeless ? null : } + {patchedNodes} + + ); }; @@ -251,7 +251,7 @@ function ScrollBlank({ editor }: { editor: BlockEditor }) { ); return ( - - {children} - + + + {children} + + ); }; From a4dc7bf127d2c2905527919dc01fd06e9324534e Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Wed, 24 Aug 2022 01:35:04 +0800 Subject: [PATCH 51/58] refactor: update block --- .../src/blocks/bullet/BulletView.tsx | 27 +- .../editor-blocks/src/blocks/bullet/index.ts | 14 +- .../src/blocks/grid-item/GridItemRender.tsx | 5 +- .../editor-blocks/src/blocks/grid/Grid.tsx | 17 +- .../src/blocks/group/ScenePage.tsx | 2 +- .../blocks/group/scene-kanban/CardItem.tsx | 5 +- .../src/blocks/numbered/NumberedView.tsx | 17 +- .../src/blocks/numbered/index.ts | 11 +- .../src/blocks/text/TextView.tsx | 5 +- .../src/blocks/todo/TodoView.tsx | 62 +++-- .../editor-blocks/src/blocks/todo/index.ts | 16 +- .../BlockContainer/BlockContainer.tsx | 2 +- .../IndentWrapper/IndentWrapper.tsx | 17 -- .../src/components/IndentWrapper/index.ts | 1 - .../source-view/format-url/youtube.ts | 1 + .../src/utils/WithTreeViewChildren.tsx | 236 ------------------ .../src/render-block/RenderBlock.tsx | 1 + 17 files changed, 96 insertions(+), 343 deletions(-) delete mode 100644 libs/components/editor-blocks/src/components/IndentWrapper/IndentWrapper.tsx delete mode 100644 libs/components/editor-blocks/src/components/IndentWrapper/index.ts delete mode 100644 libs/components/editor-blocks/src/utils/WithTreeViewChildren.tsx diff --git a/libs/components/editor-blocks/src/blocks/bullet/BulletView.tsx b/libs/components/editor-blocks/src/blocks/bullet/BulletView.tsx index 9f77eda6cb..b2f76e46f9 100644 --- a/libs/components/editor-blocks/src/blocks/bullet/BulletView.tsx +++ b/libs/components/editor-blocks/src/blocks/bullet/BulletView.tsx @@ -1,29 +1,28 @@ import type { TextProps } from '@toeverything/components/common'; import { ContentColumnValue, - services, Protocol, + services, } from '@toeverything/datasource/db-service'; import { type CreateView } from '@toeverything/framework/virgo'; import { useEffect, useRef, useState } from 'react'; +import { + BlockPendantProvider, + RenderBlockChildren, + supportChildren, + useOnSelect, +} from '@toeverything/components/editor-core'; +import { styled } from '@toeverything/components/ui'; +import { BlockContainer } from '../../components/BlockContainer'; +import { List } from '../../components/style-container'; import { TextManage, type ExtendedTextUtils, } from '../../components/text-manage'; import { tabBlock } from '../../utils/indent'; +import { BulletIcon, getChildrenType, NumberType } from './data'; import { BulletBlock, BulletProperties } from './types'; -import { - supportChildren, - RenderBlockChildren, - useOnSelect, - BlockPendantProvider, -} from '@toeverything/components/editor-core'; -import { List } from '../../components/style-container'; -import { getChildrenType, BulletIcon, NumberType } from './data'; -import { IndentWrapper } from '../../components/IndentWrapper'; -import { BlockContainer } from '../../components/BlockContainer'; -import { styled } from '@toeverything/components/ui'; export const defaultBulletProps: BulletProperties = { text: { value: [{ text: '' }] }, @@ -208,9 +207,7 @@ export const BulletView = ({ block, editor }: CreateView) => {
- - - + ); }; diff --git a/libs/components/editor-blocks/src/blocks/bullet/index.ts b/libs/components/editor-blocks/src/blocks/bullet/index.ts index 087afb3056..761aab03a1 100644 --- a/libs/components/editor-blocks/src/blocks/bullet/index.ts +++ b/libs/components/editor-blocks/src/blocks/bullet/index.ts @@ -1,18 +1,16 @@ +import { + DefaultColumnsValue, + Protocol, +} from '@toeverything/datasource/db-service'; import { AsyncBlock, BaseView, - CreateView, + getTextHtml, getTextProperties, SelectBlock, - getTextHtml, } from '@toeverything/framework/virgo'; -import { - Protocol, - DefaultColumnsValue, -} from '@toeverything/datasource/db-service'; // import { withTreeViewChildren } from '../../utils/with-tree-view-children'; -import { defaultBulletProps, BulletView } from './BulletView'; -import { IndentWrapper } from '../../components/IndentWrapper'; +import { BulletView, defaultBulletProps } from './BulletView'; export class BulletBlock extends BaseView { public type = Protocol.Block.Type.bullet; diff --git a/libs/components/editor-blocks/src/blocks/grid-item/GridItemRender.tsx b/libs/components/editor-blocks/src/blocks/grid-item/GridItemRender.tsx index 3a598b3145..1dece91699 100644 --- a/libs/components/editor-blocks/src/blocks/grid-item/GridItemRender.tsx +++ b/libs/components/editor-blocks/src/blocks/grid-item/GridItemRender.tsx @@ -1,4 +1,4 @@ -import { RenderBlock } from '@toeverything/components/editor-core'; +import { useBlockRender } from '@toeverything/components/editor-core'; import { ChildrenView, CreateView } from '@toeverything/framework/virgo'; export const GridItemRender = function ( @@ -6,10 +6,11 @@ export const GridItemRender = function ( ) { const GridItem = function (props: CreateView) { const { block } = props; + const { BlockRender } = useBlockRender(); const children = ( <> {block.childrenIds.map(id => { - return ; + return ; })} ); diff --git a/libs/components/editor-blocks/src/blocks/grid/Grid.tsx b/libs/components/editor-blocks/src/blocks/grid/Grid.tsx index 4ecf47f3b5..4b5bfd49b3 100644 --- a/libs/components/editor-blocks/src/blocks/grid/Grid.tsx +++ b/libs/components/editor-blocks/src/blocks/grid/Grid.tsx @@ -1,16 +1,16 @@ -import { RenderBlock } from '@toeverything/components/editor-core'; -import { CreateView } from '@toeverything/framework/virgo'; -import React, { useEffect, useRef, useState } from 'react'; -import { GridHandle } from './GirdHandle'; +import { useBlockRender } from '@toeverything/components/editor-core'; import { styled } from '@toeverything/components/ui'; +import { Protocol } from '@toeverything/datasource/db-service'; +import { CreateView } from '@toeverything/framework/virgo'; +import { debounce, domToRect, Point } from '@toeverything/utils'; +import clsx from 'clsx'; +import React, { useEffect, useRef, useState } from 'react'; import ReactDOM from 'react-dom'; import { GRID_ITEM_CLASS_NAME, GRID_ITEM_CONTENT_CLASS_NAME, } from '../grid-item/GridItem'; -import { debounce, domToRect, Point } from '@toeverything/utils'; -import clsx from 'clsx'; -import { Protocol } from '@toeverything/datasource/db-service'; +import { GridHandle } from './GirdHandle'; const DB_UPDATE_DELAY = 50; const GRID_ON_DRAG_CLASS = 'grid-layout-on-drag'; @@ -31,6 +31,7 @@ export const Grid = function (props: CreateView) { const originalLeftWidth = useRef(gridItemMinWidth); const originalRightWidth = useRef(gridItemMinWidth); const [alertHandleId, setAlertHandleId] = useState(null); + const { BlockRender } = useBlockRender(); const getLeftRightGridItemDomByIndex = (index: number) => { const gridItems = Array.from(gridContainerRef.current?.children).filter( @@ -226,7 +227,7 @@ export const Grid = function (props: CreateView) { key={id} className={GRID_ITEM_CLASS_NAME} > - + handleDragGrid(event, i)} editor={editor} diff --git a/libs/components/editor-blocks/src/blocks/group/ScenePage.tsx b/libs/components/editor-blocks/src/blocks/group/ScenePage.tsx index 6145bec114..739927626d 100644 --- a/libs/components/editor-blocks/src/blocks/group/ScenePage.tsx +++ b/libs/components/editor-blocks/src/blocks/group/ScenePage.tsx @@ -2,5 +2,5 @@ import { RenderBlockChildren } from '@toeverything/components/editor-core'; import type { CreateView } from '@toeverything/framework/virgo'; export const ScenePage = ({ block }: CreateView) => { - return ; + return ; }; diff --git a/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx b/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx index 837772bed2..8f79a6c208 100644 --- a/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx +++ b/libs/components/editor-blocks/src/blocks/group/scene-kanban/CardItem.tsx @@ -1,6 +1,6 @@ import { KanbanCard, - RenderBlock, + useBlockRender, useEditor, useKanban, } from '@toeverything/components/editor-core'; @@ -94,6 +94,7 @@ export const CardItem = ({ const [editable, setEditable] = useState(false); const showKanbanRefPageFlag = useFlag('ShowKanbanRefPage', false); const { editor } = useEditor(); + const { BlockRender } = useBlockRender(); const onAddItem = async () => { setEditable(true); @@ -114,7 +115,7 @@ export const CardItem = ({ setEditable(false)}> - + {showKanbanRefPageFlag && !editable && ( diff --git a/libs/components/editor-blocks/src/blocks/numbered/NumberedView.tsx b/libs/components/editor-blocks/src/blocks/numbered/NumberedView.tsx index 38dac6fc75..74bcfab504 100644 --- a/libs/components/editor-blocks/src/blocks/numbered/NumberedView.tsx +++ b/libs/components/editor-blocks/src/blocks/numbered/NumberedView.tsx @@ -1,8 +1,8 @@ import { TextProps } from '@toeverything/components/common'; import { ContentColumnValue, - services, Protocol, + services, } from '@toeverything/datasource/db-service'; import { type CreateView } from '@toeverything/framework/virgo'; import { useEffect, useRef, useState } from 'react'; @@ -11,18 +11,17 @@ import { type ExtendedTextUtils, } from '../../components/text-manage'; import { tabBlock } from '../../utils/indent'; -import { IndentWrapper } from '../../components/IndentWrapper'; import type { Numbered, NumberedAsyncBlock } from './types'; -import { getChildrenType, getNumber } from './data'; import { - supportChildren, - RenderBlockChildren, - useOnSelect, BlockPendantProvider, + RenderBlockChildren, + supportChildren, + useOnSelect, } from '@toeverything/components/editor-core'; -import { List } from '../../components/style-container'; import { BlockContainer } from '../../components/BlockContainer'; +import { List } from '../../components/style-container'; +import { getChildrenType, getNumber } from './data'; export const defaultTodoProps: Numbered = { text: { value: [{ text: '' }] }, @@ -204,9 +203,7 @@ export const NumberedView = ({ block, editor }: CreateView) => { - - - + ); }; diff --git a/libs/components/editor-blocks/src/blocks/numbered/index.ts b/libs/components/editor-blocks/src/blocks/numbered/index.ts index b8b3c3dc0a..92187be81b 100644 --- a/libs/components/editor-blocks/src/blocks/numbered/index.ts +++ b/libs/components/editor-blocks/src/blocks/numbered/index.ts @@ -1,17 +1,16 @@ +import { + DefaultColumnsValue, + Protocol, +} from '@toeverything/datasource/db-service'; import { AsyncBlock, BaseView, + getTextHtml, getTextProperties, SelectBlock, - getTextHtml, } from '@toeverything/framework/virgo'; -import { - Protocol, - DefaultColumnsValue, -} from '@toeverything/datasource/db-service'; // import { withTreeViewChildren } from '../../utils/with-tree-view-children'; import { defaultTodoProps, NumberedView } from './NumberedView'; -import { IndentWrapper } from '../../components/IndentWrapper'; export class NumberedBlock extends BaseView { public type = Protocol.Block.Type.numbered; diff --git a/libs/components/editor-blocks/src/blocks/text/TextView.tsx b/libs/components/editor-blocks/src/blocks/text/TextView.tsx index 5edf231217..fcb06238e2 100644 --- a/libs/components/editor-blocks/src/blocks/text/TextView.tsx +++ b/libs/components/editor-blocks/src/blocks/text/TextView.tsx @@ -12,7 +12,6 @@ import { styled } from '@toeverything/components/ui'; import { Protocol } from '@toeverything/datasource/db-service'; import { CreateView } from '@toeverything/framework/virgo'; import { BlockContainer } from '../../components/BlockContainer'; -import { IndentWrapper } from '../../components/IndentWrapper'; import { TextManage } from '../../components/text-manage'; import { dedentBlock, tabBlock } from '../../utils/indent'; interface CreateTextView extends CreateView { @@ -255,9 +254,7 @@ export const TextView = ({ handleTab={onTab} /> - - - + ); }; diff --git a/libs/components/editor-blocks/src/blocks/todo/TodoView.tsx b/libs/components/editor-blocks/src/blocks/todo/TodoView.tsx index 8982f4695e..9bf24a37ec 100644 --- a/libs/components/editor-blocks/src/blocks/todo/TodoView.tsx +++ b/libs/components/editor-blocks/src/blocks/todo/TodoView.tsx @@ -1,11 +1,17 @@ import { TextProps } from '@toeverything/components/common'; +import { + AsyncBlock, + BlockPendantProvider, + CreateView, + useOnSelect, +} from '@toeverything/components/editor-core'; import { styled } from '@toeverything/components/ui'; import { ContentColumnValue, Protocol, } from '@toeverything/datasource/db-service'; -import { AsyncBlock, type CreateView } from '@toeverything/framework/virgo'; -import { useRef } from 'react'; +import { useRef, useState } from 'react'; +import { BlockContainer } from '../../components/BlockContainer'; import { TextManage, type ExtendedTextUtils, @@ -36,6 +42,10 @@ const todoIsEmpty = (contentValue: ContentColumnValue): boolean => { export const TodoView = ({ block, editor }: CreateView) => { const properties = { ...defaultTodoProps, ...block.getProperties() }; const text_ref = useRef(null); + const [isSelect, setIsSelect] = useState(false); + useOnSelect(block.id, (isSelect: boolean) => { + setIsSelect(isSelect); + }); const turn_into_text_block = async () => { // Convert to text block @@ -121,28 +131,34 @@ export const TodoView = ({ block, editor }: CreateView) => { }; return ( - -
- -
+ + + +
+ +
-
- -
-
+
+ +
+
+ + ); }; diff --git a/libs/components/editor-blocks/src/blocks/todo/index.ts b/libs/components/editor-blocks/src/blocks/todo/index.ts index c6580009d0..78f317103a 100644 --- a/libs/components/editor-blocks/src/blocks/todo/index.ts +++ b/libs/components/editor-blocks/src/blocks/todo/index.ts @@ -1,18 +1,16 @@ import { - BaseView, - getTextProperties, AsyncBlock, - SelectBlock, + BaseView, getTextHtml, -} from '@toeverything/framework/virgo'; -// import type { CreateView } from '@toeverything/framework/virgo'; + getTextProperties, + SelectBlock, + withTreeViewChildren, +} from '@toeverything/components/editor-core'; import { - Protocol, DefaultColumnsValue, + Protocol, } from '@toeverything/datasource/db-service'; -// import { withTreeViewChildren } from '../../utils/with-tree-view-children'; -import { withTreeViewChildren } from '../../utils/WithTreeViewChildren'; -import { TodoView, defaultTodoProps } from './TodoView'; +import { defaultTodoProps, TodoView } from './TodoView'; import type { TodoAsyncBlock } from './types'; export class TodoBlock extends BaseView { diff --git a/libs/components/editor-blocks/src/components/BlockContainer/BlockContainer.tsx b/libs/components/editor-blocks/src/components/BlockContainer/BlockContainer.tsx index 00da92a813..4c043ce163 100644 --- a/libs/components/editor-blocks/src/components/BlockContainer/BlockContainer.tsx +++ b/libs/components/editor-blocks/src/components/BlockContainer/BlockContainer.tsx @@ -23,7 +23,7 @@ export const BlockContainer = function ({ ); }; -export const Container = styled('div')<{ selected: boolean }>( +export const Container = styled('div')<{ selected?: boolean }>( ({ selected, theme }) => ({ backgroundColor: selected ? theme.affine.palette.textSelected : '', marginBottom: '2px', diff --git a/libs/components/editor-blocks/src/components/IndentWrapper/IndentWrapper.tsx b/libs/components/editor-blocks/src/components/IndentWrapper/IndentWrapper.tsx deleted file mode 100644 index 93aa9d34a1..0000000000 --- a/libs/components/editor-blocks/src/components/IndentWrapper/IndentWrapper.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { PropsWithChildren } from 'react'; -import { ChildrenView } from '@toeverything/framework/virgo'; -import { styled } from '@toeverything/components/ui'; - -/** - * Indent rendering child nodes - */ -export const IndentWrapper = (props: PropsWithChildren) => { - return {props.children}; -}; - -const StyledIdentWrapper = styled('div')({ - display: 'flex', - flexDirection: 'column', - // TODO: marginLeft should use theme provided by styled - marginLeft: '30px', -}); diff --git a/libs/components/editor-blocks/src/components/IndentWrapper/index.ts b/libs/components/editor-blocks/src/components/IndentWrapper/index.ts deleted file mode 100644 index e4234a916d..0000000000 --- a/libs/components/editor-blocks/src/components/IndentWrapper/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './IndentWrapper'; diff --git a/libs/components/editor-blocks/src/components/source-view/format-url/youtube.ts b/libs/components/editor-blocks/src/components/source-view/format-url/youtube.ts index 56f165a515..7cd540b12e 100644 --- a/libs/components/editor-blocks/src/components/source-view/format-url/youtube.ts +++ b/libs/components/editor-blocks/src/components/source-view/format-url/youtube.ts @@ -1,4 +1,5 @@ export const isYoutubeUrl = (url?: string): boolean => { + if (!url) return false; const allowedHosts = ['www.youtu.be', 'www.youtube.com']; const host = new URL(url).host; return allowedHosts.includes(host); diff --git a/libs/components/editor-blocks/src/utils/WithTreeViewChildren.tsx b/libs/components/editor-blocks/src/utils/WithTreeViewChildren.tsx deleted file mode 100644 index e7e497f2ef..0000000000 --- a/libs/components/editor-blocks/src/utils/WithTreeViewChildren.tsx +++ /dev/null @@ -1,236 +0,0 @@ -import { - BlockPendantProvider, - CreateView, - RenderBlock, - useCurrentView, - useOnSelect, -} from '@toeverything/components/editor-core'; -import { styled } from '@toeverything/components/ui'; -import type { - ComponentPropsWithoutRef, - ComponentPropsWithRef, - CSSProperties, - ReactElement, -} from 'react'; -import { forwardRef, useState } from 'react'; -import { SCENE_CONFIG } from '../blocks/group/config'; -import { BlockContainer } from '../components/BlockContainer'; - -type WithChildrenConfig = { - indent: CSSProperties['marginLeft']; -}; - -const defaultConfig: WithChildrenConfig = { - indent: '30px', -}; - -const TreeView = forwardRef< - HTMLDivElement, - { lastItem?: boolean } & ComponentPropsWithRef<'div'> ->(({ lastItem = false, children, onClick, ...restProps }, ref) => { - return ( - - - - - {lastItem && } - - {/* maybe need a child wrapper */} - {children} - - ); -}); - -interface ChildrenViewProp { - childrenIds: string[]; - handleCollapse: () => void; - indent?: string | number; -} - -const ChildrenView = ({ - childrenIds, - handleCollapse, - indent, -}: ChildrenViewProp) => { - const [currentView] = useCurrentView(); - const isKanbanScene = currentView.type === SCENE_CONFIG.KANBAN; - - return ( - - {childrenIds.map((childId, idx) => { - if (isKanbanScene) { - return ( - - - - ); - } - - return ( - - - - ); - })} - - ); -}; - -const CollapsedNode = forwardRef< - HTMLDivElement, - ComponentPropsWithoutRef<'div'> ->((props, ref) => { - return ( - - ยทยทยท - - ); -}); - -/** - * Indent rendering child nodes - */ -export const withTreeViewChildren = ( - creator: (props: CreateView) => ReactElement, - customConfig: Partial = {} -) => { - const config = { - ...defaultConfig, - ...customConfig, - }; - - return (props: CreateView) => { - const { block, editor } = props; - const collapsed = block.getProperty('collapsed')?.value; - const childrenIds = block.childrenIds; - const showChildren = !collapsed && childrenIds.length > 0; - - const [isSelect, setIsSelect] = useState(false); - useOnSelect(block.id, (isSelect: boolean) => { - setIsSelect(isSelect); - }); - const handleCollapse = () => { - block.setProperty('collapsed', { value: true }); - }; - - const handleExpand = () => { - block.setProperty('collapsed', { value: false }); - }; - - return ( - - -
{creator(props)}
-
- - {collapsed && ( - - )} - {showChildren && ( - - )} -
- ); - }; -}; - -const Wrapper = styled('div')({ display: 'flex', flexDirection: 'column' }); - -const Children = Wrapper; - -const TREE_COLOR = '#D5DFE6'; -// adjust left and right margins of the the tree line -const TREE_LINE_LEFT_OFFSET = '-16px'; -// determine the position of the horizontal line by the type of the item -const TREE_LINE_TOP_OFFSET = '20px'; // '50%' -const TREE_LINE_WIDTH = '12px'; - -const TreeWrapper = styled('div')({ - position: 'relative', -}); - -const StyledTreeView = styled('div')({ - position: 'absolute', - left: TREE_LINE_LEFT_OFFSET, - height: '100%', -}); - -const Line = styled('div')({ - position: 'absolute', - cursor: 'pointer', - backgroundColor: TREE_COLOR, - // somehow tldraw would override this - boxSizing: 'content-box!important' as any, - // See [Can I add background color only for padding?](https://stackoverflow.com/questions/14628601/can-i-add-background-color-only-for-padding) - backgroundClip: 'content-box', - backgroundOrigin: 'content-box', - // Increase click hot spot - padding: '10px', -}); - -const VerticalLine = styled(Line)<{ last: boolean }>(({ last }) => ({ - width: '1px', - height: last ? TREE_LINE_TOP_OFFSET : '100%', - paddingTop: 0, - paddingBottom: 0, - transform: 'translate(-50%, 0)', - - opacity: last ? 0 : 'unset', -})); - -const HorizontalLine = styled(Line)<{ last: boolean }>(({ last }) => ({ - width: TREE_LINE_WIDTH, - height: '1px', - paddingLeft: 0, - paddingRight: 0, - top: TREE_LINE_TOP_OFFSET, - transform: 'translate(0, -50%)', - opacity: last ? 0 : 'unset', -})); - -const Collapsed = styled('div')({ - cursor: 'pointer', - display: 'inline-block', - color: '#98ACBD', - padding: '8px', -}); - -const LastItemRadius = styled('div')({ - boxSizing: 'content-box', - position: 'absolute', - left: '-0.5px', - top: 0, - height: TREE_LINE_TOP_OFFSET, - bottom: '50%', - width: TREE_LINE_WIDTH, - borderWidth: '1px', - borderStyle: 'solid', - borderLeftColor: TREE_COLOR, - borderBottomColor: TREE_COLOR, - borderTop: 'none', - borderRight: 'none', - borderRadius: '0 0 0 3px', - pointerEvents: 'none', -}); - -const StyledBorder = styled('div')({ - border: '1px solid #E0E6EB', - borderRadius: '5px', - margin: '4px', -}); diff --git a/libs/components/editor-core/src/render-block/RenderBlock.tsx b/libs/components/editor-core/src/render-block/RenderBlock.tsx index 1dc945e870..c843274166 100644 --- a/libs/components/editor-core/src/render-block/RenderBlock.tsx +++ b/libs/components/editor-core/src/render-block/RenderBlock.tsx @@ -69,4 +69,5 @@ export function RenderBlock({ const BlockContainer = styled('div')(({ theme }) => ({ fontSize: theme.typography.body1.fontSize, + flex: 1, })); From 123091c1aaa37bfd80da7c891542a9f33cde8d8f Mon Sep 17 00:00:00 2001 From: lawvs <18554747+lawvs@users.noreply.github.com> Date: Wed, 24 Aug 2022 02:07:37 +0800 Subject: [PATCH 52/58] chore: add warn comment --- libs/components/editor-core/src/render-block/Context.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libs/components/editor-core/src/render-block/Context.tsx b/libs/components/editor-core/src/render-block/Context.tsx index 8a1b68465c..90c89eec0e 100644 --- a/libs/components/editor-core/src/render-block/Context.tsx +++ b/libs/components/editor-core/src/render-block/Context.tsx @@ -13,6 +13,9 @@ export const BlockRenderContext = createContext( ) as any ); +/** + * CAUTION! DO NOT PROVIDE A DYNAMIC BLOCK RENDER! + */ export const BlockRenderProvider = ({ blockRender, children, From 617e9a06125671066787f097ef537c72e1d0baf9 Mon Sep 17 00:00:00 2001 From: DiamondThree Date: Wed, 24 Aug 2022 13:47:47 +0800 Subject: [PATCH 53/58] Bugfix/delete log (#315) * fix delete log * fix delete log --- libs/components/affine-board/src/Board.tsx | 5 +++-- libs/components/affine-board/src/hooks/use-shapes.ts | 3 ++- .../board-draw/src/components/command-panel/ArrowTo.tsx | 8 +++++--- libs/components/board-state/src/tldraw-app.ts | 4 ++-- libs/components/common/src/lib/text/EditableText.tsx | 2 +- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/libs/components/affine-board/src/Board.tsx b/libs/components/affine-board/src/Board.tsx index 101d54d37b..9936d115a0 100644 --- a/libs/components/affine-board/src/Board.tsx +++ b/libs/components/affine-board/src/Board.tsx @@ -52,6 +52,7 @@ const AffineBoard = ({ }); const { shapes, bindings } = useShapes(workspace, rootBlockId); + useEffect(() => { if (app) { app.replacePageContent(shapes || {}, bindings, {}); @@ -109,7 +110,6 @@ const AffineBoard = ({ }); } shape.affineId = block.id; - Object.keys(bindings).forEach(bilingKey => { if ( bindings[bilingKey]?.fromId === shape.id @@ -148,7 +148,8 @@ const AffineBoard = ({ Object.assign(pageBindings, bindings); } }); - services.api.editorBlock.update({ + + await services.api.editorBlock.update({ workspace: workspace, id: rootBlockId, properties: { diff --git a/libs/components/affine-board/src/hooks/use-shapes.ts b/libs/components/affine-board/src/hooks/use-shapes.ts index beb8c50efa..ba1bf066ff 100644 --- a/libs/components/affine-board/src/hooks/use-shapes.ts +++ b/libs/components/affine-board/src/hooks/use-shapes.ts @@ -12,7 +12,7 @@ const getBindings = (workspace: string, rootBlockId: string) => { ids: [rootBlockId], }) .then(blcoks => { - return blcoks[0].properties.bindings?.value; + return blcoks[0]?.properties.bindings?.value; }); }; @@ -104,6 +104,7 @@ export const useShapes = (workspace: string, rootBlockId: string) => { return acc; }, {} as Record); + return { shapes: blocksShapes, bindings: JSON.parse(blocks?.bindings ?? '{}'), diff --git a/libs/components/board-draw/src/components/command-panel/ArrowTo.tsx b/libs/components/board-draw/src/components/command-panel/ArrowTo.tsx index 21f37a9fbc..84ef142ef0 100644 --- a/libs/components/board-draw/src/components/command-panel/ArrowTo.tsx +++ b/libs/components/board-draw/src/components/command-panel/ArrowTo.tsx @@ -21,6 +21,9 @@ export const ArrowTo = ({ app, shapes }: GroupAndUnGroupProps) => { let activeShape = shapes[0]; let toNextShapBindings: ArrowBinding[] = []; let bindingId = ''; + if (!activeShape) { + return; + } Object.keys(bindings).forEach(key => { if (bindings[key].toId === activeShape.id) { bindingId = bindings[key].fromId; @@ -35,7 +38,6 @@ export const ArrowTo = ({ app, shapes }: GroupAndUnGroupProps) => { toNextShapBindings.forEach(binding => { if (binding.toId !== activeShape.id) { allShape.forEach(item => { - console.log(item); if (item.id === binding.toId) { ArrowToArr.push(item); } @@ -44,7 +46,7 @@ export const ArrowTo = ({ app, shapes }: GroupAndUnGroupProps) => { }); setarrowToArr(ArrowToArr); return () => {}; - }, [app.page.bindings, app.shapes]); + }, [app.page.bindings]); const jumpToNextShap = (shape: TDShape) => { app.zoomToShapes([shape]); }; @@ -68,7 +70,7 @@ export const ArrowTo = ({ app, shapes }: GroupAndUnGroupProps) => {
} > - + diff --git a/libs/components/board-state/src/tldraw-app.ts b/libs/components/board-state/src/tldraw-app.ts index 34a392db72..98bffcf654 100644 --- a/libs/components/board-state/src/tldraw-app.ts +++ b/libs/components/board-state/src/tldraw-app.ts @@ -626,7 +626,7 @@ export class TldrawApp extends StateManager { private prev_bindings = this.page.bindings; private prev_assets = this.document.assets; - private _broadcastPageChanges = () => { + private _broadcastPageChanges = async () => { const visited = new Set(); const changedShapes: Record = {}; @@ -683,7 +683,7 @@ export class TldrawApp extends StateManager { Object.keys(changedAssets).length > 0 ) { this.just_sent = true; - this.callbacks.onChangePage?.( + await this.callbacks.onChangePage?.( this, changedShapes, changedBindings, diff --git a/libs/components/common/src/lib/text/EditableText.tsx b/libs/components/common/src/lib/text/EditableText.tsx index 8637246d7d..b2b2229fec 100644 --- a/libs/components/common/src/lib/text/EditableText.tsx +++ b/libs/components/common/src/lib/text/EditableText.tsx @@ -804,7 +804,7 @@ const EditorLeaf = ({ attributes, children, leaf }: any) => { backgroundColor: '#F2F5F9', borderRadius: '5px', color: '#3A4C5C', - padding: '3px 8px', + padding: '1px 8px', margin: '0 2px', }} > From dad12b2a79e1f8d9773f34e83ad4d101c49b3be8 Mon Sep 17 00:00:00 2001 From: zuomeng wang Date: Wed, 24 Aug 2022 15:38:58 +0800 Subject: [PATCH 54/58] fix: update sidebar shadow (#323) --- apps/ligo-virgo/src/pages/workspace/docs/Page.tsx | 2 +- libs/components/ui/src/theme/theme.ts | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/ligo-virgo/src/pages/workspace/docs/Page.tsx b/apps/ligo-virgo/src/pages/workspace/docs/Page.tsx index a2440a1757..183adc6094 100644 --- a/apps/ligo-virgo/src/pages/workspace/docs/Page.tsx +++ b/apps/ligo-virgo/src/pages/workspace/docs/Page.tsx @@ -175,7 +175,7 @@ const WorkspaceSidebar = styled('div')(({ theme }) => ({ width: 300, minWidth: 300, borderRadius: '0px 10px 10px 0px', - boxShadow: theme.affine.shadows.shadow1, + boxShadow: theme.affine.shadows.shadow2, backgroundColor: '#FFFFFF', transitionProperty: 'left', transitionDuration: '0.35s', diff --git a/libs/components/ui/src/theme/theme.ts b/libs/components/ui/src/theme/theme.ts index 76d42e3a0a..ce05c7b54d 100644 --- a/libs/components/ui/src/theme/theme.ts +++ b/libs/components/ui/src/theme/theme.ts @@ -233,7 +233,10 @@ export const Theme = { }, shadows: { none: 'none', - shadow1: '0px 1px 5px rgba(152, 172, 189, 0.2)', + shadow1: + '0px 1px 10px -6px rgba(24, 39, 75, 0.08), 0px 3px 16px -6px rgba(24, 39, 75, 0.04)', + shadow2: + '0px 6px 16px -8px rgba(0,0,0,0.08), 0px 9px 14px 0px rgba(0,0,0,0.05), 0px 12px 24px 16px rgba(0,0,0,0.03)', }, border: ['none'], spacing: { From 712566ca8464d88566da056b7781e3fb4bab4de3 Mon Sep 17 00:00:00 2001 From: DiamondThree Date: Wed, 24 Aug 2022 16:51:19 +0800 Subject: [PATCH 55/58] Bugfix/board style (#321) * fix style * fix drag bounds * fix drag bounds * delete log * delete log * fix:lint * fix:lint * fix:lint * fix:bounds show --- libs/components/affine-board/src/Board.tsx | 45 ++--------- .../affine-board/src/hooks/use-shapes.ts | 27 +------ libs/components/board-draw/src/TlDraw.tsx | 2 +- .../src/components/align-panel/index.tsx | 3 +- .../components/command-panel/CommandPanel.tsx | 13 ++- .../src/arrow-util/arrow-util.tsx | 2 +- .../components/DashedRectangle.tsx | 17 ++-- libs/components/board-state/src/tldraw-app.ts | 76 ++++++++++++------ .../src/blocks/code/CodeView.tsx | 80 +++++++++---------- 9 files changed, 117 insertions(+), 148 deletions(-) diff --git a/libs/components/affine-board/src/Board.tsx b/libs/components/affine-board/src/Board.tsx index 9936d115a0..783c469b64 100644 --- a/libs/components/affine-board/src/Board.tsx +++ b/libs/components/affine-board/src/Board.tsx @@ -51,11 +51,10 @@ const AffineBoard = ({ }; }); - const { shapes, bindings } = useShapes(workspace, rootBlockId); - + const { shapes } = useShapes(workspace, rootBlockId); useEffect(() => { if (app) { - app.replacePageContent(shapes || {}, bindings, {}); + app.replacePageContent(shapes || {}, {}, {}); } }, [app, shapes]); @@ -69,7 +68,9 @@ const AffineBoard = ({ onMount(app) { set_app(app); }, - + async onPaste(e, data) { + console.log('e,data: ', e, data); + }, async onCopy(e, groupIds) { const clip = await getClipDataOfBlocksById( editor, @@ -110,18 +111,6 @@ const AffineBoard = ({ }); } shape.affineId = block.id; - Object.keys(bindings).forEach(bilingKey => { - if ( - bindings[bilingKey]?.fromId === shape.id - ) { - bindings[bilingKey].fromId = block.id; - } - if ( - bindings[bilingKey]?.toId === shape.id - ) { - bindings[bilingKey].toId = block.id; - } - }); return await services.api.editorBlock.update({ workspace: shape.workspace, id: block.id, @@ -134,30 +123,6 @@ const AffineBoard = ({ } }) ); - const pageBindingsString = ( - await services.api.editorBlock.get({ - workspace: workspace, - ids: [rootBlockId], - }) - )?.[0].properties.bindings?.value; - const pageBindings = JSON.parse(pageBindingsString ?? '{}'); - Object.keys(bindings).forEach(bindingsKey => { - if (!bindings[bindingsKey]) { - delete pageBindings[bindingsKey]; - } else { - Object.assign(pageBindings, bindings); - } - }); - - await services.api.editorBlock.update({ - workspace: workspace, - id: rootBlockId, - properties: { - bindings: { - value: JSON.stringify(pageBindings), - }, - }, - }); }, }} /> diff --git a/libs/components/affine-board/src/hooks/use-shapes.ts b/libs/components/affine-board/src/hooks/use-shapes.ts index ba1bf066ff..23270b6c19 100644 --- a/libs/components/affine-board/src/hooks/use-shapes.ts +++ b/libs/components/affine-board/src/hooks/use-shapes.ts @@ -5,24 +5,12 @@ import { services } from '@toeverything/datasource/db-service'; import { usePageClientWidth } from '@toeverything/datasource/state'; import { useEffect, useState } from 'react'; -const getBindings = (workspace: string, rootBlockId: string) => { - return services.api.editorBlock - .get({ - workspace: workspace, - ids: [rootBlockId], - }) - .then(blcoks => { - return blcoks[0]?.properties.bindings?.value; - }); -}; - export const useShapes = (workspace: string, rootBlockId: string) => { const { pageClientWidth } = usePageClientWidth(); // page padding left and right total 300px const editorShapeInitSize = pageClientWidth - 300; const [blocks, setBlocks] = useState<{ shapes: [ReturnEditorBlock[]]; - bindings: string; }>(); useEffect(() => { Promise.all([ @@ -43,11 +31,8 @@ export const useShapes = (workspace: string, rootBlockId: string) => { return shapes; }), ]).then(shapes => { - getBindings(workspace, rootBlockId).then(bindings => { - setBlocks({ - shapes, - bindings: bindings, - }); + setBlocks({ + shapes: shapes, }); }); @@ -65,11 +50,8 @@ export const useShapes = (workspace: string, rootBlockId: string) => { return childBlock; }) ).then(shapes => { - getBindings(workspace, rootBlockId).then(bindings => { - setBlocks({ - shapes: [shapes], - bindings: bindings, - }); + setBlocks({ + shapes: [shapes], }); }); }) @@ -107,6 +89,5 @@ export const useShapes = (workspace: string, rootBlockId: string) => { return { shapes: blocksShapes, - bindings: JSON.parse(blocks?.bindings ?? '{}'), }; }; diff --git a/libs/components/board-draw/src/TlDraw.tsx b/libs/components/board-draw/src/TlDraw.tsx index 1961367235..a1444b76c0 100644 --- a/libs/components/board-draw/src/TlDraw.tsx +++ b/libs/components/board-draw/src/TlDraw.tsx @@ -362,7 +362,7 @@ const InnerTldraw = memo(function InnerTldraw({ // Hide bounds when not using the select tool, or when the only selected shape has handles const hideBounds = - (isInSession && app.session?.constructor.name !== 'BrushSession') || + (isInSession && app.session?.constructor.name === 'BrushSession') || !isSelecting || isHideBoundsShape || !!pageState.editingId; diff --git a/libs/components/board-draw/src/components/align-panel/index.tsx b/libs/components/board-draw/src/components/align-panel/index.tsx index d0ff48390d..ddc43b1254 100644 --- a/libs/components/board-draw/src/components/align-panel/index.tsx +++ b/libs/components/board-draw/src/components/align-panel/index.tsx @@ -56,7 +56,8 @@ const SelectableContainer = styled('div')<{ selected?: boolean }>( borderRadius: '5px', overflow: 'hidden', margin: '5px', - padding: '3px', + width: '24px', + height: '24px', cursor: 'pointer', boxSizing: 'border-box', '&:hover': { diff --git a/libs/components/board-draw/src/components/command-panel/CommandPanel.tsx b/libs/components/board-draw/src/components/command-panel/CommandPanel.tsx index 94e28bdc2f..031d4240a6 100644 --- a/libs/components/board-draw/src/components/command-panel/CommandPanel.tsx +++ b/libs/components/board-draw/src/components/command-panel/CommandPanel.tsx @@ -2,7 +2,6 @@ import { TLDR, TldrawApp } from '@toeverything/components/board-state'; import { Divider, Popover, styled } from '@toeverything/components/ui'; import { Fragment } from 'react'; import { AlignOperation } from './AlignOperation'; -import { ArrowTo } from './ArrowTo'; import { BorderColorConfig } from './BorderColorConfig'; import { DeleteShapes } from './DeleteOperation'; import { FillColorConfig } from './FillColorConfig'; @@ -107,12 +106,12 @@ export const CommandPanel = ({ app }: { app: TldrawApp }) => { shapes={config.deleteShapes.selectedShapes} > ) : null, - toNextShap: ( - - ), + // toNextShap: ( + // + // ), }; const nodes = Object.entries(configNodes).filter(([key, node]) => !!node); diff --git a/libs/components/board-shapes/src/arrow-util/arrow-util.tsx b/libs/components/board-shapes/src/arrow-util/arrow-util.tsx index 42045918f4..dace7eeb38 100644 --- a/libs/components/board-shapes/src/arrow-util/arrow-util.tsx +++ b/libs/components/board-shapes/src/arrow-util/arrow-util.tsx @@ -42,7 +42,7 @@ type E = HTMLDivElement; export class ArrowUtil extends TDShapeUtil { type = TDShapeType.Arrow as const; - override hideBounds = true; + override hideBounds = false; override canEdit = true; diff --git a/libs/components/board-shapes/src/rectangle-util/components/DashedRectangle.tsx b/libs/components/board-shapes/src/rectangle-util/components/DashedRectangle.tsx index 77ee2cec6a..36d4475b92 100644 --- a/libs/components/board-shapes/src/rectangle-util/components/DashedRectangle.tsx +++ b/libs/components/board-shapes/src/rectangle-util/components/DashedRectangle.tsx @@ -1,6 +1,8 @@ import { Utils } from '@tldraw/core'; -import type { ShapeStyles } from '@toeverything/components/board-types'; -import { BINDING_DISTANCE } from '@toeverything/components/board-types'; +import { + BINDING_DISTANCE, + ShapeStyles, +} from '@toeverything/components/board-types'; import * as React from 'react'; import { getShapeStyle } from '../../shared'; @@ -56,23 +58,20 @@ export const DashedRectangle = React.memo(function DashedRectangle({ return ( <> {style.isFilled && ( diff --git a/libs/components/board-state/src/tldraw-app.ts b/libs/components/board-state/src/tldraw-app.ts index 98bffcf654..1e95912db5 100644 --- a/libs/components/board-state/src/tldraw-app.ts +++ b/libs/components/board-state/src/tldraw-app.ts @@ -175,6 +175,10 @@ interface TDCallbacks { * (optional) A callback to run when the shape is copied. */ onCopy?: (e: ClipboardEvent, ids: string[]) => void; + /** + * (optional) A callback to run when the shape is paste. + */ + onPaste?: (e: ClipboardEvent, data: any) => void; } export interface TldrawAppCtorProps { @@ -1956,6 +1960,53 @@ export class TldrawApp extends StateManager { paste = async (point?: number[], e?: ClipboardEvent) => { if (this.readOnly) return; + if (e) { + const data = e.clipboardData?.getData('text/html'); + const paste_as_html = (html: string) => { + try { + const maybeJson = html.match(/(.*)<\/tldraw>/)?.[1]; + + if (!maybeJson) return; + + const json: { + type: string; + shapes: TDShape[]; + bindings: TDBinding[]; + assets: TDAsset[]; + } = JSON.parse(maybeJson); + return json; + } catch (e) { + return; + } + }; + this.callbacks.onPaste?.(e, paste_as_html(data)); + return this; + } + + const paste_as_html = (html: string) => { + try { + const maybeJson = html.match(/(.*)<\/tldraw>/)?.[1]; + + if (!maybeJson) return; + + const json: { + type: string; + shapes: TDShape[]; + bindings: TDBinding[]; + assets: TDAsset[]; + } = JSON.parse(maybeJson); + + if (json.type === 'tldr/clipboard') { + pasteInCurrentPage(json.shapes, json.bindings, json.assets); + return; + } else { + throw Error('Not tldraw data!'); + } + } catch (e) { + pasteTextAsShape(html); + return; + } + }; const pasteInCurrentPage = ( shapes: TDShape[], bindings: TDBinding[], @@ -2107,31 +2158,6 @@ export class TldrawApp extends StateManager { // this.select(shapeId); }; - const paste_as_html = (html: string) => { - try { - const maybeJson = html.match(/(.*)<\/tldraw>/)?.[1]; - - if (!maybeJson) return; - - const json: { - type: string; - shapes: TDShape[]; - bindings: TDBinding[]; - assets: TDAsset[]; - } = JSON.parse(maybeJson); - - if (json.type === 'tldr/clipboard') { - pasteInCurrentPage(json.shapes, json.bindings, json.assets); - return; - } else { - throw Error('Not tldraw data!'); - } - } catch (e) { - pasteTextAsShape(html); - return; - } - }; - if (e !== undefined) { const items: DataTransferItemList = e.clipboardData?.items ?? ({} as DataTransferItemList); diff --git a/libs/components/editor-blocks/src/blocks/code/CodeView.tsx b/libs/components/editor-blocks/src/blocks/code/CodeView.tsx index 2739c8a70c..1bcedf4251 100644 --- a/libs/components/editor-blocks/src/blocks/code/CodeView.tsx +++ b/libs/components/editor-blocks/src/blocks/code/CodeView.tsx @@ -1,58 +1,54 @@ -import { useState, useRef, useEffect } from 'react'; -import { StyleWithAtRules } from 'style9'; - -import { CreateView } from '@toeverything/framework/virgo'; -import CodeMirror, { ReactCodeMirrorRef } from './CodeMirror'; -import { styled } from '@toeverything/components/ui'; - -import { javascript } from '@codemirror/lang-javascript'; -import { html } from '@codemirror/lang-html'; -import { css } from '@codemirror/lang-css'; -import { json } from '@codemirror/lang-json'; -import { python } from '@codemirror/lang-python'; -import { markdown } from '@codemirror/lang-markdown'; -import { xml } from '@codemirror/lang-xml'; -import { sql, MySQL, PostgreSQL } from '@codemirror/lang-sql'; -import { java } from '@codemirror/lang-java'; -import { rust } from '@codemirror/lang-rust'; import { cpp } from '@codemirror/lang-cpp'; +import { css } from '@codemirror/lang-css'; +import { html } from '@codemirror/lang-html'; +import { java } from '@codemirror/lang-java'; +import { javascript } from '@codemirror/lang-javascript'; +import { json } from '@codemirror/lang-json'; import { lezer } from '@codemirror/lang-lezer'; +import { markdown } from '@codemirror/lang-markdown'; import { php } from '@codemirror/lang-php'; +import { python } from '@codemirror/lang-python'; +import { rust } from '@codemirror/lang-rust'; +import { MySQL, PostgreSQL, sql } from '@codemirror/lang-sql'; +import { xml } from '@codemirror/lang-xml'; import { StreamLanguage } from '@codemirror/language'; -import { go } from '@codemirror/legacy-modes/mode/go'; -import { ruby } from '@codemirror/legacy-modes/mode/ruby'; -import { shell } from '@codemirror/legacy-modes/mode/shell'; -import { lua } from '@codemirror/legacy-modes/mode/lua'; -import { swift } from '@codemirror/legacy-modes/mode/swift'; -import { tcl } from '@codemirror/legacy-modes/mode/tcl'; -import { yaml } from '@codemirror/legacy-modes/mode/yaml'; -import { vb } from '@codemirror/legacy-modes/mode/vb'; -import { powerShell } from '@codemirror/legacy-modes/mode/powershell'; import { brainfuck } from '@codemirror/legacy-modes/mode/brainfuck'; -import { stylus } from '@codemirror/legacy-modes/mode/stylus'; -import { erlang } from '@codemirror/legacy-modes/mode/erlang'; -import { elixir } from 'codemirror-lang-elixir'; -import { nginx } from '@codemirror/legacy-modes/mode/nginx'; -import { perl } from '@codemirror/legacy-modes/mode/perl'; -import { pascal } from '@codemirror/legacy-modes/mode/pascal'; -import { liveScript } from '@codemirror/legacy-modes/mode/livescript'; -import { scheme } from '@codemirror/legacy-modes/mode/scheme'; -import { toml } from '@codemirror/legacy-modes/mode/toml'; -import { vbScript } from '@codemirror/legacy-modes/mode/vbscript'; import { clojure } from '@codemirror/legacy-modes/mode/clojure'; import { coffeeScript } from '@codemirror/legacy-modes/mode/coffeescript'; import { dockerFile } from '@codemirror/legacy-modes/mode/dockerfile'; +import { erlang } from '@codemirror/legacy-modes/mode/erlang'; +import { go } from '@codemirror/legacy-modes/mode/go'; import { julia } from '@codemirror/legacy-modes/mode/julia'; +import { liveScript } from '@codemirror/legacy-modes/mode/livescript'; +import { lua } from '@codemirror/legacy-modes/mode/lua'; +import { nginx } from '@codemirror/legacy-modes/mode/nginx'; +import { pascal } from '@codemirror/legacy-modes/mode/pascal'; +import { perl } from '@codemirror/legacy-modes/mode/perl'; +import { powerShell } from '@codemirror/legacy-modes/mode/powershell'; import { r } from '@codemirror/legacy-modes/mode/r'; +import { ruby } from '@codemirror/legacy-modes/mode/ruby'; +import { scheme } from '@codemirror/legacy-modes/mode/scheme'; +import { shell } from '@codemirror/legacy-modes/mode/shell'; +import { stylus } from '@codemirror/legacy-modes/mode/stylus'; +import { swift } from '@codemirror/legacy-modes/mode/swift'; +import { tcl } from '@codemirror/legacy-modes/mode/tcl'; +import { toml } from '@codemirror/legacy-modes/mode/toml'; +import { vb } from '@codemirror/legacy-modes/mode/vb'; +import { vbScript } from '@codemirror/legacy-modes/mode/vbscript'; +import { yaml } from '@codemirror/legacy-modes/mode/yaml'; import { Extension } from '@codemirror/state'; -import { Option, Select } from '@toeverything/components/ui'; - import { - useOnSelect, BlockPendantProvider, + useOnSelect, } from '@toeverything/components/editor-core'; -import { copyToClipboard } from '@toeverything/utils'; import { DuplicateIcon } from '@toeverything/components/icons'; +import { Option, Select, styled } from '@toeverything/components/ui'; +import { CreateView } from '@toeverything/framework/virgo'; +import { copyToClipboard } from '@toeverything/utils'; +import { elixir } from 'codemirror-lang-elixir'; +import { useEffect, useRef, useState } from 'react'; +import { StyleWithAtRules } from 'style9'; +import CodeMirror, { ReactCodeMirrorRef } from './CodeMirror'; interface CreateCodeView extends CreateView { style9?: StyleWithAtRules; @@ -110,13 +106,15 @@ const CodeBlock = styled('div')(({ theme }) => ({ borderRadius: theme.affine.shape.borderRadius, '&:hover': { '.operation': { - display: 'flex', + opacity: 1, }, }, '.operation': { display: 'flex', flexWrap: 'wrap', justifyContent: 'space-between', + opacity: 0, + transition: 'opacity 1.5s', }, '.copy-block': { padding: '0px 10px', From 6ac1f618f022dc12123d17babce6f3c29ff1f8a4 Mon Sep 17 00:00:00 2001 From: DarkSky Date: Wed, 24 Aug 2022 17:37:16 +0800 Subject: [PATCH 56/58] feat: cascading events --- libs/datasource/jwt/src/block/abstract.ts | 49 +++++++++++++++++------ libs/datasource/jwt/src/block/indexer.ts | 8 ++-- libs/datasource/jwt/src/index.ts | 2 +- 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/libs/datasource/jwt/src/block/abstract.ts b/libs/datasource/jwt/src/block/abstract.ts index 55249514b3..d2f117c62b 100644 --- a/libs/datasource/jwt/src/block/abstract.ts +++ b/libs/datasource/jwt/src/block/abstract.ts @@ -21,6 +21,7 @@ const logger_debug = getLogger('debug:BlockDB:block'); const _GET_BLOCK = Symbol('GET_BLOCK'); const _SET_PARENT = Symbol('SET_PARENT'); +const _EMIT_EVENT = Symbol('EMIT_EVENT'); export class AbstractBlock< B extends BlockInstance, @@ -30,7 +31,12 @@ export class AbstractBlock< private readonly _block: BlockInstance; private readonly _history: HistoryManager; private readonly _root: AbstractBlock | undefined; - private readonly _parentListener: Map; + private readonly _listeners: { + cascade: Map; + children: Map; + content: Map; + parent: Map; + }; private _parent: AbstractBlock | undefined; private _changeParent?: () => void; @@ -45,7 +51,19 @@ export class AbstractBlock< this._history = this._block.scopedHistory([this._id]); this._root = root; - this._parentListener = new Map(); + this._listeners = { + cascade: new Map(), + children: new Map(), + content: new Map(), + parent: new Map(), + }; + + this._block.on('content', 'internal', states => + this[_EMIT_EVENT]('content', states) + ); + this._block.on('children', 'internal', states => + this[_EMIT_EVENT]('children', states) + ); JWT_DEV && logger_debug(`init: exists ${this._id}`); if (parent) { @@ -83,19 +101,11 @@ export class AbstractBlock< name: string, callback: BlockListener ) { - if (event === 'parent') { - this._parentListener.set(name, callback); - } else { - this._block.on(event, name, callback); - } + this._listeners[event]?.set(name, callback); } public off(event: 'content' | 'children' | 'parent', name: string) { - if (event === 'parent') { - this._parentListener.delete(name); - } else { - this._block.off(event, name); - } + this._listeners[event]?.delete(name); } public addChildrenListener(name: string, listener: BlockListener) { @@ -189,11 +199,24 @@ export class AbstractBlock< const states: Map = new Map([ [parentId, type], ]); - for (const listener of this._parentListener.values()) { + for (const listener of this._listeners.parent.values()) { listener(states); } } + [_EMIT_EVENT]( + event: 'cascade' | 'content' | 'children', + states: Parameters[0] + ) { + const listeners = this._listeners[event]; + if (listeners) { + for (const listener of listeners.values()) { + listener(states); + } + } + this._parent?.[_EMIT_EVENT]('cascade', states); + } + private _refreshParent(parent: AbstractBlock) { this._changeParent?.(); parent.addChildrenListener(this._id, states => { diff --git a/libs/datasource/jwt/src/block/indexer.ts b/libs/datasource/jwt/src/block/indexer.ts index ed57465dbc..cd430ce6d6 100644 --- a/libs/datasource/jwt/src/block/indexer.ts +++ b/libs/datasource/jwt/src/block/indexer.ts @@ -123,8 +123,8 @@ export class BlockIndexer< constructor( adapter: A, workspace: string, - block_builder: (block: BlockInstance) => Promise>, - event_bus: BlockEventBus + blockBuilder: (block: BlockInstance) => Promise>, + eventBus: BlockEventBus ) { this._adapter = adapter; this._idb = initIndexIdb(workspace); @@ -144,8 +144,8 @@ export class BlockIndexer< ttl: 1000 * 60 * 30, }); - this._blockBuilder = block_builder; - this._eventBus = event_bus; + this._blockBuilder = blockBuilder; + this._eventBus = eventBus; this._delayIndex = { documents: new Map() }; diff --git a/libs/datasource/jwt/src/index.ts b/libs/datasource/jwt/src/index.ts index e08bdc1e16..e8f3483e23 100644 --- a/libs/datasource/jwt/src/index.ts +++ b/libs/datasource/jwt/src/index.ts @@ -679,7 +679,7 @@ export type { ReadableContentExporter as BlockContentExporter, } from './block'; export { BlockTypes, BucketBackend as BlockBackend } from './types'; -export type { BlockTypeKeys } from './types'; +export type { BlockFlavorKeys, BlockTypeKeys } from './types'; export { isBlock } from './utils'; export type { ArrayOperation, From e19470397e12a0edb744fe1d209d317e6acfafab Mon Sep 17 00:00:00 2001 From: DarkSky Date: Wed, 24 Aug 2022 18:07:00 +0800 Subject: [PATCH 57/58] feat: filter --- libs/datasource/jwt/src/block/abstract.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libs/datasource/jwt/src/block/abstract.ts b/libs/datasource/jwt/src/block/abstract.ts index d2f117c62b..2d620e3296 100644 --- a/libs/datasource/jwt/src/block/abstract.ts +++ b/libs/datasource/jwt/src/block/abstract.ts @@ -199,13 +199,11 @@ export class AbstractBlock< const states: Map = new Map([ [parentId, type], ]); - for (const listener of this._listeners.parent.values()) { - listener(states); - } + this[_EMIT_EVENT]('parent', states); } [_EMIT_EVENT]( - event: 'cascade' | 'content' | 'children', + event: 'cascade' | 'content' | 'children' | 'parent', states: Parameters[0] ) { const listeners = this._listeners[event]; @@ -214,7 +212,10 @@ export class AbstractBlock< listener(states); } } - this._parent?.[_EMIT_EVENT]('cascade', states); + + if (['children', 'content'].includes(event)) { + this._parent?.[_EMIT_EVENT]('cascade', states); + } } private _refreshParent(parent: AbstractBlock) { From ae19fd9b00bf60b671c4182554689bdf27c269e6 Mon Sep 17 00:00:00 2001 From: DarkSky Date: Wed, 24 Aug 2022 18:13:58 +0800 Subject: [PATCH 58/58] feat: services --- libs/datasource/db-service/src/services/database/index.ts | 2 ++ libs/datasource/jwt/src/block/abstract.ts | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libs/datasource/db-service/src/services/database/index.ts b/libs/datasource/db-service/src/services/database/index.ts index 4ea5bbbace..d6d013a3d3 100644 --- a/libs/datasource/db-service/src/services/database/index.ts +++ b/libs/datasource/db-service/src/services/database/index.ts @@ -168,6 +168,7 @@ export class Database { block.on('children', observer_name, listener); block.on('content', observer_name, listener); block.on('parent', observer_name, listener); + block.on('cascade', observer_name, listener); } this.#observers.setStatus(observer_name, 'observing'); @@ -188,6 +189,7 @@ export class Database { block.off('children', observer_name); block.off('content', observer_name); block.off('parent', observer_name); + block.off('cascade', observer_name); } } } diff --git a/libs/datasource/jwt/src/block/abstract.ts b/libs/datasource/jwt/src/block/abstract.ts index 2d620e3296..d67c92bb68 100644 --- a/libs/datasource/jwt/src/block/abstract.ts +++ b/libs/datasource/jwt/src/block/abstract.ts @@ -97,14 +97,17 @@ export class AbstractBlock< } public on( - event: 'content' | 'children' | 'parent', + event: 'cascade' | 'content' | 'children' | 'parent', name: string, callback: BlockListener ) { this._listeners[event]?.set(name, callback); } - public off(event: 'content' | 'children' | 'parent', name: string) { + public off( + event: 'cascade' | 'content' | 'children' | 'parent', + name: string + ) { this._listeners[event]?.delete(name); }