diff --git a/.vscode/settings.json b/.vscode/settings.json index 962d1d9b..2bb6ed03 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,6 +1,6 @@ { "editor.codeActionsOnSave": { - "source.organizeImports": "always" + "source.organizeImports": "always", }, "javascript.preferences.quoteStyle": "single", "typescript.preferences.quoteStyle": "single", @@ -15,7 +15,7 @@ "editor.tabSize": 2 }, "[json]": { - "editor.tabSize": 2 + "editor.tabSize": 2, }, "[jsonc]": { "editor.tabSize": 2 @@ -27,6 +27,9 @@ "editor.tabSize": 2 }, "[typescript]": { - "editor.tabSize": 2 + "editor.tabSize": 2, + }, + "[javascript]": { + "editor.tabSize": 2, } } diff --git a/hosting/.eslintrc.js b/hosting/.eslintrc.js index 1e627586..5af76742 100644 --- a/hosting/.eslintrc.js +++ b/hosting/.eslintrc.js @@ -23,6 +23,7 @@ module.exports = { "plugin:@typescript-eslint/recommended", "plugin:prettier/recommended", "plugin:@next/next/recommended", + "prettier", "google", ], diff --git a/hosting/package-lock.json b/hosting/package-lock.json index 97c04e60..b022b0dc 100644 --- a/hosting/package-lock.json +++ b/hosting/package-lock.json @@ -8,6 +8,9 @@ "name": "tanam-next", "version": "0.1.0", "dependencies": { + "@tiptap/extension-code-block-lowlight": "^2.4.0", + "@tiptap/extension-floating-menu": "^2.5.5", + "@tiptap/extension-underline": "^2.4.0", "@tiptap/pm": "^2.4.0", "@tiptap/react": "^2.4.0", "@tiptap/starter-kit": "^2.4.0", @@ -17,7 +20,9 @@ "firebase": "^10.12.0", "firebaseui": "^6.1.0", "flatpickr": "^4.6.13", + "highlight.js": "^11.10.0", "jsvectormap": "^1.5.3", + "lowlight": "^3.1.0", "next": "^14.2.3", "react": "^18.3.1", "react-apexcharts": "^1.4.1", @@ -30,6 +35,8 @@ "@iconify-json/ri": "^1.1.20", "@next/eslint-plugin-next": "^14.2.3", "@tailwindcss/typography": "^0.5.13", + "@tiptap/extension-link": "^2.5.5", + "@types/highlight.js": "^10.1.0", "@types/node": "^18.19.33", "@types/react": "^18.3.2", "@types/react-dom": "^18.3.0", @@ -46,6 +53,7 @@ "prettier": "^3.2.5", "prettier-plugin-tailwindcss": "^0.5.11", "sass": "^1.77.2", + "sass-loader": "^14.2.1", "tailwindcss": "^3.4.1", "typescript": "5.1" } @@ -1258,15 +1266,15 @@ } }, "node_modules/@tiptap/core": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.4.0.tgz", - "integrity": "sha512-YJSahk8pkxpCs8SflCZfTnJpE7IPyUWIylfgXM2DefjRQa5DZ+c6sNY0s/zbxKYFQ6AuHVX40r9pCfcqHChGxQ==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-2.5.5.tgz", + "integrity": "sha512-VnAnyWnsqN65QijtUFHbe7EPSJCkhNEAwlatsG/HvrZvUv9KmoWWbMsHAU73wozKzPXR3nHRbCxN+LuxP5bADg==", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/pm": "^2.0.0" + "@tiptap/pm": "^2.5.5" } }, "node_modules/@tiptap/extension-blockquote": { @@ -1346,6 +1354,20 @@ "@tiptap/pm": "^2.0.0" } }, + "node_modules/@tiptap/extension-code-block-lowlight": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.4.0.tgz", + "integrity": "sha512-j0SdFq66A97Cn7bQOMqFYBaYsmOltZZ6o4uDZH6fdTvEFbfXTdtTYs2awsNSbW+w/DtivKZCvAX1FRLR3/g/5A==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0", + "@tiptap/extension-code-block": "^2.0.0", + "@tiptap/pm": "^2.0.0" + } + }, "node_modules/@tiptap/extension-document": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-2.4.0.tgz", @@ -1372,9 +1394,9 @@ } }, "node_modules/@tiptap/extension-floating-menu": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.4.0.tgz", - "integrity": "sha512-vLb9v+htbHhXyty0oaXjT3VC8St4xuGSHWUB9GuAJAQ+NajIO6rBPbLUmm9qM0Eh2zico5mpSD1Qtn5FM6xYzg==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-2.5.5.tgz", + "integrity": "sha512-1mgpxZGfy1ziNSvWz6m1nGb9ZF9fVVz4X4XwrIqwGw1Vqt9oXflm6puglnzwVLDeaMDT014VUfczJ4My3wDZzA==", "dependencies": { "tippy.js": "^6.3.7" }, @@ -1383,8 +1405,8 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^2.0.0", - "@tiptap/pm": "^2.0.0" + "@tiptap/core": "^2.5.5", + "@tiptap/pm": "^2.5.5" } }, "node_modules/@tiptap/extension-gapcursor": { @@ -1462,6 +1484,23 @@ "@tiptap/core": "^2.0.0" } }, + "node_modules/@tiptap/extension-link": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-2.5.5.tgz", + "integrity": "sha512-zVpNvMD8R9uW1SX1PJoj3fLyOHwuFWqiqEHN2KWfLbEnbL/KXNnpIyKdpHnI9lqFrsMf2dmyZCS3R6xIrynviQ==", + "dev": true, + "dependencies": { + "linkifyjs": "^4.1.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.5.5", + "@tiptap/pm": "^2.5.5" + } + }, "node_modules/@tiptap/extension-list-item": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-2.4.0.tgz", @@ -1522,29 +1561,41 @@ "@tiptap/core": "^2.0.0" } }, - "node_modules/@tiptap/pm": { + "node_modules/@tiptap/extension-underline": { "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.4.0.tgz", - "integrity": "sha512-B1HMEqGS4MzIVXnpgRZDLm30mxDWj51LkBT/if1XD+hj5gm8B9Q0c84bhvODX6KIs+c6z+zsY9VkVu8w9Yfgxg==", + "resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-2.4.0.tgz", + "integrity": "sha512-guWojb7JxUwLz4OKzwNExJwOkhZjgw/ttkXCMBT0PVe55k998MMYe1nvN0m2SeTW9IxurEPtScH4kYJ0XuSm8Q==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^2.0.0" + } + }, + "node_modules/@tiptap/pm": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-2.5.5.tgz", + "integrity": "sha512-ppePiLaeG6IKkm8Yq+mRENT4LIAS4qQyLT8EnKadznaTL6SNj/72mm0MjD44URkM38ySzIyvt/vqHDapNK0Hww==", "dependencies": { "prosemirror-changeset": "^2.2.1", "prosemirror-collab": "^1.3.1", "prosemirror-commands": "^1.5.2", "prosemirror-dropcursor": "^1.8.1", "prosemirror-gapcursor": "^1.3.2", - "prosemirror-history": "^1.3.2", - "prosemirror-inputrules": "^1.3.0", + "prosemirror-history": "^1.4.1", + "prosemirror-inputrules": "^1.4.0", "prosemirror-keymap": "^1.2.2", - "prosemirror-markdown": "^1.12.0", + "prosemirror-markdown": "^1.13.0", "prosemirror-menu": "^1.2.4", - "prosemirror-model": "^1.19.4", - "prosemirror-schema-basic": "^1.2.2", - "prosemirror-schema-list": "^1.3.0", + "prosemirror-model": "^1.22.1", + "prosemirror-schema-basic": "^1.2.3", + "prosemirror-schema-list": "^1.4.1", "prosemirror-state": "^1.4.3", - "prosemirror-tables": "^1.3.5", - "prosemirror-trailing-node": "^2.0.7", - "prosemirror-transform": "^1.8.0", - "prosemirror-view": "^1.32.7" + "prosemirror-tables": "^1.3.7", + "prosemirror-trailing-node": "^2.0.8", + "prosemirror-transform": "^1.9.0", + "prosemirror-view": "^1.33.8" }, "funding": { "type": "github", @@ -1600,6 +1651,24 @@ "url": "https://github.com/sponsors/ueberdosis" } }, + "node_modules/@types/hast": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", + "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", + "dependencies": { + "@types/unist": "*" + } + }, + "node_modules/@types/highlight.js": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-10.1.0.tgz", + "integrity": "sha512-77hF2dGBsOgnvZll1vymYiNUtqJ8cJfXPD6GG/2M0aLRc29PkvB7Au6sIDjIEFcSICBhCh2+Pyq6WSRS7LUm6A==", + "deprecated": "This is a stub types definition. highlight.js provides its own type definitions, so you do not need this installed.", + "dev": true, + "dependencies": { + "highlight.js": "*" + } + }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", @@ -1640,6 +1709,11 @@ "@types/react": "*" } }, + "node_modules/@types/unist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.2.tgz", + "integrity": "sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "7.10.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.10.0.tgz", @@ -2609,11 +2683,22 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "dev": true, "engines": { "node": ">=6" } }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/dialog-polyfill": { "version": "0.4.10", "resolved": "https://registry.npmjs.org/dialog-polyfill/-/dialog-polyfill-0.4.10.tgz", @@ -4067,6 +4152,14 @@ "node": ">= 0.4" } }, + "node_modules/highlight.js": { + "version": "11.10.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.10.0.tgz", + "integrity": "sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ==", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/http-parser-js": { "version": "0.5.8", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz", @@ -4723,6 +4816,12 @@ "uc.micro": "^2.0.0" } }, + "node_modules/linkifyjs": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.1.3.tgz", + "integrity": "sha512-auMesunaJ8yfkHvK4gfg1K0SaKX/6Wn9g2Aac/NwX+l5VdmFZzo/hdPGxEOETj+ryRa4/fiOPjeeKURSAJx1sg==", + "dev": true + }, "node_modules/local-pkg": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", @@ -4793,6 +4892,28 @@ "loose-envify": "cli.js" } }, + "node_modules/lowlight": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lowlight/-/lowlight-3.1.0.tgz", + "integrity": "sha512-CEbNVoSikAxwDMDPjXlqlFYiZLkDJHwyGu/MfOsJnF3d7f3tds5J3z8s/l9TMXhzfsJCCJEAsD78842mwmg0PQ==", + "dependencies": { + "@types/hast": "^3.0.0", + "devlop": "^1.0.0", + "highlight.js": "~11.9.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/lowlight/node_modules/highlight.js": { + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz", + "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/lru-cache": { "version": "10.2.2", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz", @@ -4966,6 +5087,12 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, "node_modules/next": { "version": "14.2.3", "resolved": "https://registry.npmjs.org/next/-/next-14.2.3.tgz", @@ -5735,9 +5862,9 @@ } }, "node_modules/prosemirror-history": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.4.0.tgz", - "integrity": "sha512-UUiGzDVcqo1lovOPdi9YxxUps3oBFWAIYkXLu3Ot+JPv1qzVogRbcizxK3LhHmtaUxclohgiOVesRw5QSlMnbQ==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.4.1.tgz", + "integrity": "sha512-2JZD8z2JviJrboD9cPuX/Sv/1ChFng+xh2tChQ2X4bB2HeK+rra/bmJ3xGntCcjhOqIzSDG6Id7e8RJ9QPXLEQ==", "dependencies": { "prosemirror-state": "^1.2.2", "prosemirror-transform": "^1.0.0", @@ -5784,25 +5911,25 @@ } }, "node_modules/prosemirror-model": { - "version": "1.21.1", - "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.21.1.tgz", - "integrity": "sha512-IVBAuMqOfltTr7yPypwpfdGT+6rGAteVOw2FO6GEvCGGa1ZwxLseqC1Eax/EChDvG/xGquB2d/hLdgh3THpsYg==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.22.2.tgz", + "integrity": "sha512-I4lS7HHIW47D0Xv/gWmi4iUWcQIDYaJKd8Hk4+lcSps+553FlQrhmxtItpEvTr75iAruhzVShVp6WUwsT6Boww==", "dependencies": { "orderedmap": "^2.0.0" } }, "node_modules/prosemirror-schema-basic": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.2.tgz", - "integrity": "sha512-/dT4JFEGyO7QnNTe9UaKUhjDXbTNkiWTq/N4VpKaF79bBjSExVV2NXmJpcM7z/gD7mbqNjxbmWW5nf1iNSSGnw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.3.tgz", + "integrity": "sha512-h+H0OQwZVqMon1PNn0AG9cTfx513zgIG2DY00eJ00Yvgb3UD+GQ/VlWW5rcaxacpCGT1Yx8nuhwXk4+QbXUfJA==", "dependencies": { "prosemirror-model": "^1.19.0" } }, "node_modules/prosemirror-schema-list": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.4.0.tgz", - "integrity": "sha512-nZOIq/AkBSzCENxUyLm5ltWE53e2PLk65ghMN8qLQptOmDVixZlPqtMeQdiNw0odL9vNpalEjl3upgRkuJ/Jyw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.4.1.tgz", + "integrity": "sha512-jbDyaP/6AFfDfu70VzySsD75Om2t3sXTOdl5+31Wlxlg62td1haUpty/ybajSfJ1pkGadlOfwQq9kgW5IMo1Rg==", "dependencies": { "prosemirror-model": "^1.0.0", "prosemirror-state": "^1.0.0", @@ -5854,9 +5981,9 @@ } }, "node_modules/prosemirror-view": { - "version": "1.33.7", - "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.33.7.tgz", - "integrity": "sha512-jo6eMQCtPRwcrA2jISBCnm0Dd2B+szS08BU1Ay+XGiozHo5EZMHfLQE8R5nO4vb1spTH2RW1woZIYXRiQsuP8g==", + "version": "1.33.9", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.33.9.tgz", + "integrity": "sha512-xV1A0Vz9cIcEnwmMhKKFAOkfIp8XmJRnaZoPqNXrPS7EK5n11Ov8V76KhR0RsfQd/SIzmWY+bg+M44A2Lx/Nnw==", "dependencies": { "prosemirror-model": "^1.20.0", "prosemirror-state": "^1.0.0", @@ -6226,6 +6353,46 @@ "node": ">=14.0.0" } }, + "node_modules/sass-loader": { + "version": "14.2.1", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-14.2.1.tgz", + "integrity": "sha512-G0VcnMYU18a4N7VoNDegg2OuMjYtxnqzQWARVWCIVSZwJeiL9kg8QMsuIZOplsJgTzZLF6jGxI3AClj8I9nRdQ==", + "dev": true, + "dependencies": { + "neo-async": "^2.6.2" + }, + "engines": { + "node": ">= 18.12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", diff --git a/hosting/package.json b/hosting/package.json index 9b31a75d..1fbf845b 100644 --- a/hosting/package.json +++ b/hosting/package.json @@ -12,6 +12,9 @@ "codecheck": "npm run prettier:fix && npm run lint:fix" }, "dependencies": { + "@tiptap/extension-code-block-lowlight": "^2.4.0", + "@tiptap/extension-floating-menu": "^2.5.5", + "@tiptap/extension-underline": "^2.4.0", "@tiptap/pm": "^2.4.0", "@tiptap/react": "^2.4.0", "@tiptap/starter-kit": "^2.4.0", @@ -21,7 +24,9 @@ "firebase": "^10.12.0", "firebaseui": "^6.1.0", "flatpickr": "^4.6.13", + "highlight.js": "^11.10.0", "jsvectormap": "^1.5.3", + "lowlight": "^3.1.0", "next": "^14.2.3", "react": "^18.3.1", "react-apexcharts": "^1.4.1", @@ -34,6 +39,8 @@ "@iconify-json/ri": "^1.1.20", "@next/eslint-plugin-next": "^14.2.3", "@tailwindcss/typography": "^0.5.13", + "@tiptap/extension-link": "^2.5.5", + "@types/highlight.js": "^10.1.0", "@types/node": "^18.19.33", "@types/react": "^18.3.2", "@types/react-dom": "^18.3.0", @@ -50,6 +57,7 @@ "prettier": "^3.2.5", "prettier-plugin-tailwindcss": "^0.5.11", "sass": "^1.77.2", + "sass-loader": "^14.2.1", "tailwindcss": "^3.4.1", "typescript": "5.1" } diff --git a/hosting/src/components/Layouts/CmsLayout.tsx b/hosting/src/components/Layouts/CmsLayout.tsx index 81c1b4a3..634180b6 100644 --- a/hosting/src/components/Layouts/CmsLayout.tsx +++ b/hosting/src/components/Layouts/CmsLayout.tsx @@ -5,7 +5,6 @@ import Header from "@/components/Header"; import Sidebar from "@/components/Sidebar"; import {useAuthentication} from "@/hooks/useAuthentication"; import "flatpickr/dist/flatpickr.min.css"; -import "jsvectormap/dist/css/jsvectormap.css"; import React, {useState} from "react"; export default function CmsLayout({children}: {children: React.ReactNode}) { diff --git a/hosting/src/components/Tiptap/BubbleMenu.module.css b/hosting/src/components/Tiptap/BubbleMenu.module.css deleted file mode 100644 index 4ae090b1..00000000 --- a/hosting/src/components/Tiptap/BubbleMenu.module.css +++ /dev/null @@ -1,10 +0,0 @@ -.bubbleMenu { - position: absolute; - display: flex; - background: white; - border: 1px solid #ddd; - border-radius: 4px; - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); - padding: 5px; - z-index: 10; -} diff --git a/hosting/src/components/Tiptap/BubbleMenu.tsx b/hosting/src/components/Tiptap/BubbleMenu.tsx index 7ce33219..04ecdaa1 100644 --- a/hosting/src/components/Tiptap/BubbleMenu.tsx +++ b/hosting/src/components/Tiptap/BubbleMenu.tsx @@ -1,16 +1,329 @@ -import {Editor} from "@tiptap/react"; -import styles from "./BubbleMenu.module.css"; +import {Editor, BubbleMenu as TiptapBubbleMenu} from "@tiptap/react"; +import {useCallback, useState} from "react"; +import "./styles/bubble-menu.scss"; interface BubbleMenuProps { editor: Editor; } export default function BubbleMenu({editor}: BubbleMenuProps) { + const baseStyleButton = ` + flex group items-center justify-center border text-sm font-semibold rounded-md disabled:opacity-50 whitespace-nowrap bg-transparent border-transparent text-neutral-500 dark:text-neutral-400 hover:bg-black/5 hover:text-neutral-700 active:bg-black/10 active:text-neutral-800 dark:hover:bg-white/10 dark:hover:text-neutral-300 dark:active:text-neutral-200 h-8 gap-1 min-w-[2rem] px-2 w-auto + `; + const baseStyleDropdownItem = "block w-full px-4 py-2 text-left text-sm text-gray-700"; + + const [dropdownFormat, setDropdownFormat] = useState(false); + + const toggleDropdownFormat = () => { + setDropdownFormat(!dropdownFormat); + }; + + const setLink = useCallback(() => { + const previousUrl = editor.getAttributes("link").href; + const url = window.prompt("URL", previousUrl); + + // cancelled + if (url === null) { + return; + } + + // empty + if (url === "") { + editor.chain().focus().extendMarkRange("link").unsetLink().run(); + + return; + } + + // update link + editor.chain().focus().extendMarkRange("link").setLink({href: url}).run(); + }, [editor]); + return editor ? ( -
+++