diff --git a/package-lock.json b/package-lock.json index cb2b7c5a595..b34aa075745 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,9 +11,6 @@ "dependencies": { "@apollo/client": "^3.1.5", "@auth0/auth0-react": "^1.2.0", - "@draft-js-plugins/editor": "^4.1.0", - "@draft-js-plugins/emoji": "^4.2.0", - "@draft-js-plugins/mention": "^4.3.1", "@headlessui/react": "^1.4.1", "@heroicons/react": "^1.0.1", "@recordreplay/playwright": "^1.10.3", @@ -24,6 +21,10 @@ "@stripe/react-stripe-js": "^1.4.1", "@stripe/stripe-js": "^1.17.1", "@tailwindcss/forms": "^0.3.2", + "@tiptap/extension-mention": "^2.0.0-beta.75", + "@tiptap/extension-placeholder": "^2.0.0-beta.33", + "@tiptap/react": "^2.0.0-beta.81", + "@tiptap/starter-kit": "^2.0.0-beta.123", "apollo-link-http": "^1.5.17", "babel-plugin-add-react-displayname": "0.0.5", "base64-arraybuffer": "^0.2.0", @@ -34,7 +35,6 @@ "debug": "^4.2.0", "devtools-sprintf-js": "^1.0.3", "dotenv": "^10.0.0", - "draft-js": "^0.11.7", "escape-html": "^1.0.3", "fontfaceobserver": "^2.1.0", "graphql": "^15.3.0", @@ -85,7 +85,6 @@ "@babel/preset-typescript": "^7.14.5", "@babel/types": "^7.14.8", "@types/classnames": "^2.2.11", - "@types/draft-js": "^0.10.44", "@types/escape-html": "^1.0.1", "@types/lodash": "^4.14.168", "@types/logrocket-react": "^3.0.0", @@ -1102,79 +1101,6 @@ "node": ">=10.0.0" } }, - "node_modules/@draft-js-plugins/buttons": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@draft-js-plugins/buttons/-/buttons-4.1.0.tgz", - "integrity": "sha512-sGt5mSo6TwX53EYCHgF7KnwTJCT0OBHbWlvB0UG7aUSK2oiT2QD+z51o3d/BvM7105m/rdLA8WCeWW23tw771Q==", - "dependencies": { - "clsx": "^1.0.4" - }, - "peerDependencies": { - "draft-js": "^0.10.1 || ^0.11.0", - "react": "^15.5.0 || ^16.0.0 || ^17.0.0", - "react-dom": "^15.5.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@draft-js-plugins/editor": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@draft-js-plugins/editor/-/editor-4.1.0.tgz", - "integrity": "sha512-i95uGF1GOFwP99qRCjtocGAYanULtkX9/XPeXKwjKx65vnOt/0dvBBdSvzSgrJ9pncHHLUqDfFQKXy/09fTmvg==", - "dependencies": { - "immutable": "~3.7.4", - "prop-types": "^15.5.8" - }, - "peerDependencies": { - "draft-js": "^0.11.0", - "react": "^16.3.0 || ^17.0.0" - } - }, - "node_modules/@draft-js-plugins/emoji": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@draft-js-plugins/emoji/-/emoji-4.3.0.tgz", - "integrity": "sha512-OkuL/FdOLrrRTpOBRoDhIf8+7NSNueZBFe6YjT5pa5vyPmTBLKQZRbYPrn8tIYmGjQSP9fSWKPsdpjSwEkHr+Q==", - "dependencies": { - "@draft-js-plugins/buttons": "^4.0.0", - "@draft-js-plugins/utils": "^4.0.0", - "clsx": "^1.0.4", - "emoji-toolkit": "^6.5.1", - "emojibase": "^5.1.1", - "emojibase-data": "^6.1.2", - "find-with-regex": "^1.1.3", - "immutable": "~3.7.4", - "lodash-es": "^4.17.21", - "prop-types": "^15.5.8", - "react-custom-scrollbars": "^4.2.0", - "react-icons": "^4.2.0", - "to-style": "^1.3.3" - }, - "peerDependencies": { - "draft-js": "^0.10.1 || ^0.11.0", - "react": "^16.8.0 || ^17.0.0" - } - }, - "node_modules/@draft-js-plugins/mention": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@draft-js-plugins/mention/-/mention-4.3.1.tgz", - "integrity": "sha512-44UMpV+CTFvdm9rrMUudo/cCfnaiP03OwCLsvj0ECORogBhveVwnZc31ElDh1brlUwg3uEyVqhBjSoskZvapHQ==", - "dependencies": { - "clsx": "^1.0.4", - "immutable": "~3.7.4", - "lodash-es": "^4.17.21", - "prop-types": "^15.5.8" - }, - "peerDependencies": { - "draft-js": "^0.10.1 || ^0.11.0", - "react": "^16.3.0 || ^17.0.0" - } - }, - "node_modules/@draft-js-plugins/utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@draft-js-plugins/utils/-/utils-4.1.0.tgz", - "integrity": "sha512-bU1deEINlqHPX9+IqFyMT8EwDBsqn1o0C5U8VfhbVGXTuvTu/F0LI6XT2h7VD9ufoYK0s/BE6XBkyO+764Petg==", - "peerDependencies": { - "draft-js": "^0.10.1 || ^0.11.0" - } - }, "node_modules/@emotion/is-prop-valid": { "version": "0.8.8", "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", @@ -1334,6 +1260,15 @@ "node": ">= 8" } }, + "node_modules/@popperjs/core": { + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.2.tgz", + "integrity": "sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@recordreplay/playwright": { "version": "1.10.4", "resolved": "https://registry.npmjs.org/@recordreplay/playwright/-/playwright-1.10.4.tgz", @@ -1597,6 +1532,399 @@ "tailwindcss": ">=2.0.0" } }, + "node_modules/@tiptap/core": { + "version": "2.0.0-beta.122", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.0.0-beta.122.tgz", + "integrity": "sha512-kuEYMfAV+2lO/QyL6yerfJo2fI9wnYCPvIJgpj9sTB0WeXl8ZiD53POlBZM0MEKqmUCtw5kqnGffnsEzSK7jGQ==", + "dependencies": { + "@types/prosemirror-commands": "^1.0.4", + "@types/prosemirror-keymap": "^1.0.4", + "@types/prosemirror-model": "^1.13.2", + "@types/prosemirror-schema-list": "^1.0.3", + "@types/prosemirror-state": "^1.2.7", + "@types/prosemirror-transform": "^1.1.4", + "@types/prosemirror-view": "^1.19.1", + "prosemirror-commands": "^1.1.11", + "prosemirror-keymap": "^1.1.3", + "prosemirror-model": "^1.14.3", + "prosemirror-schema-list": "^1.1.6", + "prosemirror-state": "^1.3.4", + "prosemirror-transform": "^1.3.3", + "prosemirror-view": "^1.20.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + } + }, + "node_modules/@tiptap/extension-blockquote": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.0.0-beta.17.tgz", + "integrity": "sha512-mn94P3TO6LFCvn/LEgAbZrtKWLJw3YQgGiI3Doa67DGUXeID0nlyu+5iVTHUOdMXtqWbYgRW8HGjVgdyo5G5cw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-bold": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-2.0.0-beta.17.tgz", + "integrity": "sha512-17XOOasNK7sB6UdxDquF0s7Pdaitr165d3mwPrTETeQytS7cCnGpIjwg3rvp+LNgZMKEC4mxrBob8WxA7uK8Mg==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-bubble-menu": { + "version": "2.0.0-beta.40", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.40.tgz", + "integrity": "sha512-1bMuQ7747IPvvoy1GLoX/iwmleIWRH7maEi8K2MTB0wsN4pjnuRjua0LdNMMM5i4/ZE/qYehNtpHeJfwIrFnhQ==", + "dependencies": { + "prosemirror-state": "^1.3.4", + "prosemirror-view": "^1.20.2", + "tippy.js": "^6.3.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-bullet-list": { + "version": "2.0.0-beta.16", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.0-beta.16.tgz", + "integrity": "sha512-+L4/Oeey1wqYwN2KGFfsw2K7qfn81FSNElRylhcG2RueqFnMgiaeigPDDIHT5xOqUQ0cyWsJxHoQOaKw4h2bPA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-code": { + "version": "2.0.0-beta.18", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-2.0.0-beta.18.tgz", + "integrity": "sha512-d/QKmcCFwoYxoI+UPhB3Bb2EIFERw5MXZpNUxjnY3hDZfqA7AgXj6wiHS6RkQSeLgnQEULWRvtMU0J+Uvo0z6A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-code-block": { + "version": "2.0.0-beta.21", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-2.0.0-beta.21.tgz", + "integrity": "sha512-2D/aW3DqfvwmWWNY5z9LncXawkd4iyEtAXJ6a+b4F7K022z7wNloPicXEA/mKyyiYNezhTiN84aVdUVsnGsgAg==", + "dependencies": { + "prosemirror-state": "^1.3.4" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-document": { + "version": "2.0.0-beta.13", + "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.0.0-beta.13.tgz", + "integrity": "sha512-nrufdKziA/wovaY4DjGkc8OGuIZi8CH8CW3+yYfeWbruwFKkyZHlZy9nplFWSEqBHPAeqD+px9r91yGMW3ontA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-dropcursor": { + "version": "2.0.0-beta.19", + "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-2.0.0-beta.19.tgz", + "integrity": "sha512-rslIcVvD42NNh5sEbkCkG03DWMFBrS5KoK+lDOdIcC1DjmTtpVgcLvvE01btzaB3ljx+UVqI2Zaxa6VOiTeEMw==", + "dependencies": { + "@types/prosemirror-dropcursor": "^1.0.3", + "prosemirror-dropcursor": "^1.3.5" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-floating-menu": { + "version": "2.0.0-beta.34", + "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.34.tgz", + "integrity": "sha512-WheIsmcTy3+4j9qHoaRdFzdczqSXZVPOPytEq81zwMz7GuWA+Oom3egkvmW1gc1gv5gR+bGklWhm+l0ML2D7qA==", + "dependencies": { + "prosemirror-state": "^1.3.4", + "prosemirror-view": "^1.20.2", + "tippy.js": "^6.3.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-gapcursor": { + "version": "2.0.0-beta.25", + "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-2.0.0-beta.25.tgz", + "integrity": "sha512-dmow1C822DFfLhe+0bIRsdjTWjjzPeq2j9zpo2IaE54rMTfGVvrOPNe51OZ2KgpPob7iTilgaOZDTrnUW6ialw==", + "dependencies": { + "@types/prosemirror-gapcursor": "^1.0.4", + "prosemirror-gapcursor": "^1.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-hard-break": { + "version": "2.0.0-beta.22", + "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.0.0-beta.22.tgz", + "integrity": "sha512-ofoOBwjqcQJ2QCzAERPvwXOzTuf7lVuMb2soUUOyjIuwqXidGC30aY2peOnVGsFsdYNjeprOejE//ud7pg/3sA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-heading": { + "version": "2.0.0-beta.16", + "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.0.0-beta.16.tgz", + "integrity": "sha512-z9NsabhyqIct8S12LdJ7XGGt73jlzwjDjqyc/g5AhEPZWNJ6k4yvcsGk+t6hEatK5O6ELs1gdeCOCElP0OqA8A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-history": { + "version": "2.0.0-beta.16", + "resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.0.0-beta.16.tgz", + "integrity": "sha512-nrNwV8a7zUt1t2I/kPX5Y6N9vZ8mrugimJIQmPGIp/4mmw1SEUzkaPpIsv6+ELmqMHSDktQ0ofb3pXeWDXWZvw==", + "dependencies": { + "@types/prosemirror-history": "^1.0.3", + "prosemirror-history": "^1.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-horizontal-rule": { + "version": "2.0.0-beta.22", + "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.0.0-beta.22.tgz", + "integrity": "sha512-v9PFi8hxCBRMXCk5lK35sHetw95IzqjZ9ttkdgro2JfeDdOfFG7FylOrXriFvfKHCpbU2TNbZLud+fg8MXVPtQ==", + "dependencies": { + "prosemirror-state": "^1.3.4" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-italic": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-2.0.0-beta.17.tgz", + "integrity": "sha512-rtbijLCunCp2xyvUxDcYJDErMn0EwZ+PUBYWBzCG1WpxxvsaqC+/yoj8mBKlxW1Dob/uFGkJnyMCZrhXMwW3iQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-list-item": { + "version": "2.0.0-beta.14", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.0.0-beta.14.tgz", + "integrity": "sha512-t6xwEqP+d5443Ul2Jvqz9kXb3ro7bA7yY9HA0vskm3120WxxHW9jxgxZN+82Ot5Tm7nXOAlsN6vuqnt4idnxZQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-mention": { + "version": "2.0.0-beta.75", + "resolved": "https://registry.npmjs.org/@tiptap/extension-mention/-/extension-mention-2.0.0-beta.75.tgz", + "integrity": "sha512-BEhGFh6R7T6R13A64C7wRwM0quHrMV09VI6yXxy1MRYjpYUojPfh7YUeFMstKTx+yI3Bb4lNf7xDygKDSivVWw==", + "dependencies": { + "@tiptap/suggestion": "^2.0.0-beta.72", + "prosemirror-model": "^1.14.3", + "prosemirror-state": "^1.3.4" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-ordered-list": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-2.0.0-beta.17.tgz", + "integrity": "sha512-gPAtg8nLdmGMgtdz6wVX6rVO/IpzrB3JyF8VBfKjwB0poQiGjEsSpQngWam7wokIuDYtMZuitUwmhVDBvGrNqw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-paragraph": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.0.0-beta.17.tgz", + "integrity": "sha512-qCQVCf9c2hgaeIdfy22PaoZyW5Vare/1aGkOEAaZma5RjrUbV9hrRKwoW9LsDjnh1EN1fIeKdg02yEhnHWtG8A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-placeholder": { + "version": "2.0.0-beta.33", + "resolved": "https://registry.npmjs.org/@tiptap/extension-placeholder/-/extension-placeholder-2.0.0-beta.33.tgz", + "integrity": "sha512-qn9XxYDiepF/uS0u45Jz8Ro+Ki6MuwK4AY+AgNTFh3VgfJj6qUXD0B1yU5XxKLXLfrfDPFQ+saOKuPoipF5GXw==", + "dependencies": { + "prosemirror-model": "^1.14.3", + "prosemirror-state": "^1.3.4", + "prosemirror-view": "^1.20.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-strike": { + "version": "2.0.0-beta.19", + "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.0.0-beta.19.tgz", + "integrity": "sha512-vRcUW6YkFcb535MgdEotwoqnrbhlsUoZ7nKoZ5MNA+Nu6rXRAz5VXaHncFNpWM77WcEbuaOKvcGolkMK1q2BIw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/extension-text": { + "version": "2.0.0-beta.13", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.0.0-beta.13.tgz", + "integrity": "sha512-0EtAwuRldCAoFaL/iXgkRepEeOd55rPg5N4FQUN1xTwZT7PDofukP0DG/2jff/Uj17x4uTaJAa9qlFWuNnDvjw==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, + "node_modules/@tiptap/react": { + "version": "2.0.0-beta.81", + "resolved": "https://registry.npmjs.org/@tiptap/react/-/react-2.0.0-beta.81.tgz", + "integrity": "sha512-bYriarBAHA9iOj8o9edcstTiJnkwwSDsYfIZ+FmcaTLV7sJUMvp+UieEF9gPZpd/zI98Mf13Lmb4u+FT+hssGg==", + "dependencies": { + "@tiptap/extension-bubble-menu": "^2.0.0-beta.40", + "@tiptap/extension-floating-menu": "^2.0.0-beta.34", + "prosemirror-view": "^1.20.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1", + "react": "^17.0.0", + "react-dom": "^17.0.0" + } + }, + "node_modules/@tiptap/starter-kit": { + "version": "2.0.0-beta.123", + "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-2.0.0-beta.123.tgz", + "integrity": "sha512-r46ChIuthSecoozfRATPqRUffU8t1tVycAwH+0zdpJVtBmMiVV8hHp0otasvFn5w7d38MbaYHGEaH40myc2mrg==", + "dependencies": { + "@tiptap/core": "^2.0.0-beta.122", + "@tiptap/extension-blockquote": "^2.0.0-beta.17", + "@tiptap/extension-bold": "^2.0.0-beta.17", + "@tiptap/extension-bullet-list": "^2.0.0-beta.16", + "@tiptap/extension-code": "^2.0.0-beta.18", + "@tiptap/extension-code-block": "^2.0.0-beta.21", + "@tiptap/extension-document": "^2.0.0-beta.13", + "@tiptap/extension-dropcursor": "^2.0.0-beta.19", + "@tiptap/extension-gapcursor": "^2.0.0-beta.25", + "@tiptap/extension-hard-break": "^2.0.0-beta.22", + "@tiptap/extension-heading": "^2.0.0-beta.16", + "@tiptap/extension-history": "^2.0.0-beta.16", + "@tiptap/extension-horizontal-rule": "^2.0.0-beta.22", + "@tiptap/extension-italic": "^2.0.0-beta.17", + "@tiptap/extension-list-item": "^2.0.0-beta.14", + "@tiptap/extension-ordered-list": "^2.0.0-beta.17", + "@tiptap/extension-paragraph": "^2.0.0-beta.17", + "@tiptap/extension-strike": "^2.0.0-beta.19", + "@tiptap/extension-text": "^2.0.0-beta.13" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + } + }, + "node_modules/@tiptap/suggestion": { + "version": "2.0.0-beta.72", + "resolved": "https://registry.npmjs.org/@tiptap/suggestion/-/suggestion-2.0.0-beta.72.tgz", + "integrity": "sha512-DwImLQpl0KR1fySV2g84AGviDiryo40fwCXxwzpMXpn0rcEVEdh616eQGEOWCvC3NIY2RdB4KVpbYcMnXCZxFw==", + "dependencies": { + "prosemirror-model": "^1.14.3", + "prosemirror-state": "^1.3.4", + "prosemirror-view": "^1.20.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0-beta.1" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", @@ -1633,16 +1961,6 @@ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, - "node_modules/@types/draft-js": { - "version": "0.10.44", - "resolved": "https://registry.npmjs.org/@types/draft-js/-/draft-js-0.10.44.tgz", - "integrity": "sha512-6p3FZED91yPf+KQinlzFz1HuqSQ5zRXqU3RUsaP2oQYZTtrm5HDf2kwYnF5IihsleHR3jlQAwdSZt0zlJw3VGQ==", - "dev": true, - "dependencies": { - "@types/react": "*", - "immutable": "~3.7.4" - } - }, "node_modules/@types/escape-html": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/escape-html/-/escape-html-1.0.1.tgz", @@ -1766,6 +2084,11 @@ "integrity": "sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA==", "devOptional": true }, + "node_modules/@types/orderedmap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/orderedmap/-/orderedmap-1.0.0.tgz", + "integrity": "sha512-dxKo80TqYx3YtBipHwA/SdFmMMyLCnP+5mkEqN0eMjcTBzHkiiX0ES118DsjDBjvD+zeSsSU9jULTZ+frog+Gw==" + }, "node_modules/@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", @@ -1777,6 +2100,99 @@ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" }, + "node_modules/@types/prosemirror-commands": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/prosemirror-commands/-/prosemirror-commands-1.0.4.tgz", + "integrity": "sha512-utDNYB3EXLjAfYIcRWJe6pn3kcQ5kG4RijbT/0Y/TFOm6yhvYS/D9eJVnijdg9LDjykapcezchxGRqFD5LcyaQ==", + "dependencies": { + "@types/prosemirror-model": "*", + "@types/prosemirror-state": "*", + "@types/prosemirror-view": "*" + } + }, + "node_modules/@types/prosemirror-dropcursor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/prosemirror-dropcursor/-/prosemirror-dropcursor-1.0.3.tgz", + "integrity": "sha512-b0/8njnJ4lwyHKcGuCMf3x7r1KjxyugB1R/c2iMCjplsJHSC7UY9+OysqgJR5uUXRekUSGniiLgBtac/lvH6wg==", + "dependencies": { + "@types/prosemirror-state": "*" + } + }, + "node_modules/@types/prosemirror-gapcursor": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/prosemirror-gapcursor/-/prosemirror-gapcursor-1.0.4.tgz", + "integrity": "sha512-9xKjFIG5947dzerFvkLWp6F53JwrUYoYwh3SgcTFEp8SbSfNNrez/PFYVZKPnoqPoaK5WtTdQTaMwpCV9rXQIg==", + "dependencies": { + "@types/prosemirror-model": "*", + "@types/prosemirror-state": "*" + } + }, + "node_modules/@types/prosemirror-history": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/prosemirror-history/-/prosemirror-history-1.0.3.tgz", + "integrity": "sha512-5TloMDRavgLjOAKXp1Li8u0xcsspzbT1Cm9F2pwHOkgvQOz1jWQb2VIXO7RVNsFjLBZdIXlyfSLivro3DuMWXg==", + "dependencies": { + "@types/prosemirror-model": "*", + "@types/prosemirror-state": "*" + } + }, + "node_modules/@types/prosemirror-keymap": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/prosemirror-keymap/-/prosemirror-keymap-1.0.4.tgz", + "integrity": "sha512-ycevwkqUh+jEQtPwqO7sWGcm+Sybmhu8MpBsM8DlO3+YTKnXbKA6SDz/+q14q1wK3UA8lHJyfR+v+GPxfUSemg==", + "dependencies": { + "@types/prosemirror-commands": "*", + "@types/prosemirror-model": "*", + "@types/prosemirror-state": "*", + "@types/prosemirror-view": "*" + } + }, + "node_modules/@types/prosemirror-model": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@types/prosemirror-model/-/prosemirror-model-1.13.2.tgz", + "integrity": "sha512-a2rDB0aZ+7aIP7uBqQq1wLb4Hg4qqEvpkCqvhsgT/gG8IWC0peCAZfQ24sgTco0qSJLeDgIbtPeU6mgr869/kg==", + "dependencies": { + "@types/orderedmap": "*" + } + }, + "node_modules/@types/prosemirror-schema-list": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/prosemirror-schema-list/-/prosemirror-schema-list-1.0.3.tgz", + "integrity": "sha512-uWybOf+M2Ea7rlbs0yLsS4YJYNGXYtn4N+w8HCw3Vvfl6wBAROzlMt0gV/D/VW/7J/LlAjwMezuGe8xi24HzXA==", + "dependencies": { + "@types/orderedmap": "*", + "@types/prosemirror-model": "*", + "@types/prosemirror-state": "*" + } + }, + "node_modules/@types/prosemirror-state": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/prosemirror-state/-/prosemirror-state-1.2.7.tgz", + "integrity": "sha512-clJf5uw3/XQnBJtl2RqYXoLMGBySnLYl43xtDvFfQZKkLnnYcM1SDU8dcz7lWjl2Dm+H98RpLOl44pp7DYT+wA==", + "dependencies": { + "@types/prosemirror-model": "*", + "@types/prosemirror-transform": "*", + "@types/prosemirror-view": "*" + } + }, + "node_modules/@types/prosemirror-transform": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/prosemirror-transform/-/prosemirror-transform-1.1.4.tgz", + "integrity": "sha512-HP1PauvkqSgDquZut8HaLOTUDQ6jja/LAy4OA7tTS1XG7wqRnX3gLUyEj0mD6vFd4y8BPkNddNdOh/BeGHlUjg==", + "dependencies": { + "@types/prosemirror-model": "*" + } + }, + "node_modules/@types/prosemirror-view": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/@types/prosemirror-view/-/prosemirror-view-1.19.1.tgz", + "integrity": "sha512-fyQ4NVxAdfISWrE2qT8cpZdosXoH/1JuVYMBs9CdaXPbvi/8R2L2tkkcMRM314piKrO8nfYH5OBZKzP2Ax3jtA==", + "dependencies": { + "@types/prosemirror-model": "*", + "@types/prosemirror-state": "*", + "@types/prosemirror-transform": "*" + } + }, "node_modules/@types/react": { "version": "16.9.55", "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.55.tgz", @@ -2390,11 +2806,6 @@ "node": ">=0.4.0" } }, - "node_modules/add-px-to-style": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/add-px-to-style/-/add-px-to-style-1.0.0.tgz", - "integrity": "sha1-0ME1RB+oAUqBN5BFMQlvZ/KPJjo=" - }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -2712,11 +3123,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" - }, "node_modules/asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -3675,14 +4081,6 @@ "node": ">=6" } }, - "node_modules/clsx": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", - "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==", - "engines": { - "node": ">=6" - } - }, "node_modules/code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -4196,14 +4594,6 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, - "node_modules/cross-fetch": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.6.tgz", - "integrity": "sha512-KBPUbqgFjzWlVcURG+Svp9TlhA5uliYtiNx/0r8nv0pdypeQCRJ9IaSIc3q/x3q8t3F75cHuwxVql1HFGHCNJQ==", - "dependencies": { - "node-fetch": "2.6.1" - } - }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -4910,16 +5300,6 @@ "utila": "~0.4" } }, - "node_modules/dom-css": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/dom-css/-/dom-css-2.1.0.tgz", - "integrity": "sha1-/bwtWgFdCj4YcuEUcrvQ57nmogI=", - "dependencies": { - "add-px-to-style": "1.0.0", - "prefix-style": "2.0.1", - "to-camel-case": "1.0.0" - } - }, "node_modules/dom-helpers": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", @@ -5043,28 +5423,6 @@ "node": ">=10" } }, - "node_modules/draft-js": { - "version": "0.11.7", - "resolved": "https://registry.npmjs.org/draft-js/-/draft-js-0.11.7.tgz", - "integrity": "sha512-ne7yFfN4sEL82QPQEn80xnADR8/Q6ALVworbC5UOSzOvjffmYfFsr3xSZtxbIirti14R7Y33EZC5rivpLgIbsg==", - "dependencies": { - "fbjs": "^2.0.0", - "immutable": "~3.7.4", - "object-assign": "^4.1.1" - }, - "peerDependencies": { - "react": ">=0.14.0", - "react-dom": ">=0.14.0" - } - }, - "node_modules/draft-js/node_modules/immutable": { - "version": "3.7.6", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", - "integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks=", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -5104,32 +5462,6 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, - "node_modules/emoji-toolkit": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/emoji-toolkit/-/emoji-toolkit-6.5.1.tgz", - "integrity": "sha512-oY5E81cXvRUxXkbVgOI8NxYHKF5FeWfJhFCIYUKhbVfSmdCH8+bmJzgDdhufExa7t1+WEzpUFdHwYxJTXS90vQ==" - }, - "node_modules/emojibase": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/emojibase/-/emojibase-5.1.1.tgz", - "integrity": "sha512-qc/qfuzZ93xmYMhnVA15yP2k3t4zJvBbqCc8dpDXFf75eJ+IogbzJuWQur8fkwsZ0u7YvJDBh939F9DapQqktQ==", - "funding": { - "type": "ko-fi", - "url": "https://ko-fi.com/milesjohnson" - } - }, - "node_modules/emojibase-data": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/emojibase-data/-/emojibase-data-6.1.2.tgz", - "integrity": "sha512-1fYgpAYkAJq7bmGO3XboP0dQHrtRiyWrAluCmv5NHSK1nruz0x8kXhpLiz48rAJGDQOWYUpLGaPASTNXVZX87Q==", - "funding": { - "type": "ko-fi", - "url": "https://ko-fi.com/milesjohnson" - }, - "peerDependencies": { - "emojibase": "*" - } - }, "node_modules/emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", @@ -6486,36 +6818,6 @@ "node": ">=0.8.0" } }, - "node_modules/fbjs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-2.0.0.tgz", - "integrity": "sha512-8XA8ny9ifxrAWlyhAbexXcs3rRMtxWcs3M0lctLfB49jRDHiaxj+Mo0XxbwE7nKZYzgCFoq64FS+WFd4IycPPQ==", - "dependencies": { - "core-js": "^3.6.4", - "cross-fetch": "^3.0.4", - "fbjs-css-vars": "^1.0.0", - "loose-envify": "^1.0.0", - "object-assign": "^4.1.0", - "promise": "^7.1.1", - "setimmediate": "^1.0.5", - "ua-parser-js": "^0.7.18" - } - }, - "node_modules/fbjs-css-vars": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", - "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" - }, - "node_modules/fbjs/node_modules/core-js": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.3.tgz", - "integrity": "sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q==", - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, "node_modules/fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -6723,14 +7025,6 @@ "node": ">=4" } }, - "node_modules/find-with-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/find-with-regex/-/find-with-regex-1.1.3.tgz", - "integrity": "sha512-zkEVQ1H3PIQL/19ADKt1lCQU4QGM3OneiderUcFgn5EgTm/TnoUh7HxPAwP8w/vXxWSLC6KtpbDQpypJ5+majw==", - "peerDependencies": { - "draft-js": "^0.10.5" - } - }, "node_modules/flat-cache": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", @@ -7674,14 +7968,6 @@ "node": ">= 4" } }, - "node_modules/immutable": { - "version": "3.7.6", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", - "integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks=", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -8873,11 +9159,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" - }, "node_modules/lodash-move": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/lodash-move/-/lodash-move-1.1.1.tgz", @@ -9538,14 +9819,6 @@ "lodash.toarray": "^4.4.0" } }, - "node_modules/node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", - "engines": { - "node": "4.x || >=6.0.0" - } - }, "node_modules/node-forge": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", @@ -9986,6 +10259,11 @@ "node": ">= 0.8.0" } }, + "node_modules/orderedmap": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-1.1.1.tgz", + "integrity": "sha512-3Ux8um0zXbVacKUkcytc0u3HgC0b0bBLT+I60r2J/En72cI0nZffqrA7Xtf2Hqs27j1g82llR5Mhbd0Z1XW4AQ==" + }, "node_modules/original": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", @@ -10354,11 +10632,6 @@ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, "node_modules/picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", @@ -10822,11 +11095,6 @@ "simple-concat": "^1.0.0" } }, - "node_modules/prefix-style": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/prefix-style/-/prefix-style-2.0.1.tgz", - "integrity": "sha1-ZrupqHDP2jCKXcIOhekSCTLJWgY=" - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -10899,14 +11167,6 @@ "node": ">=0.4.0" } }, - "node_modules/promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "dependencies": { - "asap": "~2.0.3" - } - }, "node_modules/promise-polyfill": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.2.0.tgz", @@ -10943,6 +11203,100 @@ "node": ">= 0.3.1" } }, + "node_modules/prosemirror-commands": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.1.11.tgz", + "integrity": "sha512-uXDVkOGJbFHocdacMJihrnQCT7tHswO48ewq6ByqLxTwOrI8Y4B4aHvwUbM4epwElv/YjgC+DuqXm/gEHPym4w==", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-dropcursor": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.3.5.tgz", + "integrity": "sha512-tNUwcF2lPAkwKBZPZRtbxpwljnODRNZ3eiYloN1DSUqDjMT1nBZm0nejaEMS1TvNQ+3amibUSAiV4hX+jpASFA==", + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0", + "prosemirror-view": "^1.1.0" + } + }, + "node_modules/prosemirror-gapcursor": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.2.0.tgz", + "integrity": "sha512-yCLy5+0rVqLir/KcHFathQj4Rf8aRHi80FmEfKtM0JmyzvwdomslLzDZ/pX4oFhFKDgjl/WBBBFNqDyNifWg7g==", + "dependencies": { + "prosemirror-keymap": "^1.0.0", + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-view": "^1.0.0" + } + }, + "node_modules/prosemirror-history": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.2.0.tgz", + "integrity": "sha512-B9v9xtf4fYbKxQwIr+3wtTDNLDZcmMMmGiI3TAPShnUzvo+Rmv1GiUrsQChY1meetHl7rhML2cppF3FTs7f7UQ==", + "dependencies": { + "prosemirror-state": "^1.2.2", + "prosemirror-transform": "^1.0.0", + "rope-sequence": "^1.3.0" + } + }, + "node_modules/prosemirror-keymap": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.1.4.tgz", + "integrity": "sha512-Al8cVUOnDFL4gcI5IDlG6xbZ0aOD/i3B17VT+1JbHWDguCgt/lBHVTHUBcKvvbSg6+q/W4Nj1Fu6bwZSca3xjg==", + "dependencies": { + "prosemirror-state": "^1.0.0", + "w3c-keyname": "^2.2.0" + } + }, + "node_modules/prosemirror-model": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.14.3.tgz", + "integrity": "sha512-yzZlBaSxfUPIIP6U5Edh5zKxJPZ5f7bwZRhiCuH3UYkWhj+P3d8swHsbuAMOu/iDatDc5J/Qs5Mb3++mZf+CvQ==", + "dependencies": { + "orderedmap": "^1.1.0" + } + }, + "node_modules/prosemirror-schema-list": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.1.6.tgz", + "integrity": "sha512-aFGEdaCWmJzouZ8DwedmvSsL50JpRkqhQ6tcpThwJONVVmCgI36LJHtoQ4VGZbusMavaBhXXr33zyD2IVsTlkw==", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-state": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.3.4.tgz", + "integrity": "sha512-Xkkrpd1y/TQ6HKzN3agsQIGRcLckUMA9u3j207L04mt8ToRgpGeyhbVv0HI7omDORIBHjR29b7AwlATFFf2GLA==", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-transform": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.3.3.tgz", + "integrity": "sha512-9NLVXy1Sfa2G6qPqhWMkEvwQQMTw7OyTqOZbJaGQWsCeH3hH5Cw+c5eNaLM1Uu75EyKLsEZhJ93XpHJBa6RX8A==", + "dependencies": { + "prosemirror-model": "^1.0.0" + } + }, + "node_modules/prosemirror-view": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.20.3.tgz", + "integrity": "sha512-2ImL9K/tIEk+aC2GT8shzfmT2U0Y8UQZ13L5AY0A4Tcj09o/ICGE362gKUE3Ze/Xr/nMw61Zv5JMSQUszAj9dw==", + "dependencies": { + "prosemirror-model": "^1.14.3", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -11071,14 +11425,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "dependencies": { - "performance-now": "^2.1.0" - } - }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -11251,23 +11597,9 @@ "node_modules/react-circular-progressbar": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/react-circular-progressbar/-/react-circular-progressbar-2.0.4.tgz", - "integrity": "sha512-OfX0ThSxRYEVGaQSt0DlXfyl5w4DbXHsXetyeivmoQrh9xA9bzVPHNf8aAhOIiwiaxX2WYWpLDB3gcpsDJ9oww==", - "peerDependencies": { - "react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/react-custom-scrollbars": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/react-custom-scrollbars/-/react-custom-scrollbars-4.2.1.tgz", - "integrity": "sha1-gw/ZUCkn6X6KeMIIaBOJmyqLZts=", - "dependencies": { - "dom-css": "^2.0.0", - "prop-types": "^15.5.10", - "raf": "^3.1.0" - }, + "integrity": "sha512-OfX0ThSxRYEVGaQSt0DlXfyl5w4DbXHsXetyeivmoQrh9xA9bzVPHNf8aAhOIiwiaxX2WYWpLDB3gcpsDJ9oww==", "peerDependencies": { - "react": "^0.14.0 || ^15.0.0 || ^16.0.0", - "react-dom": "^0.14.0 || ^15.0.0 || ^16.0.0" + "react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "node_modules/react-devtools-inline": { @@ -11293,14 +11625,6 @@ "resolved": "https://registry.npmjs.org/react-dom-factories/-/react-dom-factories-1.0.2.tgz", "integrity": "sha1-63cFxNs2+1AbOqOP91lhaqD/luA=" }, - "node_modules/react-icons": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.2.0.tgz", - "integrity": "sha512-rmzEDFt+AVXRzD7zDE21gcxyBizD/3NqjbX6cmViAgdqfJ2UiLer8927/QhhrXQV7dEj/1EGuOTPp7JnLYVJKQ==", - "peerDependencies": { - "react": "*" - } - }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -11877,6 +12201,11 @@ "inherits": "^2.0.1" } }, + "node_modules/rope-sequence": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.2.tgz", + "integrity": "sha512-ku6MFrwEVSVmXLvy3dYph3LAMNS0890K7fabn+0YIRQ2T96T9F4gkFf0vf0WW0JUraNWwGRtInEpH7yO4tbQZg==" + }, "node_modules/run-parallel": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", @@ -12141,7 +12470,8 @@ "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true }, "node_modules/setprototypeof": { "version": "1.1.1", @@ -13580,12 +13910,12 @@ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, - "node_modules/to-camel-case": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-camel-case/-/to-camel-case-1.0.0.tgz", - "integrity": "sha1-GlYFSy+daWKYzmamCJcyK29CPkY=", + "node_modules/tippy.js": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.2.tgz", + "integrity": "sha512-35XVQI7Zl/jHZ51+8eHu/vVRXBjWYGobPm5G9FxOchj4r5dWhghKGS0nm0ARUKZTF96V7pPn7EbXS191NTwldw==", "dependencies": { - "to-space-case": "^1.0.0" + "@popperjs/core": "^2.9.0" } }, "node_modules/to-fast-properties": { @@ -13596,11 +13926,6 @@ "node": ">=4" } }, - "node_modules/to-no-case": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz", - "integrity": "sha1-xyKQcWTvaxeBMsjmmTAhLRtKoWo=" - }, "node_modules/to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -13653,19 +13978,6 @@ "node": ">=0.10.0" } }, - "node_modules/to-space-case": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-space-case/-/to-space-case-1.0.0.tgz", - "integrity": "sha1-sFLar7Gysp3HcM6gFj5ewOvJ/Bc=", - "dependencies": { - "to-no-case": "^1.0.0" - } - }, - "node_modules/to-style": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/to-style/-/to-style-1.3.3.tgz", - "integrity": "sha1-Y6K3Cm9KfU/cLtV6C+TnI1y2aZw=" - }, "node_modules/toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", @@ -13872,14 +14184,6 @@ "node": ">=4.2.0" } }, - "node_modules/ua-parser-js": { - "version": "0.7.23", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.23.tgz", - "integrity": "sha512-m4hvMLxgGHXG3O3fQVAyyAQpZzDOvwnhOTjYz5Xmr7r/+LpkNy3vJXdVRWgd1TkAb7NGROZuSy96CrlNVjA7KA==", - "engines": { - "node": "*" - } - }, "node_modules/unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", @@ -14296,6 +14600,11 @@ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", "dev": true }, + "node_modules/w3c-keyname": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.4.tgz", + "integrity": "sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw==" + }, "node_modules/watchpack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.2.0.tgz", @@ -16012,60 +16321,6 @@ "integrity": "sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g==", "dev": true }, - "@draft-js-plugins/buttons": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@draft-js-plugins/buttons/-/buttons-4.1.0.tgz", - "integrity": "sha512-sGt5mSo6TwX53EYCHgF7KnwTJCT0OBHbWlvB0UG7aUSK2oiT2QD+z51o3d/BvM7105m/rdLA8WCeWW23tw771Q==", - "requires": { - "clsx": "^1.0.4" - } - }, - "@draft-js-plugins/editor": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@draft-js-plugins/editor/-/editor-4.1.0.tgz", - "integrity": "sha512-i95uGF1GOFwP99qRCjtocGAYanULtkX9/XPeXKwjKx65vnOt/0dvBBdSvzSgrJ9pncHHLUqDfFQKXy/09fTmvg==", - "requires": { - "immutable": "~3.7.4", - "prop-types": "^15.5.8" - } - }, - "@draft-js-plugins/emoji": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/@draft-js-plugins/emoji/-/emoji-4.3.0.tgz", - "integrity": "sha512-OkuL/FdOLrrRTpOBRoDhIf8+7NSNueZBFe6YjT5pa5vyPmTBLKQZRbYPrn8tIYmGjQSP9fSWKPsdpjSwEkHr+Q==", - "requires": { - "@draft-js-plugins/buttons": "^4.0.0", - "@draft-js-plugins/utils": "^4.0.0", - "clsx": "^1.0.4", - "emoji-toolkit": "^6.5.1", - "emojibase": "^5.1.1", - "emojibase-data": "^6.1.2", - "find-with-regex": "^1.1.3", - "immutable": "~3.7.4", - "lodash-es": "^4.17.21", - "prop-types": "^15.5.8", - "react-custom-scrollbars": "^4.2.0", - "react-icons": "^4.2.0", - "to-style": "^1.3.3" - } - }, - "@draft-js-plugins/mention": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/@draft-js-plugins/mention/-/mention-4.3.1.tgz", - "integrity": "sha512-44UMpV+CTFvdm9rrMUudo/cCfnaiP03OwCLsvj0ECORogBhveVwnZc31ElDh1brlUwg3uEyVqhBjSoskZvapHQ==", - "requires": { - "clsx": "^1.0.4", - "immutable": "~3.7.4", - "lodash-es": "^4.17.21", - "prop-types": "^15.5.8" - } - }, - "@draft-js-plugins/utils": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@draft-js-plugins/utils/-/utils-4.1.0.tgz", - "integrity": "sha512-bU1deEINlqHPX9+IqFyMT8EwDBsqn1o0C5U8VfhbVGXTuvTu/F0LI6XT2h7VD9ufoYK0s/BE6XBkyO+764Petg==", - "requires": {} - }, "@emotion/is-prop-valid": { "version": "0.8.8", "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", @@ -16189,6 +16444,11 @@ "fastq": "^1.6.0" } }, + "@popperjs/core": { + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.2.tgz", + "integrity": "sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ==" + }, "@recordreplay/playwright": { "version": "1.10.4", "resolved": "https://registry.npmjs.org/@recordreplay/playwright/-/playwright-1.10.4.tgz", @@ -16365,6 +16625,234 @@ "mini-svg-data-uri": "^1.2.3" } }, + "@tiptap/core": { + "version": "2.0.0-beta.122", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.0.0-beta.122.tgz", + "integrity": "sha512-kuEYMfAV+2lO/QyL6yerfJo2fI9wnYCPvIJgpj9sTB0WeXl8ZiD53POlBZM0MEKqmUCtw5kqnGffnsEzSK7jGQ==", + "requires": { + "@types/prosemirror-commands": "^1.0.4", + "@types/prosemirror-keymap": "^1.0.4", + "@types/prosemirror-model": "^1.13.2", + "@types/prosemirror-schema-list": "^1.0.3", + "@types/prosemirror-state": "^1.2.7", + "@types/prosemirror-transform": "^1.1.4", + "@types/prosemirror-view": "^1.19.1", + "prosemirror-commands": "^1.1.11", + "prosemirror-keymap": "^1.1.3", + "prosemirror-model": "^1.14.3", + "prosemirror-schema-list": "^1.1.6", + "prosemirror-state": "^1.3.4", + "prosemirror-transform": "^1.3.3", + "prosemirror-view": "^1.20.2" + } + }, + "@tiptap/extension-blockquote": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-2.0.0-beta.17.tgz", + "integrity": "sha512-mn94P3TO6LFCvn/LEgAbZrtKWLJw3YQgGiI3Doa67DGUXeID0nlyu+5iVTHUOdMXtqWbYgRW8HGjVgdyo5G5cw==", + "requires": {} + }, + "@tiptap/extension-bold": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-2.0.0-beta.17.tgz", + "integrity": "sha512-17XOOasNK7sB6UdxDquF0s7Pdaitr165d3mwPrTETeQytS7cCnGpIjwg3rvp+LNgZMKEC4mxrBob8WxA7uK8Mg==", + "requires": {} + }, + "@tiptap/extension-bubble-menu": { + "version": "2.0.0-beta.40", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.40.tgz", + "integrity": "sha512-1bMuQ7747IPvvoy1GLoX/iwmleIWRH7maEi8K2MTB0wsN4pjnuRjua0LdNMMM5i4/ZE/qYehNtpHeJfwIrFnhQ==", + "requires": { + "prosemirror-state": "^1.3.4", + "prosemirror-view": "^1.20.2", + "tippy.js": "^6.3.2" + } + }, + "@tiptap/extension-bullet-list": { + "version": "2.0.0-beta.16", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.0-beta.16.tgz", + "integrity": "sha512-+L4/Oeey1wqYwN2KGFfsw2K7qfn81FSNElRylhcG2RueqFnMgiaeigPDDIHT5xOqUQ0cyWsJxHoQOaKw4h2bPA==", + "requires": {} + }, + "@tiptap/extension-code": { + "version": "2.0.0-beta.18", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-2.0.0-beta.18.tgz", + "integrity": "sha512-d/QKmcCFwoYxoI+UPhB3Bb2EIFERw5MXZpNUxjnY3hDZfqA7AgXj6wiHS6RkQSeLgnQEULWRvtMU0J+Uvo0z6A==", + "requires": {} + }, + "@tiptap/extension-code-block": { + "version": "2.0.0-beta.21", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-2.0.0-beta.21.tgz", + "integrity": "sha512-2D/aW3DqfvwmWWNY5z9LncXawkd4iyEtAXJ6a+b4F7K022z7wNloPicXEA/mKyyiYNezhTiN84aVdUVsnGsgAg==", + "requires": { + "prosemirror-state": "^1.3.4" + } + }, + "@tiptap/extension-document": { + "version": "2.0.0-beta.13", + "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.0.0-beta.13.tgz", + "integrity": "sha512-nrufdKziA/wovaY4DjGkc8OGuIZi8CH8CW3+yYfeWbruwFKkyZHlZy9nplFWSEqBHPAeqD+px9r91yGMW3ontA==", + "requires": {} + }, + "@tiptap/extension-dropcursor": { + "version": "2.0.0-beta.19", + "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-2.0.0-beta.19.tgz", + "integrity": "sha512-rslIcVvD42NNh5sEbkCkG03DWMFBrS5KoK+lDOdIcC1DjmTtpVgcLvvE01btzaB3ljx+UVqI2Zaxa6VOiTeEMw==", + "requires": { + "@types/prosemirror-dropcursor": "^1.0.3", + "prosemirror-dropcursor": "^1.3.5" + } + }, + "@tiptap/extension-floating-menu": { + "version": "2.0.0-beta.34", + "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.34.tgz", + "integrity": "sha512-WheIsmcTy3+4j9qHoaRdFzdczqSXZVPOPytEq81zwMz7GuWA+Oom3egkvmW1gc1gv5gR+bGklWhm+l0ML2D7qA==", + "requires": { + "prosemirror-state": "^1.3.4", + "prosemirror-view": "^1.20.2", + "tippy.js": "^6.3.2" + } + }, + "@tiptap/extension-gapcursor": { + "version": "2.0.0-beta.25", + "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-2.0.0-beta.25.tgz", + "integrity": "sha512-dmow1C822DFfLhe+0bIRsdjTWjjzPeq2j9zpo2IaE54rMTfGVvrOPNe51OZ2KgpPob7iTilgaOZDTrnUW6ialw==", + "requires": { + "@types/prosemirror-gapcursor": "^1.0.4", + "prosemirror-gapcursor": "^1.2.0" + } + }, + "@tiptap/extension-hard-break": { + "version": "2.0.0-beta.22", + "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-2.0.0-beta.22.tgz", + "integrity": "sha512-ofoOBwjqcQJ2QCzAERPvwXOzTuf7lVuMb2soUUOyjIuwqXidGC30aY2peOnVGsFsdYNjeprOejE//ud7pg/3sA==", + "requires": {} + }, + "@tiptap/extension-heading": { + "version": "2.0.0-beta.16", + "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-2.0.0-beta.16.tgz", + "integrity": "sha512-z9NsabhyqIct8S12LdJ7XGGt73jlzwjDjqyc/g5AhEPZWNJ6k4yvcsGk+t6hEatK5O6ELs1gdeCOCElP0OqA8A==", + "requires": {} + }, + "@tiptap/extension-history": { + "version": "2.0.0-beta.16", + "resolved": "https://registry.npmjs.org/@tiptap/extension-history/-/extension-history-2.0.0-beta.16.tgz", + "integrity": "sha512-nrNwV8a7zUt1t2I/kPX5Y6N9vZ8mrugimJIQmPGIp/4mmw1SEUzkaPpIsv6+ELmqMHSDktQ0ofb3pXeWDXWZvw==", + "requires": { + "@types/prosemirror-history": "^1.0.3", + "prosemirror-history": "^1.2.0" + } + }, + "@tiptap/extension-horizontal-rule": { + "version": "2.0.0-beta.22", + "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-2.0.0-beta.22.tgz", + "integrity": "sha512-v9PFi8hxCBRMXCk5lK35sHetw95IzqjZ9ttkdgro2JfeDdOfFG7FylOrXriFvfKHCpbU2TNbZLud+fg8MXVPtQ==", + "requires": { + "prosemirror-state": "^1.3.4" + } + }, + "@tiptap/extension-italic": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-2.0.0-beta.17.tgz", + "integrity": "sha512-rtbijLCunCp2xyvUxDcYJDErMn0EwZ+PUBYWBzCG1WpxxvsaqC+/yoj8mBKlxW1Dob/uFGkJnyMCZrhXMwW3iQ==", + "requires": {} + }, + "@tiptap/extension-list-item": { + "version": "2.0.0-beta.14", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.0.0-beta.14.tgz", + "integrity": "sha512-t6xwEqP+d5443Ul2Jvqz9kXb3ro7bA7yY9HA0vskm3120WxxHW9jxgxZN+82Ot5Tm7nXOAlsN6vuqnt4idnxZQ==", + "requires": {} + }, + "@tiptap/extension-mention": { + "version": "2.0.0-beta.75", + "resolved": "https://registry.npmjs.org/@tiptap/extension-mention/-/extension-mention-2.0.0-beta.75.tgz", + "integrity": "sha512-BEhGFh6R7T6R13A64C7wRwM0quHrMV09VI6yXxy1MRYjpYUojPfh7YUeFMstKTx+yI3Bb4lNf7xDygKDSivVWw==", + "requires": { + "@tiptap/suggestion": "^2.0.0-beta.72", + "prosemirror-model": "^1.14.3", + "prosemirror-state": "^1.3.4" + } + }, + "@tiptap/extension-ordered-list": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-2.0.0-beta.17.tgz", + "integrity": "sha512-gPAtg8nLdmGMgtdz6wVX6rVO/IpzrB3JyF8VBfKjwB0poQiGjEsSpQngWam7wokIuDYtMZuitUwmhVDBvGrNqw==", + "requires": {} + }, + "@tiptap/extension-paragraph": { + "version": "2.0.0-beta.17", + "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-2.0.0-beta.17.tgz", + "integrity": "sha512-qCQVCf9c2hgaeIdfy22PaoZyW5Vare/1aGkOEAaZma5RjrUbV9hrRKwoW9LsDjnh1EN1fIeKdg02yEhnHWtG8A==", + "requires": {} + }, + "@tiptap/extension-placeholder": { + "version": "2.0.0-beta.33", + "resolved": "https://registry.npmjs.org/@tiptap/extension-placeholder/-/extension-placeholder-2.0.0-beta.33.tgz", + "integrity": "sha512-qn9XxYDiepF/uS0u45Jz8Ro+Ki6MuwK4AY+AgNTFh3VgfJj6qUXD0B1yU5XxKLXLfrfDPFQ+saOKuPoipF5GXw==", + "requires": { + "prosemirror-model": "^1.14.3", + "prosemirror-state": "^1.3.4", + "prosemirror-view": "^1.20.2" + } + }, + "@tiptap/extension-strike": { + "version": "2.0.0-beta.19", + "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.0.0-beta.19.tgz", + "integrity": "sha512-vRcUW6YkFcb535MgdEotwoqnrbhlsUoZ7nKoZ5MNA+Nu6rXRAz5VXaHncFNpWM77WcEbuaOKvcGolkMK1q2BIw==", + "requires": {} + }, + "@tiptap/extension-text": { + "version": "2.0.0-beta.13", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-2.0.0-beta.13.tgz", + "integrity": "sha512-0EtAwuRldCAoFaL/iXgkRepEeOd55rPg5N4FQUN1xTwZT7PDofukP0DG/2jff/Uj17x4uTaJAa9qlFWuNnDvjw==", + "requires": {} + }, + "@tiptap/react": { + "version": "2.0.0-beta.81", + "resolved": "https://registry.npmjs.org/@tiptap/react/-/react-2.0.0-beta.81.tgz", + "integrity": "sha512-bYriarBAHA9iOj8o9edcstTiJnkwwSDsYfIZ+FmcaTLV7sJUMvp+UieEF9gPZpd/zI98Mf13Lmb4u+FT+hssGg==", + "requires": { + "@tiptap/extension-bubble-menu": "^2.0.0-beta.40", + "@tiptap/extension-floating-menu": "^2.0.0-beta.34", + "prosemirror-view": "^1.20.2" + } + }, + "@tiptap/starter-kit": { + "version": "2.0.0-beta.123", + "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-2.0.0-beta.123.tgz", + "integrity": "sha512-r46ChIuthSecoozfRATPqRUffU8t1tVycAwH+0zdpJVtBmMiVV8hHp0otasvFn5w7d38MbaYHGEaH40myc2mrg==", + "requires": { + "@tiptap/core": "^2.0.0-beta.122", + "@tiptap/extension-blockquote": "^2.0.0-beta.17", + "@tiptap/extension-bold": "^2.0.0-beta.17", + "@tiptap/extension-bullet-list": "^2.0.0-beta.16", + "@tiptap/extension-code": "^2.0.0-beta.18", + "@tiptap/extension-code-block": "^2.0.0-beta.21", + "@tiptap/extension-document": "^2.0.0-beta.13", + "@tiptap/extension-dropcursor": "^2.0.0-beta.19", + "@tiptap/extension-gapcursor": "^2.0.0-beta.25", + "@tiptap/extension-hard-break": "^2.0.0-beta.22", + "@tiptap/extension-heading": "^2.0.0-beta.16", + "@tiptap/extension-history": "^2.0.0-beta.16", + "@tiptap/extension-horizontal-rule": "^2.0.0-beta.22", + "@tiptap/extension-italic": "^2.0.0-beta.17", + "@tiptap/extension-list-item": "^2.0.0-beta.14", + "@tiptap/extension-ordered-list": "^2.0.0-beta.17", + "@tiptap/extension-paragraph": "^2.0.0-beta.17", + "@tiptap/extension-strike": "^2.0.0-beta.19", + "@tiptap/extension-text": "^2.0.0-beta.13" + } + }, + "@tiptap/suggestion": { + "version": "2.0.0-beta.72", + "resolved": "https://registry.npmjs.org/@tiptap/suggestion/-/suggestion-2.0.0-beta.72.tgz", + "integrity": "sha512-DwImLQpl0KR1fySV2g84AGviDiryo40fwCXxwzpMXpn0rcEVEdh616eQGEOWCvC3NIY2RdB4KVpbYcMnXCZxFw==", + "requires": { + "prosemirror-model": "^1.14.3", + "prosemirror-state": "^1.3.4", + "prosemirror-view": "^1.20.2" + } + }, "@tsconfig/node10": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", @@ -16401,16 +16889,6 @@ "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", "dev": true }, - "@types/draft-js": { - "version": "0.10.44", - "resolved": "https://registry.npmjs.org/@types/draft-js/-/draft-js-0.10.44.tgz", - "integrity": "sha512-6p3FZED91yPf+KQinlzFz1HuqSQ5zRXqU3RUsaP2oQYZTtrm5HDf2kwYnF5IihsleHR3jlQAwdSZt0zlJw3VGQ==", - "dev": true, - "requires": { - "@types/react": "*", - "immutable": "~3.7.4" - } - }, "@types/escape-html": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/escape-html/-/escape-html-1.0.1.tgz", @@ -16536,6 +17014,11 @@ "integrity": "sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA==", "devOptional": true }, + "@types/orderedmap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/orderedmap/-/orderedmap-1.0.0.tgz", + "integrity": "sha512-dxKo80TqYx3YtBipHwA/SdFmMMyLCnP+5mkEqN0eMjcTBzHkiiX0ES118DsjDBjvD+zeSsSU9jULTZ+frog+Gw==" + }, "@types/parse-json": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", @@ -16547,6 +17030,99 @@ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", "integrity": "sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==" }, + "@types/prosemirror-commands": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/prosemirror-commands/-/prosemirror-commands-1.0.4.tgz", + "integrity": "sha512-utDNYB3EXLjAfYIcRWJe6pn3kcQ5kG4RijbT/0Y/TFOm6yhvYS/D9eJVnijdg9LDjykapcezchxGRqFD5LcyaQ==", + "requires": { + "@types/prosemirror-model": "*", + "@types/prosemirror-state": "*", + "@types/prosemirror-view": "*" + } + }, + "@types/prosemirror-dropcursor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/prosemirror-dropcursor/-/prosemirror-dropcursor-1.0.3.tgz", + "integrity": "sha512-b0/8njnJ4lwyHKcGuCMf3x7r1KjxyugB1R/c2iMCjplsJHSC7UY9+OysqgJR5uUXRekUSGniiLgBtac/lvH6wg==", + "requires": { + "@types/prosemirror-state": "*" + } + }, + "@types/prosemirror-gapcursor": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/prosemirror-gapcursor/-/prosemirror-gapcursor-1.0.4.tgz", + "integrity": "sha512-9xKjFIG5947dzerFvkLWp6F53JwrUYoYwh3SgcTFEp8SbSfNNrez/PFYVZKPnoqPoaK5WtTdQTaMwpCV9rXQIg==", + "requires": { + "@types/prosemirror-model": "*", + "@types/prosemirror-state": "*" + } + }, + "@types/prosemirror-history": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/prosemirror-history/-/prosemirror-history-1.0.3.tgz", + "integrity": "sha512-5TloMDRavgLjOAKXp1Li8u0xcsspzbT1Cm9F2pwHOkgvQOz1jWQb2VIXO7RVNsFjLBZdIXlyfSLivro3DuMWXg==", + "requires": { + "@types/prosemirror-model": "*", + "@types/prosemirror-state": "*" + } + }, + "@types/prosemirror-keymap": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/prosemirror-keymap/-/prosemirror-keymap-1.0.4.tgz", + "integrity": "sha512-ycevwkqUh+jEQtPwqO7sWGcm+Sybmhu8MpBsM8DlO3+YTKnXbKA6SDz/+q14q1wK3UA8lHJyfR+v+GPxfUSemg==", + "requires": { + "@types/prosemirror-commands": "*", + "@types/prosemirror-model": "*", + "@types/prosemirror-state": "*", + "@types/prosemirror-view": "*" + } + }, + "@types/prosemirror-model": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@types/prosemirror-model/-/prosemirror-model-1.13.2.tgz", + "integrity": "sha512-a2rDB0aZ+7aIP7uBqQq1wLb4Hg4qqEvpkCqvhsgT/gG8IWC0peCAZfQ24sgTco0qSJLeDgIbtPeU6mgr869/kg==", + "requires": { + "@types/orderedmap": "*" + } + }, + "@types/prosemirror-schema-list": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/prosemirror-schema-list/-/prosemirror-schema-list-1.0.3.tgz", + "integrity": "sha512-uWybOf+M2Ea7rlbs0yLsS4YJYNGXYtn4N+w8HCw3Vvfl6wBAROzlMt0gV/D/VW/7J/LlAjwMezuGe8xi24HzXA==", + "requires": { + "@types/orderedmap": "*", + "@types/prosemirror-model": "*", + "@types/prosemirror-state": "*" + } + }, + "@types/prosemirror-state": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/prosemirror-state/-/prosemirror-state-1.2.7.tgz", + "integrity": "sha512-clJf5uw3/XQnBJtl2RqYXoLMGBySnLYl43xtDvFfQZKkLnnYcM1SDU8dcz7lWjl2Dm+H98RpLOl44pp7DYT+wA==", + "requires": { + "@types/prosemirror-model": "*", + "@types/prosemirror-transform": "*", + "@types/prosemirror-view": "*" + } + }, + "@types/prosemirror-transform": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@types/prosemirror-transform/-/prosemirror-transform-1.1.4.tgz", + "integrity": "sha512-HP1PauvkqSgDquZut8HaLOTUDQ6jja/LAy4OA7tTS1XG7wqRnX3gLUyEj0mD6vFd4y8BPkNddNdOh/BeGHlUjg==", + "requires": { + "@types/prosemirror-model": "*" + } + }, + "@types/prosemirror-view": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/@types/prosemirror-view/-/prosemirror-view-1.19.1.tgz", + "integrity": "sha512-fyQ4NVxAdfISWrE2qT8cpZdosXoH/1JuVYMBs9CdaXPbvi/8R2L2tkkcMRM314piKrO8nfYH5OBZKzP2Ax3jtA==", + "requires": { + "@types/prosemirror-model": "*", + "@types/prosemirror-state": "*", + "@types/prosemirror-transform": "*" + } + }, "@types/react": { "version": "16.9.55", "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.55.tgz", @@ -17030,11 +17606,6 @@ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==" }, - "add-px-to-style": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/add-px-to-style/-/add-px-to-style-1.0.0.tgz", - "integrity": "sha1-0ME1RB+oAUqBN5BFMQlvZ/KPJjo=" - }, "agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", @@ -17280,11 +17851,6 @@ "function-bind": "^1.1.1" } }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" - }, "asn1.js": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", @@ -18056,11 +18622,6 @@ "shallow-clone": "^3.0.0" } }, - "clsx": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.1.1.tgz", - "integrity": "sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA==" - }, "code-point-at": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", @@ -18484,14 +19045,6 @@ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", "dev": true }, - "cross-fetch": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.0.6.tgz", - "integrity": "sha512-KBPUbqgFjzWlVcURG+Svp9TlhA5uliYtiNx/0r8nv0pdypeQCRJ9IaSIc3q/x3q8t3F75cHuwxVql1HFGHCNJQ==", - "requires": { - "node-fetch": "2.6.1" - } - }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -19037,16 +19590,6 @@ "utila": "~0.4" } }, - "dom-css": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/dom-css/-/dom-css-2.1.0.tgz", - "integrity": "sha1-/bwtWgFdCj4YcuEUcrvQ57nmogI=", - "requires": { - "add-px-to-style": "1.0.0", - "prefix-style": "2.0.1", - "to-camel-case": "1.0.0" - } - }, "dom-helpers": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", @@ -19137,23 +19680,6 @@ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz", "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==" }, - "draft-js": { - "version": "0.11.7", - "resolved": "https://registry.npmjs.org/draft-js/-/draft-js-0.11.7.tgz", - "integrity": "sha512-ne7yFfN4sEL82QPQEn80xnADR8/Q6ALVworbC5UOSzOvjffmYfFsr3xSZtxbIirti14R7Y33EZC5rivpLgIbsg==", - "requires": { - "fbjs": "^2.0.0", - "immutable": "~3.7.4", - "object-assign": "^4.1.1" - }, - "dependencies": { - "immutable": { - "version": "3.7.6", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", - "integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks=" - } - } - }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -19195,22 +19721,6 @@ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", "dev": true }, - "emoji-toolkit": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/emoji-toolkit/-/emoji-toolkit-6.5.1.tgz", - "integrity": "sha512-oY5E81cXvRUxXkbVgOI8NxYHKF5FeWfJhFCIYUKhbVfSmdCH8+bmJzgDdhufExa7t1+WEzpUFdHwYxJTXS90vQ==" - }, - "emojibase": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/emojibase/-/emojibase-5.1.1.tgz", - "integrity": "sha512-qc/qfuzZ93xmYMhnVA15yP2k3t4zJvBbqCc8dpDXFf75eJ+IogbzJuWQur8fkwsZ0u7YvJDBh939F9DapQqktQ==" - }, - "emojibase-data": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/emojibase-data/-/emojibase-data-6.1.2.tgz", - "integrity": "sha512-1fYgpAYkAJq7bmGO3XboP0dQHrtRiyWrAluCmv5NHSK1nruz0x8kXhpLiz48rAJGDQOWYUpLGaPASTNXVZX87Q==", - "requires": {} - }, "emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", @@ -20269,33 +20779,6 @@ "websocket-driver": ">=0.5.1" } }, - "fbjs": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-2.0.0.tgz", - "integrity": "sha512-8XA8ny9ifxrAWlyhAbexXcs3rRMtxWcs3M0lctLfB49jRDHiaxj+Mo0XxbwE7nKZYzgCFoq64FS+WFd4IycPPQ==", - "requires": { - "core-js": "^3.6.4", - "cross-fetch": "^3.0.4", - "fbjs-css-vars": "^1.0.0", - "loose-envify": "^1.0.0", - "object-assign": "^4.1.0", - "promise": "^7.1.1", - "setimmediate": "^1.0.5", - "ua-parser-js": "^0.7.18" - }, - "dependencies": { - "core-js": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.8.3.tgz", - "integrity": "sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q==" - } - } - }, - "fbjs-css-vars": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", - "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" - }, "fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", @@ -20461,12 +20944,6 @@ "locate-path": "^2.0.0" } }, - "find-with-regex": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/find-with-regex/-/find-with-regex-1.1.3.tgz", - "integrity": "sha512-zkEVQ1H3PIQL/19ADKt1lCQU4QGM3OneiderUcFgn5EgTm/TnoUh7HxPAwP8w/vXxWSLC6KtpbDQpypJ5+majw==", - "requires": {} - }, "flat-cache": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", @@ -21193,11 +21670,6 @@ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, - "immutable": { - "version": "3.7.6", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", - "integrity": "sha1-E7TTyxK++hVIKib+Gy665kAHHks=" - }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -22076,11 +22548,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, - "lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" - }, "lodash-move": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/lodash-move/-/lodash-move-1.1.1.tgz", @@ -22608,11 +23075,6 @@ "lodash.toarray": "^4.4.0" } }, - "node-fetch": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", - "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" - }, "node-forge": { "version": "0.10.0", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", @@ -22942,6 +23404,11 @@ "word-wrap": "^1.2.3" } }, + "orderedmap": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-1.1.1.tgz", + "integrity": "sha512-3Ux8um0zXbVacKUkcytc0u3HgC0b0bBLT+I60r2J/En72cI0nZffqrA7Xtf2Hqs27j1g82llR5Mhbd0Z1XW4AQ==" + }, "original": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", @@ -23249,11 +23716,6 @@ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" }, - "performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" - }, "picomatch": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", @@ -23597,11 +24059,6 @@ } } }, - "prefix-style": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/prefix-style/-/prefix-style-2.0.1.tgz", - "integrity": "sha1-ZrupqHDP2jCKXcIOhekSCTLJWgY=" - }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -23653,14 +24110,6 @@ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" }, - "promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", - "requires": { - "asap": "~2.0.3" - } - }, "promise-polyfill": { "version": "8.2.0", "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.2.0.tgz", @@ -23694,6 +24143,100 @@ "string.prototype.codepointat": "^0.2.0" } }, + "prosemirror-commands": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.1.11.tgz", + "integrity": "sha512-uXDVkOGJbFHocdacMJihrnQCT7tHswO48ewq6ByqLxTwOrI8Y4B4aHvwUbM4epwElv/YjgC+DuqXm/gEHPym4w==", + "requires": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "prosemirror-dropcursor": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.3.5.tgz", + "integrity": "sha512-tNUwcF2lPAkwKBZPZRtbxpwljnODRNZ3eiYloN1DSUqDjMT1nBZm0nejaEMS1TvNQ+3amibUSAiV4hX+jpASFA==", + "requires": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0", + "prosemirror-view": "^1.1.0" + } + }, + "prosemirror-gapcursor": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.2.0.tgz", + "integrity": "sha512-yCLy5+0rVqLir/KcHFathQj4Rf8aRHi80FmEfKtM0JmyzvwdomslLzDZ/pX4oFhFKDgjl/WBBBFNqDyNifWg7g==", + "requires": { + "prosemirror-keymap": "^1.0.0", + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-view": "^1.0.0" + } + }, + "prosemirror-history": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.2.0.tgz", + "integrity": "sha512-B9v9xtf4fYbKxQwIr+3wtTDNLDZcmMMmGiI3TAPShnUzvo+Rmv1GiUrsQChY1meetHl7rhML2cppF3FTs7f7UQ==", + "requires": { + "prosemirror-state": "^1.2.2", + "prosemirror-transform": "^1.0.0", + "rope-sequence": "^1.3.0" + } + }, + "prosemirror-keymap": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.1.4.tgz", + "integrity": "sha512-Al8cVUOnDFL4gcI5IDlG6xbZ0aOD/i3B17VT+1JbHWDguCgt/lBHVTHUBcKvvbSg6+q/W4Nj1Fu6bwZSca3xjg==", + "requires": { + "prosemirror-state": "^1.0.0", + "w3c-keyname": "^2.2.0" + } + }, + "prosemirror-model": { + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.14.3.tgz", + "integrity": "sha512-yzZlBaSxfUPIIP6U5Edh5zKxJPZ5f7bwZRhiCuH3UYkWhj+P3d8swHsbuAMOu/iDatDc5J/Qs5Mb3++mZf+CvQ==", + "requires": { + "orderedmap": "^1.1.0" + } + }, + "prosemirror-schema-list": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.1.6.tgz", + "integrity": "sha512-aFGEdaCWmJzouZ8DwedmvSsL50JpRkqhQ6tcpThwJONVVmCgI36LJHtoQ4VGZbusMavaBhXXr33zyD2IVsTlkw==", + "requires": { + "prosemirror-model": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "prosemirror-state": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.3.4.tgz", + "integrity": "sha512-Xkkrpd1y/TQ6HKzN3agsQIGRcLckUMA9u3j207L04mt8ToRgpGeyhbVv0HI7omDORIBHjR29b7AwlATFFf2GLA==", + "requires": { + "prosemirror-model": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "prosemirror-transform": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.3.3.tgz", + "integrity": "sha512-9NLVXy1Sfa2G6qPqhWMkEvwQQMTw7OyTqOZbJaGQWsCeH3hH5Cw+c5eNaLM1Uu75EyKLsEZhJ93XpHJBa6RX8A==", + "requires": { + "prosemirror-model": "^1.0.0" + } + }, + "prosemirror-view": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.20.3.tgz", + "integrity": "sha512-2ImL9K/tIEk+aC2GT8shzfmT2U0Y8UQZ13L5AY0A4Tcj09o/ICGE362gKUE3Ze/Xr/nMw61Zv5JMSQUszAj9dw==", + "requires": { + "prosemirror-model": "^1.14.3", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0" + } + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -23798,14 +24341,6 @@ "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==" }, - "raf": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", - "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", - "requires": { - "performance-now": "^2.1.0" - } - }, "randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -23943,16 +24478,6 @@ "integrity": "sha512-OfX0ThSxRYEVGaQSt0DlXfyl5w4DbXHsXetyeivmoQrh9xA9bzVPHNf8aAhOIiwiaxX2WYWpLDB3gcpsDJ9oww==", "requires": {} }, - "react-custom-scrollbars": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/react-custom-scrollbars/-/react-custom-scrollbars-4.2.1.tgz", - "integrity": "sha1-gw/ZUCkn6X6KeMIIaBOJmyqLZts=", - "requires": { - "dom-css": "^2.0.0", - "prop-types": "^15.5.10", - "raf": "^3.1.0" - } - }, "react-devtools-inline": { "version": "4.17.0", "resolved": "https://registry.npmjs.org/react-devtools-inline/-/react-devtools-inline-4.17.0.tgz", @@ -23973,12 +24498,6 @@ "resolved": "https://registry.npmjs.org/react-dom-factories/-/react-dom-factories-1.0.2.tgz", "integrity": "sha1-63cFxNs2+1AbOqOP91lhaqD/luA=" }, - "react-icons": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.2.0.tgz", - "integrity": "sha512-rmzEDFt+AVXRzD7zDE21gcxyBizD/3NqjbX6cmViAgdqfJ2UiLer8927/QhhrXQV7dEj/1EGuOTPp7JnLYVJKQ==", - "requires": {} - }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -24426,6 +24945,11 @@ "inherits": "^2.0.1" } }, + "rope-sequence": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.2.tgz", + "integrity": "sha512-ku6MFrwEVSVmXLvy3dYph3LAMNS0890K7fabn+0YIRQ2T96T9F4gkFf0vf0WW0JUraNWwGRtInEpH7yO4tbQZg==" + }, "run-parallel": { "version": "1.1.9", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", @@ -24666,7 +25190,8 @@ "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true }, "setprototypeof": { "version": "1.1.1", @@ -25791,12 +26316,12 @@ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==" }, - "to-camel-case": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-camel-case/-/to-camel-case-1.0.0.tgz", - "integrity": "sha1-GlYFSy+daWKYzmamCJcyK29CPkY=", + "tippy.js": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.2.tgz", + "integrity": "sha512-35XVQI7Zl/jHZ51+8eHu/vVRXBjWYGobPm5G9FxOchj4r5dWhghKGS0nm0ARUKZTF96V7pPn7EbXS191NTwldw==", "requires": { - "to-space-case": "^1.0.0" + "@popperjs/core": "^2.9.0" } }, "to-fast-properties": { @@ -25804,11 +26329,6 @@ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=" }, - "to-no-case": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz", - "integrity": "sha1-xyKQcWTvaxeBMsjmmTAhLRtKoWo=" - }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -25851,19 +26371,6 @@ "repeat-string": "^1.6.1" } }, - "to-space-case": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-space-case/-/to-space-case-1.0.0.tgz", - "integrity": "sha1-sFLar7Gysp3HcM6gFj5ewOvJ/Bc=", - "requires": { - "to-no-case": "^1.0.0" - } - }, - "to-style": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/to-style/-/to-style-1.3.3.tgz", - "integrity": "sha1-Y6K3Cm9KfU/cLtV6C+TnI1y2aZw=" - }, "toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", @@ -26009,11 +26516,6 @@ "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", "dev": true }, - "ua-parser-js": { - "version": "0.7.23", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.23.tgz", - "integrity": "sha512-m4hvMLxgGHXG3O3fQVAyyAQpZzDOvwnhOTjYz5Xmr7r/+LpkNy3vJXdVRWgd1TkAb7NGROZuSy96CrlNVjA7KA==" - }, "unbox-primitive": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", @@ -26330,6 +26832,11 @@ "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", "dev": true }, + "w3c-keyname": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.4.tgz", + "integrity": "sha512-tOhfEwEzFLJzf6d1ZPkYfGj+FWhIpBux9ppoP3rlclw3Z0BZv3N7b7030Z1kYth+6rDuAsXUFr+d0VE6Ed1ikw==" + }, "watchpack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.2.0.tgz", diff --git a/package.json b/package.json index 2e1610d3aa4..f78b108c7dc 100644 --- a/package.json +++ b/package.json @@ -15,9 +15,6 @@ "dependencies": { "@apollo/client": "^3.1.5", "@auth0/auth0-react": "^1.2.0", - "@draft-js-plugins/editor": "^4.1.0", - "@draft-js-plugins/emoji": "^4.2.0", - "@draft-js-plugins/mention": "^4.3.1", "@headlessui/react": "^1.4.1", "@heroicons/react": "^1.0.1", "@recordreplay/playwright": "^1.10.3", @@ -28,6 +25,10 @@ "@stripe/react-stripe-js": "^1.4.1", "@stripe/stripe-js": "^1.17.1", "@tailwindcss/forms": "^0.3.2", + "@tiptap/extension-mention": "^2.0.0-beta.75", + "@tiptap/extension-placeholder": "^2.0.0-beta.33", + "@tiptap/react": "^2.0.0-beta.81", + "@tiptap/starter-kit": "^2.0.0-beta.123", "apollo-link-http": "^1.5.17", "babel-plugin-add-react-displayname": "0.0.5", "base64-arraybuffer": "^0.2.0", @@ -38,7 +39,6 @@ "debug": "^4.2.0", "devtools-sprintf-js": "^1.0.3", "dotenv": "^10.0.0", - "draft-js": "^0.11.7", "escape-html": "^1.0.3", "fontfaceobserver": "^2.1.0", "graphql": "^15.3.0", @@ -89,7 +89,6 @@ "@babel/preset-typescript": "^7.14.5", "@babel/types": "^7.14.8", "@types/classnames": "^2.2.11", - "@types/draft-js": "^0.10.44", "@types/escape-html": "^1.0.1", "@types/lodash": "^4.14.168", "@types/logrocket-react": "^3.0.0", diff --git a/src/devtools/client/debugger/src/components/Editor/Breakpoints/Panel/PanelSummary/index.tsx b/src/devtools/client/debugger/src/components/Editor/Breakpoints/Panel/PanelSummary/index.tsx index 1ce0b06e672..de7e7711cce 100644 --- a/src/devtools/client/debugger/src/components/Editor/Breakpoints/Panel/PanelSummary/index.tsx +++ b/src/devtools/client/debugger/src/components/Editor/Breakpoints/Panel/PanelSummary/index.tsx @@ -62,8 +62,10 @@ function PanelSummary({ e.stopPropagation(); if (pausedOnHit) { + console.log("createFrameComment", currentTime, executionPoint, breakpoint); createFrameComment(currentTime, executionPoint, null, breakpoint); } else { + console.log("createFloatingCodeComment", currentTime, executionPoint, breakpoint); createFloatingCodeComment(currentTime, executionPoint, breakpoint); } }; diff --git a/src/devtools/client/webconsole/components/Output/Message.js b/src/devtools/client/webconsole/components/Output/Message.js index 2a6a72ffc4b..e103d403e99 100644 --- a/src/devtools/client/webconsole/components/Output/Message.js +++ b/src/devtools/client/webconsole/components/Output/Message.js @@ -178,7 +178,7 @@ class Message extends Component { this.onViewSourceInDebugger({ ...frame, url: frame.source }); }; let handleAddComment = () => { - dispatch(actions.createComment(executionPointTime, executionPoint, null, true, frame)); + dispatch(actions.createComment(executionPointTime, executionPoint, undefined, true, frame)); }; if (BigInt(executionPoint) > BigInt(pausedExecutionPoint)) { diff --git a/src/ui/actions/comments.ts b/src/ui/actions/comments.ts index 52df866620d..afd4e53c7ef 100644 --- a/src/ui/actions/comments.ts +++ b/src/ui/actions/comments.ts @@ -1,13 +1,13 @@ import { Action } from "redux"; import { selectors } from "ui/reducers"; import { actions } from "ui/actions"; -import { PendingComment, Event, Comment, Reply, SourceLocation } from "ui/state/comments"; +import { PendingComment, Comment, Reply, SourceLocation } from "ui/state/comments"; import { UIThunkAction } from "."; import { ThreadFront } from "protocol/thread"; import { setSelectedPrimaryPanel } from "./app"; import escapeHtml from "escape-html"; import { waitForTime } from "protocol/utils"; -import { getPendingComment } from "ui/reducers/comments"; +import { PENDING_COMMENT_ID } from "ui/reducers/comments"; const { getFilenameFromURL } = require("devtools/client/debugger/src/utils/sources-tree/getURL"); const { getTextAtLocation } = require("devtools/client/debugger/src/reducers/sources"); const { findClosestFunction } = require("devtools/client/debugger/src/utils/ast"); @@ -61,20 +61,24 @@ export function createComment( ): UIThunkAction { return async ({ dispatch }) => { const labels = sourceLocation ? await dispatch(createLabels(sourceLocation)) : undefined; - const primaryLabel = labels?.primary || null; - const secondaryLabel = labels?.secondary || null; + const primaryLabel = labels?.primary; + const secondaryLabel = labels?.secondary; const pendingComment: PendingComment = { type: "new_comment", comment: { content: "", - time, + createdAt: new Date().toISOString(), + hasFrames, + id: PENDING_COMMENT_ID, point, position, primaryLabel, + replies: [], secondaryLabel, - hasFrames, sourceLocation, + time, + updatedAt: new Date().toISOString(), }, }; @@ -92,7 +96,7 @@ export function createFrameComment( return async ({ dispatch }) => { const sourceLocation = breakpoint?.location || (await getCurrentPauseSourceLocationWithTimeout()); - dispatch(createComment(time, point, position, true /* hasFrames */, sourceLocation || null)); + dispatch(createComment(time, point, position, true, sourceLocation || null)); }; } @@ -107,20 +111,7 @@ export function createFloatingCodeComment( ): UIThunkAction { return async ({ dispatch }) => { const { location: sourceLocation } = breakpoint; - dispatch(createComment(time, point, null, false /* hasFrames */, sourceLocation || null)); - }; -} - -export function createNoFrameComment( - time: number, - point: string, - position: { x: number; y: number } | null, - breakpoint?: any -): UIThunkAction { - return async ({ dispatch }) => { - const sourceLocation = - breakpoint?.location || (await getCurrentPauseSourceLocationWithTimeout()); - dispatch(createComment(time, point, position, false /* hasFrames */, sourceLocation || null)); + dispatch(createComment(time, point, null, false, sourceLocation || null)); }; } @@ -160,72 +151,55 @@ export function createLabels(sourceLocation: { }; } -export function editItem(item: Comment | Reply): UIThunkAction { +export function editItem(item: Reply | Comment): UIThunkAction { return async ({ dispatch }) => { const { point, time, hasFrames } = item; dispatch(seekToComment(item)); if (!("replies" in item)) { - const { content, sourceLocation, parentId, position, id } = item; - - // Editing a reply. const pendingComment: PendingComment = { + comment: item, type: "edit_reply", - comment: { content, time, point, hasFrames, sourceLocation, parentId, position, id }, }; dispatch(setPendingComment(pendingComment)); } else { - const { content, primaryLabel, secondaryLabel, sourceLocation, id, position } = item; - - // Editing a comment. const pendingComment: PendingComment = { + comment: item, type: "edit_comment", - comment: { - content, - primaryLabel, - secondaryLabel, - time, - point, - hasFrames, - sourceLocation, - id, - position, - }, }; dispatch(setPendingComment(pendingComment)); } }; } -export function seekToComment( - item: Comment | Reply | Event | PendingComment["comment"] -): UIThunkAction { +export function seekToComment(item: Comment | Reply | PendingComment["comment"]): UIThunkAction { return ({ dispatch, getState }) => { dispatch(clearPendingComment()); let cx = selectors.getThreadContext(getState()); - const hasFrames = "hasFrames" in item ? item.hasFrames : false; - dispatch(actions.seek(item.point, item.time, hasFrames)); - if ("sourceLocation" in item && item.sourceLocation) { + dispatch(actions.seek(item.point, item.time, item.hasFrames)); + if (item.sourceLocation) { cx = selectors.getThreadContext(getState()); dispatch(actions.selectLocation(cx, item.sourceLocation)); } }; } -export function replyToComment(comment: Comment): UIThunkAction { +export function replyToComment(parentId: string, point: string, time: number): UIThunkAction { return ({ dispatch }) => { - const { time, point, hasFrames, id } = comment; const pendingComment: PendingComment = { type: "new_reply", comment: { content: "", - time, - point, - hasFrames, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + id: PENDING_COMMENT_ID, + hasFrames: false, sourceLocation: null, - parentId: id, + parentId, + point, + time, }, }; diff --git a/src/ui/components/Comments/CommentMarker.tsx b/src/ui/components/Comments/CommentMarker.tsx index 039da30d3fb..2a4cbe7436b 100644 --- a/src/ui/components/Comments/CommentMarker.tsx +++ b/src/ui/components/Comments/CommentMarker.tsx @@ -55,7 +55,7 @@ class CommentMarker extends React.Component { return null; } - if (comment.time > zoomRegion.endTime) { + if (!comment.time || comment.time > zoomRegion.endTime) { return null; } diff --git a/src/ui/components/Comments/TranscriptComments/CommentCard.tsx b/src/ui/components/Comments/TranscriptComments/CommentCard.tsx index cc5627754cb..b7ee117d54e 100644 --- a/src/ui/components/Comments/TranscriptComments/CommentCard.tsx +++ b/src/ui/components/Comments/TranscriptComments/CommentCard.tsx @@ -1,7 +1,6 @@ import React, { useEffect, useState } from "react"; import { connect, ConnectedProps } from "react-redux"; import classNames from "classnames"; -import Markdown from "react-markdown"; import { UIState } from "ui/state"; import { selectors } from "ui/reducers"; import { actions } from "ui/actions"; @@ -17,9 +16,8 @@ import differenceInWeeks from "date-fns/differenceInWeeks"; import differenceInMonths from "date-fns/differenceInMonths"; import differenceInYears from "date-fns/differenceInYears"; -import useAuth0 from "ui/utils/useAuth0"; -import CommentCardFooter from "./CommentCardFooter"; import { AvatarImage } from "ui/components/Avatar"; +import { PENDING_COMMENT_ID } from "ui/reducers/comments"; const { getExecutionPoint } = require("devtools/client/debugger/src/reducers/pause"); function formatRelativeTime(date: Date) { @@ -35,24 +33,19 @@ function formatRelativeTime(date: Date) { if (months > 0) { return `${months}m`; } - if (weeks > 0) { return `${weeks}w`; } - if (days > 0) { return `${days}d`; } - if (minutes >= 60) { return `${Math.floor(minutes / 60)}h`; } - - if (minutes == 0) { - return "Now"; + if (minutes > 0) { + return `${minutes}m`; } - - return `${minutes}m`; + return "Now"; } function BorderBridge({ @@ -89,6 +82,10 @@ function CommentItemHeader({ setRelativeDate(formatRelativeTime(new Date(comment.createdAt))); }, []); + if (!comment.user) { + return null; + } + return (
@@ -115,38 +112,20 @@ function CommentItem({ pendingComment: PendingComment | null; comment: Comment | Reply; }) { - let content, showOptions; - - if ( - pendingComment && - (pendingComment.type == "edit_reply" || pendingComment.type == "edit_comment") && - "id" in comment && - pendingComment.comment.id == comment.id - ) { - const { comment, type } = pendingComment; - - content = ; - showOptions = false; - } else { - content = ( -
- {comment.content} -
- ); - showOptions = true; - } + const isEditing = Boolean(pendingComment?.comment?.id == comment.id); + const showOptions = !isEditing; return (
- {content} +
); } type PropsFromParent = { - comment: Comment | PendingNewComment; - comments: (Comment | PendingNewComment)[]; + comment: PendingNewComment; + comments: PendingNewComment[]; }; type CommentCardProps = PropsFromRedux & PropsFromParent; @@ -156,36 +135,13 @@ function CommentCard({ currentTime, executionPoint, seekToComment, - setModal, - replyToComment, hoveredComment, setHoveredComment, pendingComment, }: CommentCardProps) { - const { isAuthenticated } = useAuth0(); - const isPaused = comment.time === currentTime && executionPoint === comment.point; - const isEditing = - pendingComment && - ["edit_comment", "edit_reply"].includes(pendingComment.type) && - pendingComment?.comment.time === currentTime && - pendingComment?.comment.point === executionPoint; - - const onReply = (e: React.MouseEvent) => { - e.stopPropagation(); - - if (!isAuthenticated) { - setModal("login"); - return; - } - - if ("id" in comment) { - replyToComment(comment); - } - }; - - // If the comment for this card doesn't have an ID, it's because it's the corresponding - // comment for a pending new comment. - if (!("id" in comment)) { + const isPaused = currentTime === comment.time && executionPoint === comment.point; + + if (comment.id === PENDING_COMMENT_ID) { return (
{comment.sourceLocation ? : null} - - {comment.replies?.map((reply: Reply, i: number) => ( -
+ + {comment.replies?.map((reply: Reply) => ( +
))} - {isPaused && !isEditing ? : null} + {isPaused && !pendingComment ? ( + + ) : null}
); @@ -233,16 +195,14 @@ function CommentCard({ const connector = connect( (state: UIState) => ({ - pendingComment: selectors.getPendingComment(state), currentTime: selectors.getCurrentTime(state), executionPoint: getExecutionPoint(state), hoveredComment: selectors.getHoveredComment(state), + pendingComment: selectors.getPendingComment(state), }), { - replyToComment: actions.replyToComment, - setModal: actions.setModal, - seekToComment: actions.seekToComment, editItem: actions.editItem, + seekToComment: actions.seekToComment, setHoveredComment: actions.setHoveredComment, } ); diff --git a/src/ui/components/Comments/TranscriptComments/CommentCardFooter.tsx b/src/ui/components/Comments/TranscriptComments/CommentCardFooter.tsx deleted file mode 100644 index 0746aa44c98..00000000000 --- a/src/ui/components/Comments/TranscriptComments/CommentCardFooter.tsx +++ /dev/null @@ -1,105 +0,0 @@ -import React from "react"; -import { connect, ConnectedProps } from "react-redux"; -import { UIState } from "ui/state"; -import { selectors } from "ui/reducers"; -import NewCommentEditor from "./CommentEditor/NewCommentEditor"; -import { Comment, PendingNewComment, PendingNewReply } from "ui/state/comments"; - -type CommentCardFooterProps = PropsFromRedux & { - comment: PendingNewComment | Comment; - onReply: (e: React.MouseEvent) => void; -}; - -function NewComment({ - pendingComment, - comment, - replyPrompt, -}: { - pendingComment: PendingNewComment; - comment: PendingNewComment | Comment; - replyPrompt: React.ReactElement; -}) { - // Don't show the editor if this comment card's root comment is not the - // pendingComment itself. - if (pendingComment !== comment) { - return replyPrompt; - } - - return ( -
- -
- ); -} - -function NewReply({ - pendingComment, - comment, - replyPrompt, -}: { - pendingComment: PendingNewReply; - comment: Comment; - replyPrompt: React.ReactElement; -}) { - // Don't show the editor if the pending reply's supposed parent does not match - // this comment card's root comment. - if (pendingComment.parentId !== comment.id) { - return replyPrompt; - } - - return ( -
- -
- ); -} - -export function ReplyPrompt({ onReply }: { onReply?: (e: React.MouseEvent) => void }) { - return ( -
- Write a reply... -
- ); -} - -function CommentCardFooter({ comment, pendingComment, onReply }: CommentCardFooterProps) { - let footer; - - // Case 1 and 2: Editing a comment/reply. - if ( - !pendingComment || - pendingComment.type === "edit_comment" || - pendingComment.type === "edit_reply" - ) { - footer = ; - } else if (pendingComment.type === "new_comment") { - // Case 3: Adding a comment. - footer = ( - } - /> - ); - } else { - // Case 4: Adding a reply. - footer = ( - } - /> - ); - } - - return
{footer}
; -} - -const connector = connect((state: UIState) => ({ - pendingComment: selectors.getPendingComment(state), -})); -type PropsFromRedux = ConnectedProps; -export default connector(CommentCardFooter); diff --git a/src/ui/components/Comments/TranscriptComments/CommentEditor/CommentEditor.css b/src/ui/components/Comments/TranscriptComments/CommentEditor/CommentEditor.css index 198c8a25e56..6c2ada18c12 100644 --- a/src/ui/components/Comments/TranscriptComments/CommentEditor/CommentEditor.css +++ b/src/ui/components/Comments/TranscriptComments/CommentEditor/CommentEditor.css @@ -80,3 +80,11 @@ .transcript-list .img.paper-airplane:hover { background: var(--primary-accent); } + +.ProseMirror p.is-editor-empty:first-child::before { + content: attr(data-placeholder); + float: left; + color: #9197a3; + pointer-events: none; + height: 0; +} diff --git a/src/ui/components/Comments/TranscriptComments/CommentEditor/CommentEditor.tsx b/src/ui/components/Comments/TranscriptComments/CommentEditor/CommentEditor.tsx index 44066dd10e1..eb8ba00f4b7 100644 --- a/src/ui/components/Comments/TranscriptComments/CommentEditor/CommentEditor.tsx +++ b/src/ui/components/Comments/TranscriptComments/CommentEditor/CommentEditor.tsx @@ -1,37 +1,29 @@ -import React, { useMemo, useState } from "react"; +import React, { useMemo } from "react"; import { connect, ConnectedProps } from "react-redux"; import { selectors } from "ui/reducers"; import { actions } from "ui/actions"; import { UIState } from "ui/state"; import hooks from "ui/hooks"; -import { - Comment, - PendingEditComment, - PendingEditReply, - PendingNewComment, - PendingNewReply, -} from "ui/state/comments"; +import { Comment, PendingNewComment, PendingNewReply, Reply } from "ui/state/comments"; -import DraftJSEditor, { DraftJSAPI } from "./DraftJSEditor"; import "./CommentEditor.css"; import { User } from "ui/types"; -import { DisabledSmButton, PrimarySmButton, SecondarySmButton } from "ui/components/shared/Button"; +import TipTapEditor from "./TipTapEditor"; type CommentEditorProps = PropsFromRedux & { - comment: Comment | PendingNewComment | PendingNewReply | PendingEditReply | PendingEditComment; + comment: Comment | Reply | PendingNewComment | PendingNewReply; + editable: boolean; handleSubmit: (inputValue: string) => void; }; function CommentEditor({ + clearPendingComment, comment, + editable, handleSubmit, - updatePendingCommentContent, - clearPendingComment, }: CommentEditorProps) { const recordingId = hooks.useGetRecordingId(); const { collaborators, recording, loading } = hooks.useGetOwnersAndCollaborators(recordingId!); - const [api, setApi] = useState(); - const [submitEnabled, setSubmitEnabled] = useState(false); const users = useMemo( () => @@ -41,21 +33,15 @@ function CommentEditor({ [loading] ); - const handleCancel = () => { - clearPendingComment(); - }; - const onChangeCallback = () => { - setSubmitEnabled(!!api?.getText().length); - updatePendingCommentContent(api ? api.getText() : ""); - }; - return (
e.stopPropagation()}>
-
@@ -76,10 +59,7 @@ const connector = connect( (state: UIState) => ({ pendingComment: selectors.getPendingComment(state), }), - { - clearPendingComment: actions.clearPendingComment, - updatePendingCommentContent: actions.updatePendingCommentContent, - } + { clearPendingComment: actions.clearPendingComment } ); type PropsFromRedux = ConnectedProps; export default connector(CommentEditor); diff --git a/src/ui/components/Comments/TranscriptComments/CommentEditor/DraftJSEditor.css b/src/ui/components/Comments/TranscriptComments/CommentEditor/DraftJSEditor.css deleted file mode 100644 index 35c646265e5..00000000000 --- a/src/ui/components/Comments/TranscriptComments/CommentEditor/DraftJSEditor.css +++ /dev/null @@ -1,21 +0,0 @@ - -/* These styles override the default emoji popover - to constrain it to the narrow comment pane */ -.pluginPopover { - position: absolute; - top: calc(100% + 8px) !important; - left: 0 !important; - right: 0; - z-index: 1000; - background: #fff; - padding: 8px; - border-radius: 4px; - box-shadow: 1px 2px 4px rgb(200 200 200 / 80%); - margin: 0; - min-width: auto; -} - -.flipPopup .pluginPopover { - top: auto !important; - bottom: calc(100% + 8px) !important; -} diff --git a/src/ui/components/Comments/TranscriptComments/CommentEditor/DraftJSEditor.tsx b/src/ui/components/Comments/TranscriptComments/CommentEditor/DraftJSEditor.tsx deleted file mode 100644 index 4f108d819a3..00000000000 --- a/src/ui/components/Comments/TranscriptComments/CommentEditor/DraftJSEditor.tsx +++ /dev/null @@ -1,221 +0,0 @@ -import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"; -import type Draft from "draft-js"; - -import { User } from "ui/types"; - -import useDraftJS, { DraftJSModule, LazyLoadDraftConfig } from "./use-draftjs"; -import { addMentions, convertToMarkdown } from "./mention"; -import { features } from "ui/utils/prefs"; - -import "./DraftJSEditor.css"; -import { ReplyPrompt } from "../CommentCardFooter"; - -const moveSelectionToEnd = (editorState: Draft.EditorState, DraftJS: DraftJSModule) => { - const { EditorState, SelectionState } = DraftJS; - const content = editorState.getCurrentContent(); - const blockMap = content.getBlockMap(); - const key = blockMap.last().getKey(); - const length = blockMap.last().getLength(); - - // On Chrome and Safari, calling focus on contenteditable focuses the - // cursor at the first character. This is something you don't expect when - // you're clicking on an input element but not directly on a character. - // Put the cursor back where it was before the blur. - const selection = new SelectionState({ - anchorKey: key, - anchorOffset: length, - focusKey: key, - focusOffset: length, - }); - return EditorState.forceSelection(editorState, selection); -}; - -export interface DraftJSAPI { - getText: () => string; - focus: () => void; - blur: () => void; -} - -interface InternalApi extends DraftJSAPI { - state?: Draft.EditorState; - config?: LazyLoadDraftConfig; -} - -interface DraftJSEditorProps { - api: (api: DraftJSAPI) => void; - initialContent: string; - placeholder: string; - handleSubmit: (text: string) => void; - handleCancel: () => void; - onChangeCallback: () => void; - users?: User[]; -} - -export default function DraftJSEditor({ - api, - handleCancel, - handleSubmit, - onChangeCallback, - initialContent, - placeholder, - users, -}: DraftJSEditorProps) { - const editorNode = useRef(null); - const wrapperNode = useRef(null); - const [mentionSearchText, setMentionSearchText] = useState(""); - const [open, setOpen] = useState(false); - const [editorState, setEditorState] = useState(); - const [config, setConfig] = useState(); - const load = useDraftJS(); - const publicApi = useRef({ - state: undefined, - config: undefined, - focus: () => editorNode.current && editorNode.current.focus(), - blur: () => editorNode.current && editorNode.current.blur(), - getText: function () { - return this.state && this.config - ? convertToMarkdown(this.state, this.config.modules.DraftJS) - : ""; - }, - }); - - const handleChange = useCallback( - (updated: Draft.EditorState) => { - publicApi.current.state = updated; - setEditorState(updated); - onChangeCallback(); - }, - [setEditorState, onChangeCallback] - ); - - useEffect(() => { - if (api) api(publicApi.current); - }, [api]); - - useEffect( - function importDraftJS() { - load().then(cfg => { - const { - modules: { DraftJS, Editor }, - } = cfg; - - let es = Editor.createEditorStateWithText(initialContent); - if (users) { - es = addMentions(DraftJS, es, users); - } - - setEditorState(es); - setConfig(cfg); - publicApi.current.config = cfg; - }); - }, - [users] - ); - - const decorator = editorState?.getDecorator(); - useEffect(() => { - // This guards against calling focus() with a stale editorNode reference - // that doesn't yet have the emoji decorators attached. - if (!decorator) return; - - // The order is important here — we focus the editor first before scrolling the - // wrapper into view. Otherwise, the scrolling animation is interrupted by the focus. - editorNode.current!.focus(); - wrapperNode.current!.scrollIntoView({ block: "center", behavior: "smooth" }); - const { bottom } = wrapperNode.current!.getBoundingClientRect(); - const { innerHeight } = window; - - // Toggle a class to render the emoji popup above the editor when close to the bottom - wrapperNode.current!.classList.toggle("flipPopup", innerHeight - bottom < 300); - - // Move the cursor so that it's at the end of the selection instead of the beginning. - // Which DraftJS doesn't make easy: https://github.com/brijeshb42/medium-draft/issues/71 - setEditorState(state => - state && config?.modules.DraftJS - ? moveSelectionToEnd(state, config?.modules.DraftJS) - : undefined - ); - }, [decorator]); - - const keyBindingFn = (e: React.KeyboardEvent) => { - // Only save if the user is pressing Enter without holding Shift - if (e.keyCode == 13 && !e.shiftKey) { - return "save"; - } else if (e.keyCode == 27) { - return "cancel"; - } - - return config?.modules.DraftJS.getDefaultKeyBinding(e); - }; - const handleKeyCommand = (command: "save" | "cancel") => { - if (command === "save") { - handleSubmit(publicApi.current.getText()); - return "handled"; - } else if (command === "cancel") { - handleCancel(); - return "handled"; - } - - return "not-handled"; - }; - - const filteredUsers = useMemo( - () => - users - ? users.filter( - u => u.name.includes(mentionSearchText) || u.name.includes(mentionSearchText) - ) - : [], - [mentionSearchText, users] - ); - - // This keeps the comment from collapsing when the user clicks the reply button. - if (!config) return ; - - const { - emojiPlugin, - mentionPlugin, - modules: { - Editor: { default: Editor }, - }, - } = config; - - const plugins = []; - if (features.commentEmojis) { - plugins.push(emojiPlugin); - } - - if (features.commentMentions) { - plugins.push(mentionPlugin); - } - - return ( -
editorNode.current!.focus()} - > - - {features.commentEmojis && } - {features.commentMentions && ( - - setMentionSearchText(value) - } - onOpenChange={setOpen} - open={open} - /> - )} -
- ); -} diff --git a/src/ui/components/Comments/TranscriptComments/CommentEditor/ExistingCommentEditor.tsx b/src/ui/components/Comments/TranscriptComments/CommentEditor/ExistingCommentEditor.tsx index 9af74eb2c2c..617414482ec 100644 --- a/src/ui/components/Comments/TranscriptComments/CommentEditor/ExistingCommentEditor.tsx +++ b/src/ui/components/Comments/TranscriptComments/CommentEditor/ExistingCommentEditor.tsx @@ -2,36 +2,44 @@ import React from "react"; import { connect, ConnectedProps } from "react-redux"; import hooks from "ui/hooks"; import { actions } from "ui/actions"; -import { PendingEditComment, PendingEditReply } from "ui/state/comments"; import CommentEditor from "./CommentEditor"; +import { + Comment, + PendingComment, + PendingNewComment, + PendingNewReply, + Reply, +} from "ui/state/comments"; type ExistingCommentEditorProps = PropsFromRedux & { - comment: PendingEditComment | PendingEditReply; - type: "edit_comment" | "edit_reply"; + comment: Comment | Reply | PendingNewComment | PendingNewReply; + pendingComment: PendingComment | null; }; -function ExistingCommentEditor({ comment, type, clearPendingComment }: ExistingCommentEditorProps) { +function ExistingCommentEditor({ + comment, + pendingComment, + clearPendingComment, +}: ExistingCommentEditorProps) { const updateComment = hooks.useUpdateComment(); const updateCommentReply = hooks.useUpdateCommentReply(); const handleSubmit = (inputValue: string) => { - handleExistingSave(comment, inputValue); - clearPendingComment(); - }; - const handleExistingSave = ( - pendingComment: PendingEditComment | PendingEditReply, - inputValue: string - ) => { - const { id } = pendingComment; - - if (type === "edit_comment") { - updateComment(id, inputValue, pendingComment.position); - } else { - updateCommentReply(id, inputValue); + if (pendingComment?.type === "edit_comment") { + updateComment(pendingComment.comment.id, inputValue, pendingComment.comment.position); + } else if (pendingComment?.type === "edit_reply") { + updateCommentReply(pendingComment.comment.id, inputValue); } + clearPendingComment(); }; - return ; + return ( + + ); } const connector = connect(null, { clearPendingComment: actions.clearPendingComment }); diff --git a/src/ui/components/Comments/TranscriptComments/CommentEditor/NewCommentEditor.tsx b/src/ui/components/Comments/TranscriptComments/CommentEditor/NewCommentEditor.tsx index 8bef20b4ce2..36a0fdf65d4 100644 --- a/src/ui/components/Comments/TranscriptComments/CommentEditor/NewCommentEditor.tsx +++ b/src/ui/components/Comments/TranscriptComments/CommentEditor/NewCommentEditor.tsx @@ -5,7 +5,6 @@ import { actions } from "ui/actions"; import { PendingNewComment, PendingNewReply } from "ui/state/comments"; import CommentEditor from "./CommentEditor"; import { useAuth0 } from "@auth0/auth0-react"; -import { setModal } from "ui/actions/app"; interface NewCommentEditorProps extends PropsFromRedux { comment: PendingNewComment | PendingNewReply; @@ -24,6 +23,12 @@ function NewCommentEditor({ comment, type, clearPendingComment, setModal }: NewC return; } + // For now we can simply bail if the input happens to be empty. We should fix + // this in the next pass to handle and show an error prompt. + if (inputValue == "") { + return; + } + if (type == "new_reply") { handleReplySave(comment as PendingNewReply, inputValue); } else { @@ -34,51 +39,24 @@ function NewCommentEditor({ comment, type, clearPendingComment, setModal }: NewC }; const handleReplySave = async (comment: PendingNewReply, inputValue: string) => { - // For now we can simply bail if the input happens to be empty. We should fix - // this in the next pass to handle and show an error prompt. - if (inputValue == "") { - return; - } - - const { parentId } = comment; - const reply = { + ...comment, content: inputValue, - commentId: parentId, }; addCommentReply(reply, recordingId!); }; - const handleNewSave = async (comment: PendingNewComment, inputValue: string) => { - // For now we can simply bail if the input happens to be empty. We should fix - // this in the next pass to handle and show an error prompt. - if (inputValue == "") { - return; - } - - const { primaryLabel, secondaryLabel, time, point, hasFrames, sourceLocation } = comment; + const handleNewSave = async (comment: PendingNewComment, inputValue: string) => { const newComment = { + ...comment, content: inputValue, - primaryLabel, - secondaryLabel, - point, - time, - hasFrames, - sourceLocation, - recordingId, - position: comment.position - ? { - x: comment.position?.x, - y: comment.position?.y, - } - : null, }; addComment(newComment, recordingId!); }; - return ; + return ; } const connector = connect(null, { diff --git a/src/ui/components/Comments/TranscriptComments/CommentEditor/TipTapEditor.tsx b/src/ui/components/Comments/TranscriptComments/CommentEditor/TipTapEditor.tsx new file mode 100644 index 00000000000..26d83a0e33c --- /dev/null +++ b/src/ui/components/Comments/TranscriptComments/CommentEditor/TipTapEditor.tsx @@ -0,0 +1,89 @@ +import React, { useEffect } from "react"; +import { useEditor, EditorContent, Extension } from "@tiptap/react"; +import StarterKit from "@tiptap/starter-kit"; +import { User } from "ui/types"; +import Placeholder from "@tiptap/extension-placeholder"; +import classNames from "classnames"; + +interface TipTapEditorProps { + content: string; + editable: boolean; + handleSubmit: (text: string) => void; + handleCancel: () => void; + placeholder: string; + // Not actually implementing this now, but leaving it in the API for later + possibleMentions: User[]; +} + +const tryToParse = (content: string): any => { + try { + return JSON.parse(content); + } catch { + // Our comments were not always JSON, they used to be stored as markdown + // In that case, we just render the raw markdown. + const textContent = content ? [{ type: "text", text: content }] : []; + return { + type: "doc", + content: [{ type: "paragraph", content: textContent }], + }; + } +}; + +const TipTapEditor = ({ + content, + editable, + handleSubmit, + handleCancel, + placeholder, +}: TipTapEditorProps) => { + const editor = useEditor({ + extensions: [ + StarterKit, + // Mention.configure({ suggestion: suggestion(possibleMentions.map(u => u.name)) }), + Placeholder.configure({ placeholder }), + Extension.create({ + name: "submitOnEnter", + addKeyboardShortcuts() { + return { + Enter: ({ editor }) => { + handleSubmit(JSON.stringify(editor.getJSON())); + return true; + }, + Escape: () => { + handleCancel(); + return true; + }, + }; + }, + }), + ], + editorProps: { + attributes: { + class: "focus:outline-none", + }, + }, + content: tryToParse(content), + editable, + autofocus: true, + }); + + useEffect(() => { + editor?.setEditable(editable); + if (editable) { + editor?.commands.focus("end"); + } + }, [editable]); + + return ( + + ); +}; + +export default TipTapEditor; diff --git a/src/ui/components/Comments/TranscriptComments/CommentEditor/draftjs.ts b/src/ui/components/Comments/TranscriptComments/CommentEditor/draftjs.ts deleted file mode 100644 index 9c5c564249c..00000000000 --- a/src/ui/components/Comments/TranscriptComments/CommentEditor/draftjs.ts +++ /dev/null @@ -1,15 +0,0 @@ -import DraftJS from "draft-js"; -import * as Editor from "@draft-js-plugins/editor"; -import createEmojiPlugin, { defaultTheme as defaultEmojiTheme } from "@draft-js-plugins/emoji"; -import createMentionPlugin, { - defaultTheme as defaultMentionTheme, -} from "@draft-js-plugins/mention"; - -export { - DraftJS, - Editor, - createEmojiPlugin, - defaultEmojiTheme, - createMentionPlugin, - defaultMentionTheme, -}; diff --git a/src/ui/components/Comments/TranscriptComments/CommentEditor/mention.ts b/src/ui/components/Comments/TranscriptComments/CommentEditor/mention.ts deleted file mode 100644 index 77a88c77429..00000000000 --- a/src/ui/components/Comments/TranscriptComments/CommentEditor/mention.ts +++ /dev/null @@ -1,96 +0,0 @@ -import type Draft from "draft-js"; -import { User } from "ui/types"; - -// @ts-ignore-line -import { features } from "ui/utils/prefs"; - -import { DraftJSModule } from "./use-draftjs"; - -// Borrowed and slightly modified from -// https://github.com/draft-js-plugins/draft-js-plugins/blob/master/packages/mention/src/defaultRegExp.ts -// for creating the entities on load -const defaultRegExp = - "[" + - "\\w-\\." + // Latin-1 Supplement (letters only) - https://en.wikipedia.org/wiki/List_of_Unicode_characters#Latin-1_Supplement - "\xC0-\xD6" + - "\xD8-\xF6" + - "\xF8-\xFF" + // Latin Extended-A (without deprecated character) - https://en.wikipedia.org/wiki/List_of_Unicode_characters#Latin_Extended-A - "\u0100-\u0148" + - "\u014A-\u017F" + // Cyrillic symbols: \u0410-\u044F - https://en.wikipedia.org/wiki/Cyrillic_script_in_Unicode - "\u0410-\u044F" + // hiragana (japanese): \u3040-\u309F - https://gist.github.com/ryanmcgrath/982242#file-japaneseregex-js - "\u3040-\u309F" + // katakana (japanese): \u30A0-\u30FF - https://gist.github.com/ryanmcgrath/982242#file-japaneseregex-js - "\u30A0-\u30FF" + // For an advanced explaination about Hangul see https://github.com/draft-js-plugins/draft-js-plugins/pull/480#issuecomment-254055437 - // Hangul Jamo (korean): \u3130-\u318F - https://en.wikipedia.org/wiki/Korean_language_and_computers#Hangul_in_Unicode - // Hangul Syllables (korean): \uAC00-\uD7A3 - https://en.wikipedia.org/wiki/Korean_language_and_computers#Hangul_in_Unicode - "\u3130-\u318F" + - "\uAC00-\uD7A3" + // common chinese symbols: \u4e00-\u9eff - http://stackoverflow.com/a/1366113/837709 - "\u4E00-\u9EFF" + // Arabic https://en.wikipedia.org/wiki/Arabic_(Unicode_block) - "\u0600-\u06FF" + // Vietnamese http://vietunicode.sourceforge.net/charset/ - "\xC0-\u1EF9" + - "]"; - -function mentionsEnabled() { - return features.commentMentions; -} - -function addMentions(DraftJS: DraftJSModule, es: Draft.EditorState, users: User[]) { - if (!mentionsEnabled()) return es; - - const blocks = es.getCurrentContent().getBlocksAsArray(); - blocks.forEach(b => { - // iterate in reverse order to avoid invalidating the match indices when changing the text - // @ts-ignore - const matches = [...b.getText().matchAll(new RegExp(`@(${defaultRegExp}+)`, "ig"))].reverse(); - for (let match of matches) { - const mention = users.find(u => u.name === match[1]); - - if (!mention) continue; - - // If we find a user for the mention (which we should), create a mention - // entity and replace the text with the new entity - const contentStateWithEntity = es.getCurrentContent().createEntity("mention", "IMMUTABLE", { - mention, - }); - const selectionState = DraftJS.SelectionState.createEmpty(b.getKey()).merge({ - anchorOffset: match.index, - focusOffset: match.index + match[0].length, - }); - const entityKey = contentStateWithEntity.getLastCreatedEntityKey(); - const mentionFragment = DraftJS.Modifier.replaceText( - es.getCurrentContent(), - selectionState, - mention.name, - undefined, - entityKey - ); - es = DraftJS.EditorState.push(es, mentionFragment, "insert-fragment"); - } - }); - - return es; -} - -function convertToMarkdown(editorState: Draft.EditorState, DraftJS: DraftJSModule) { - if (!mentionsEnabled()) return editorState.getCurrentContent().getPlainText(); - - const raw = DraftJS.convertToRaw(editorState.getCurrentContent()); - return raw.blocks - .map(b => { - const buffer = []; - let i = 0; - b.entityRanges.forEach(er => { - const e = raw.entityMap[er.key]; - if (e.type === "mention") { - buffer.push(b.text.substring(i, er.offset)); - buffer.push(`@${e.data.mention.nickname}`); - i = er.offset + er.length; - } - }); - buffer.push(b.text.substring(i)); - - return buffer.join(""); - }) - .join("\n"); -} - -export { addMentions, convertToMarkdown, mentionsEnabled }; diff --git a/src/ui/components/Comments/TranscriptComments/CommentEditor/use-draftjs.ts b/src/ui/components/Comments/TranscriptComments/CommentEditor/use-draftjs.ts deleted file mode 100644 index 97eaac79bfb..00000000000 --- a/src/ui/components/Comments/TranscriptComments/CommentEditor/use-draftjs.ts +++ /dev/null @@ -1,75 +0,0 @@ -import type * as Draft from "draft-js"; -import type { EditorPlugin } from "@draft-js-plugins/editor"; -import type { EmojiPlugin } from "@draft-js-plugins/emoji"; - -import "draft-js/dist/Draft.css"; -import "@draft-js-plugins/emoji/lib/plugin.css"; -import "@draft-js-plugins/mention/lib/plugin.css"; - -// Defining a partial interface for the module so consumers can use strongly -// typed interfaces when using DraftJS returned from the hook -export interface DraftJSModule { - convertToRaw: typeof Draft.convertToRaw; - SelectionState: typeof Draft.SelectionState; - Modifier: typeof Draft.Modifier; - EditorState: typeof Draft.EditorState; - KeyBindingUtil: typeof Draft.KeyBindingUtil; - getDefaultKeyBinding: typeof Draft.getDefaultKeyBinding; -} - -export interface LazyLoadDraftConfig { - modules: { - DraftJS: DraftJSModule; - Editor: any; - }; - emojiPlugin: EmojiPlugin; - mentionPlugin: EditorPlugin & { - MentionSuggestions: React.ComponentType; - }; -} - -let config: LazyLoadDraftConfig; - -function useDraftJS() { - function load() { - if (config) return Promise.resolve(config); - return import("./draftjs").then( - ({ - DraftJS, - Editor, - createEmojiPlugin, - defaultEmojiTheme, - createMentionPlugin, - defaultMentionTheme, - }) => { - const cfg: LazyLoadDraftConfig = { - modules: { - DraftJS, - Editor, - }, - emojiPlugin: createEmojiPlugin({ - theme: { - ...defaultEmojiTheme, - emojiSuggestions: `${defaultEmojiTheme.emojiSuggestions} pluginPopover`, - }, - }), - mentionPlugin: createMentionPlugin({ - entityMutability: "IMMUTABLE", - theme: { - ...defaultMentionTheme, - mentionSuggestions: `${defaultMentionTheme.mentionSuggestions} pluginPopover`, - }, - }), - }; - - config = cfg; - - return cfg; - } - ); - } - - return load; -} - -export default useDraftJS; diff --git a/src/ui/components/Transcript/Transcript.tsx b/src/ui/components/Transcript/Transcript.tsx index 61dcefaeee3..18ebb6df05c 100644 --- a/src/ui/components/Transcript/Transcript.tsx +++ b/src/ui/components/Transcript/Transcript.tsx @@ -8,26 +8,13 @@ import { UIState } from "ui/state"; import { Comment, PendingNewComment } from "ui/state/comments"; import CommentCard from "ui/components/Comments/TranscriptComments/CommentCard"; import useAuth0 from "ui/utils/useAuth0"; -import useDraftJS from "ui/components/Comments/TranscriptComments/CommentEditor/use-draftjs"; import MaterialIcon from "ui/components/shared/MaterialIcon"; function Transcript({ pendingComment }: PropsFromRedux) { const recordingId = hooks.useGetRecordingId(); const { comments } = hooks.useGetComments(recordingId); - const { recording, loading } = hooks.useGetRecording(recordingId); - const { userId } = hooks.useGetUserId(); - const load = useDraftJS(); - const isAuthor = userId && userId == recording?.userId; - - useEffect(() => { - let idle: NodeJS.Timeout | undefined = setTimeout(() => { - load().then(() => { - idle = undefined; - }); - }, 1000); - - return () => idle && clearTimeout(idle); - }, []); + const { loading } = hooks.useGetRecording(recordingId); + const { isAuthenticated } = useAuth0(); if (loading) { return null; @@ -38,9 +25,7 @@ function Transcript({ pendingComment }: PropsFromRedux) { displayedComments.push(pendingComment.comment); } - const { isAuthenticated } = useAuth0(); - - const sortedComments = sortBy(displayedComments, ["time"]); + const sortedComments = sortBy(displayedComments, ["time", "createdAt"]); return (
diff --git a/src/ui/hooks/comments/useAddComment.tsx b/src/ui/hooks/comments/useAddComment.tsx index 7bfed9539ff..8aa8f272346 100644 --- a/src/ui/hooks/comments/useAddComment.tsx +++ b/src/ui/hooks/comments/useAddComment.tsx @@ -1,15 +1,11 @@ import { RecordingId } from "@recordreplay/protocol"; import { gql, useMutation } from "@apollo/client"; import useAuth0 from "ui/utils/useAuth0"; -import { CommentPosition, PendingNewComment } from "ui/state/comments"; +import { PendingNewComment, Remark } from "ui/state/comments"; import { GET_USER_ID } from "ui/graphql/users"; import { GET_COMMENTS } from "ui/graphql/comments"; import { trackEvent } from "ui/utils/telemetry"; - -interface NewCommentVariable extends Omit { - content: string; - position: CommentPosition | null; -} +import _ from "lodash"; export default function useAddComment() { const { user } = useAuth0(); @@ -31,12 +27,18 @@ export default function useAddComment() { console.error("Apollo error while adding a comment:", error); } - return (comment: NewCommentVariable, recordingId: RecordingId) => { + return (comment: PendingNewComment, recordingId: RecordingId) => { const temporaryId = new Date().toISOString(); trackEvent("create comment"); + const without = (object: any, keys: string[]): any => { + return _.fromPairs(_.toPairs(object).filter(pair => !keys.includes(pair[0]))); + }; + addComment({ - variables: { input: comment }, + variables: { + input: { ...without(comment, ["id", "createdAt", "updatedAt", "replies"]), recordingId }, + }, optimisticResponse: { addComment: { success: true, @@ -66,15 +68,13 @@ export default function useAddComment() { const newComment = { ...comment, id: commentId, - replies: [], - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), user: { id: userId, name: user.name, picture: user.picture, __typename: "User", }, + __typename: "Comment", }; const newData = { ...data, @@ -82,7 +82,7 @@ export default function useAddComment() { ...data.recording, comments: [ ...data.recording.comments.filter( - (c: any) => c.id !== temporaryId && c.id !== commentId + (c: Remark) => c.id !== temporaryId && c.id !== commentId ), newComment, ], diff --git a/src/ui/hooks/comments/useAddCommentReply.tsx b/src/ui/hooks/comments/useAddCommentReply.tsx index dcb200de51d..358a1e777cc 100644 --- a/src/ui/hooks/comments/useAddCommentReply.tsx +++ b/src/ui/hooks/comments/useAddCommentReply.tsx @@ -3,11 +3,7 @@ import { gql, useMutation } from "@apollo/client"; import useAuth0 from "ui/utils/useAuth0"; import { GET_USER_ID } from "ui/graphql/users"; import { GET_COMMENTS } from "ui/graphql/comments"; - -interface NewReplyVariable { - content: string; - commentId: string; -} +import { PendingNewReply } from "ui/state/comments"; export default function useAddCommentReply() { const { user } = useAuth0(); @@ -29,10 +25,15 @@ export default function useAddCommentReply() { console.error("Apollo error while adding a comment:", error); } - return (reply: NewReplyVariable, recordingId: RecordingId) => { + return (reply: PendingNewReply, recordingId: RecordingId) => { const temporaryId = new Date().toISOString(); addCommentReply({ - variables: { input: reply }, + variables: { + input: { + commentId: reply.parentId, + content: reply.content, + }, + }, optimisticResponse: { addCommentReply: { success: true, @@ -61,7 +62,7 @@ export default function useAddCommentReply() { query: GET_USER_ID, }); - const parentComment = data.recording.comments.find((r: any) => r.id === reply.commentId); + const parentComment = data.recording.comments.find((r: any) => r.id === reply.parentId); const newReply = { id: commentReply.id, content: reply.content, @@ -90,7 +91,7 @@ export default function useAddCommentReply() { recording: { ...data.recording, comments: [ - ...data.recording.comments.filter((r: any) => r.id !== reply.commentId), + ...data.recording.comments.filter((r: any) => r.id !== reply.parentId), newParentComment, ], }, diff --git a/src/ui/reducers/comments.ts b/src/ui/reducers/comments.ts index acf23f72822..629040abee8 100644 --- a/src/ui/reducers/comments.ts +++ b/src/ui/reducers/comments.ts @@ -3,6 +3,8 @@ import { CommentsAction } from "ui/actions/comments"; import { UIState } from "ui/state"; import cloneDeep from "lodash/cloneDeep"; +export const PENDING_COMMENT_ID = "PENDING"; + function initialCommentsState(): CommentsState { return { hoveredComment: null, diff --git a/src/ui/state/comments.ts b/src/ui/state/comments.ts index a8fea8b961a..568e41d96c0 100644 --- a/src/ui/state/comments.ts +++ b/src/ui/state/comments.ts @@ -1,4 +1,5 @@ -import { RecordingId, MouseEvent } from "@recordreplay/protocol"; +import { RecordingId } from "@recordreplay/protocol"; +import { User } from "ui/types"; export interface CommentsState { pendingComment: PendingComment | null; @@ -18,101 +19,49 @@ export interface CommentPosition { y: number; } -interface User { - picture: string; - name: string; - id: string; -} - -export interface Comment { +export interface Remark { content: string; - primaryLabel: string; - secondaryLabel: string; createdAt: string; hasFrames: boolean; - sourceLocation: SourceLocation | null; id: string; point: string; - recording_id: RecordingId; - time: number; - updatedAt: string; - user: User; - replies: Reply[]; - __typename: string; - position: CommentPosition; - parentId: null; -} - -export interface Reply { - content: string; - createdAt: string; - hasFrames: boolean; + recordingId: RecordingId; sourceLocation: SourceLocation | null; - id: string; - point: string; - recording_id: RecordingId; time: number; updatedAt: string; user: User; - __typename: string; - position: null; - parentId: string; } -export interface Event extends MouseEvent { - comment?: Comment; +export interface Comment extends Remark { + position: CommentPosition | null; + primaryLabel?: string; + replies: Reply[]; + secondaryLabel?: string; } -// Pending Comments +export interface Reply extends Remark { + parentId: string; +} export type PendingComment = | { - type: "new_comment"; comment: PendingNewComment; + type: "new_comment"; } | { - type: "new_reply"; comment: PendingNewReply; + type: "new_reply"; } | { + comment: Comment; type: "edit_comment"; - comment: PendingEditComment; } | { + comment: Reply; type: "edit_reply"; - comment: PendingEditReply; }; -export interface PendingNewComment extends PendingBlankComment { - content: string; - primaryLabel: string | null; - secondaryLabel: string | null; - position: CommentPosition | null; -} - -export interface PendingNewReply extends PendingBlankComment { - content: string; - parentId: string; -} - -export interface PendingEditComment extends PendingBlankComment { - primaryLabel: string | null; - secondaryLabel: string | null; - position: CommentPosition; - parentId?: null; - id: string; -} - -export interface PendingEditReply extends PendingBlankComment { - position: null; - parentId: string; - id: string; -} +export type PendingCommentAction = "edit_reply" | "edit_comment" | "new_reply" | "new_comment"; -export interface PendingBlankComment { - content: string; - time: number; - point: string; - hasFrames: boolean; - sourceLocation: SourceLocation | null; -} +export type PendingNewComment = Omit; +export type PendingNewReply = Omit;