diff --git a/package-lock.json b/package-lock.json index 5129222..e5d617a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,18 +16,48 @@ "@radix-ui/react-dropdown-menu": "^2.1.15", "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-popover": "^1.1.14", + "@radix-ui/react-scroll-area": "^1.2.9", "@radix-ui/react-select": "^2.2.5", "@radix-ui/react-separator": "^1.1.7", "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-tabs": "^1.1.12", "@tailwindcss/vite": "^4.1.6", - "@tiptap/pm": "^3.1.0", + "@tiptap/extension-blockquote": "^3.1.0", + "@tiptap/extension-bold": "^3.1.0", + "@tiptap/extension-code": "^3.1.0", + "@tiptap/extension-code-block": "^3.1.0", + "@tiptap/extension-color": "^3.1.0", + "@tiptap/extension-document": "^3.1.0", + "@tiptap/extension-emoji": "^3.1.0", + "@tiptap/extension-file-handler": "^3.1.0", + "@tiptap/extension-hard-break": "^3.1.0", + "@tiptap/extension-heading": "^3.1.0", + "@tiptap/extension-highlight": "^3.1.0", + "@tiptap/extension-image": "^3.1.0", + "@tiptap/extension-italic": "^3.1.0", + "@tiptap/extension-link": "^3.1.0", + "@tiptap/extension-list": "^3.1.0", + "@tiptap/extension-paragraph": "^3.1.0", + "@tiptap/extension-placeholder": "^3.1.0", + "@tiptap/extension-strike": "^3.1.0", + "@tiptap/extension-table": "^3.1.0", + "@tiptap/extension-table-cell": "^3.1.0", + "@tiptap/extension-table-header": "^3.1.0", + "@tiptap/extension-table-row": "^3.1.0", + "@tiptap/extension-task-item": "^3.1.0", + "@tiptap/extension-task-list": "^3.1.0", + "@tiptap/extension-text": "^3.1.0", + "@tiptap/extension-text-align": "^3.1.0", + "@tiptap/extension-text-style": "^3.1.0", + "@tiptap/extension-underline": "^3.1.0", + "@tiptap/extension-youtube": "^3.1.0", + "@tiptap/extensions": "^3.1.0", "@tiptap/react": "^3.1.0", - "@tiptap/starter-kit": "^3.1.0", "axios": "^1.11.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "dotenv": "^17.2.1", + "emoji-picker-react": "^4.13.2", "input-otp": "^1.4.2", "lodash.throttle": "^4.1.1", "lucide-react": "^0.510.0", @@ -41,7 +71,8 @@ "recoil": "^0.7.7", "sonner": "^2.0.6", "tailwind-merge": "^3.3.0", - "tailwindcss": "^4.1.6" + "tailwindcss": "^4.1.6", + "tippy.js": "^6.3.7" }, "devDependencies": { "@eslint/js": "^9.25.0", @@ -356,9 +387,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz", - "integrity": "sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", + "integrity": "sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA==", "cpu": [ "ppc64" ], @@ -372,9 +403,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.8.tgz", - "integrity": "sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.9.tgz", + "integrity": "sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ==", "cpu": [ "arm" ], @@ -388,9 +419,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz", - "integrity": "sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz", + "integrity": "sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg==", "cpu": [ "arm64" ], @@ -404,9 +435,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.8.tgz", - "integrity": "sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.9.tgz", + "integrity": "sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw==", "cpu": [ "x64" ], @@ -420,9 +451,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz", - "integrity": "sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz", + "integrity": "sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg==", "cpu": [ "arm64" ], @@ -436,9 +467,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz", - "integrity": "sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz", + "integrity": "sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ==", "cpu": [ "x64" ], @@ -452,9 +483,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz", - "integrity": "sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz", + "integrity": "sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q==", "cpu": [ "arm64" ], @@ -468,9 +499,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz", - "integrity": "sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz", + "integrity": "sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg==", "cpu": [ "x64" ], @@ -484,9 +515,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz", - "integrity": "sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz", + "integrity": "sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw==", "cpu": [ "arm" ], @@ -500,9 +531,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz", - "integrity": "sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz", + "integrity": "sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw==", "cpu": [ "arm64" ], @@ -516,9 +547,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz", - "integrity": "sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz", + "integrity": "sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A==", "cpu": [ "ia32" ], @@ -532,9 +563,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz", - "integrity": "sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz", + "integrity": "sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ==", "cpu": [ "loong64" ], @@ -548,9 +579,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz", - "integrity": "sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz", + "integrity": "sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA==", "cpu": [ "mips64el" ], @@ -564,9 +595,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz", - "integrity": "sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz", + "integrity": "sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w==", "cpu": [ "ppc64" ], @@ -580,9 +611,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz", - "integrity": "sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz", + "integrity": "sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg==", "cpu": [ "riscv64" ], @@ -596,9 +627,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz", - "integrity": "sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz", + "integrity": "sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA==", "cpu": [ "s390x" ], @@ -612,9 +643,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz", - "integrity": "sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz", + "integrity": "sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg==", "cpu": [ "x64" ], @@ -628,9 +659,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz", - "integrity": "sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz", + "integrity": "sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q==", "cpu": [ "arm64" ], @@ -644,9 +675,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz", - "integrity": "sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz", + "integrity": "sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g==", "cpu": [ "x64" ], @@ -660,9 +691,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz", - "integrity": "sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz", + "integrity": "sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ==", "cpu": [ "arm64" ], @@ -676,9 +707,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz", - "integrity": "sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz", + "integrity": "sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA==", "cpu": [ "x64" ], @@ -692,9 +723,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz", - "integrity": "sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz", + "integrity": "sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg==", "cpu": [ "arm64" ], @@ -708,9 +739,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz", - "integrity": "sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz", + "integrity": "sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw==", "cpu": [ "x64" ], @@ -724,9 +755,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz", - "integrity": "sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz", + "integrity": "sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ==", "cpu": [ "arm64" ], @@ -740,9 +771,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz", - "integrity": "sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz", + "integrity": "sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww==", "cpu": [ "ia32" ], @@ -756,9 +787,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz", - "integrity": "sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz", + "integrity": "sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ==", "cpu": [ "x64" ], @@ -1057,9 +1088,9 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.12", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", - "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -1076,15 +1107,15 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", - "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.29", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", - "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", + "version": "0.3.30", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", + "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1129,6 +1160,16 @@ "node": ">= 8" } }, + "node_modules/@popperjs/core": { + "version": "2.11.8", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz", + "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/@radix-ui/number": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", @@ -1706,6 +1747,37 @@ } } }, + "node_modules/@radix-ui/react-scroll-area": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.9.tgz", + "integrity": "sha512-YSjEfBXnhUELsO2VzjdtYYD4CfQjvao+lhhrX5XsHD7/cyUNzljF1FHEbgTPN7LH2MClfwRMIsYlqTYpKTTe2A==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.4", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-select": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-2.2.5.tgz", @@ -2007,7 +2079,8 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz", "integrity": "sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-beta.27", @@ -2543,6 +2616,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.1.0.tgz", "integrity": "sha512-GDxoCrA+ggdzhUcelcWWVsMcmoOYXWmpjIviYXZTyHR/fds8G/mNjG0ZpFqXNmFnZ7Rs16bAsSX2tjDZ9MyTFg==", "license": "MIT", + "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" @@ -2595,19 +2669,6 @@ "@tiptap/pm": "^3.1.0" } }, - "node_modules/@tiptap/extension-bullet-list": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-3.1.0.tgz", - "integrity": "sha512-lSuj0T/c/lAI01sgOdDUmFmnxItIC2WQHxzg16KOoDCzW/PtWBc6pNmCSexmqqGoTg9xNWytPWvKapZ/GCwhiQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/extension-list": "^3.1.0" - } - }, "node_modules/@tiptap/extension-code": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-3.1.0.tgz", @@ -2635,6 +2696,19 @@ "@tiptap/pm": "^3.1.0" } }, + "node_modules/@tiptap/extension-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-color/-/extension-color-3.1.0.tgz", + "integrity": "sha512-ERE9eMpUFUpQMPvB1Z78Wi0Y4xPU0gwzpd4We8Km+pIX2VL4iIqA+rWouj/apaMTRdxs9uSECsS3vSfisrQPMw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-text-style": "^3.1.0" + } + }, "node_modules/@tiptap/extension-document": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-3.1.0.tgz", @@ -2648,46 +2722,55 @@ "@tiptap/core": "^3.1.0" } }, - "node_modules/@tiptap/extension-dropcursor": { + "node_modules/@tiptap/extension-emoji": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-3.1.0.tgz", - "integrity": "sha512-zXyjLLcEYFl0pYQtSe12EKjByxS0qnycZhccpgQ7ePCusoDZTTyw4yE5pMxah5gkWK8N+qqynP+2oFcwcIWSLg==", + "resolved": "https://registry.npmjs.org/@tiptap/extension-emoji/-/extension-emoji-3.1.0.tgz", + "integrity": "sha512-CrwheMFxvfCNBH58Y4ZeYmgS+5RUchgOdr6cjdLEOn39jkgY/1hiN+fVqvO3iAeDiamb0S4dXB+0fwknLy8e5g==", "license": "MIT", + "dependencies": { + "emoji-regex": "^10.4.0", + "emojibase-data": "^15", + "is-emoji-supported": "^0.0.5" + }, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/extensions": "^3.1.0" + "@tiptap/core": "^3.1.0", + "@tiptap/pm": "^3.1.0", + "@tiptap/suggestion": "^3.1.0" } }, - "node_modules/@tiptap/extension-floating-menu": { + "node_modules/@tiptap/extension-file-handler": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-3.1.0.tgz", - "integrity": "sha512-dNhRw3gH9VHqaaSEZ5y7n8k5Ot1cH6jzTpXrKOFt0EhrwV+4P+knTHsvKe33AumpukailMpuSGhDr2/RQQCRTQ==", + "resolved": "https://registry.npmjs.org/@tiptap/extension-file-handler/-/extension-file-handler-3.1.0.tgz", + "integrity": "sha512-nCDFJjsmZ6KNLnYsgQYrzV8phacDinWJ3lnA1Qg0Axd6nlVwt6DPUlakUPjqUsOss02qwAxyneQknw6s9K7wow==", "license": "MIT", - "optional": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@floating-ui/dom": "^1.0.0", "@tiptap/core": "^3.1.0", + "@tiptap/extension-text-style": "^3.1.0", "@tiptap/pm": "^3.1.0" } }, - "node_modules/@tiptap/extension-gapcursor": { + "node_modules/@tiptap/extension-floating-menu": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-3.1.0.tgz", - "integrity": "sha512-9cm1ngE1SY26hCw/nzDNmWkyeZYRfidLamOuym7sg15pWj8BifTNuByrnK6fpQVSJWneV1y0npDj8WLpQ+t3CA==", + "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-3.1.0.tgz", + "integrity": "sha512-dNhRw3gH9VHqaaSEZ5y7n8k5Ot1cH6jzTpXrKOFt0EhrwV+4P+knTHsvKe33AumpukailMpuSGhDr2/RQQCRTQ==", "license": "MIT", + "optional": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/extensions": "^3.1.0" + "@floating-ui/dom": "^1.0.0", + "@tiptap/core": "^3.1.0", + "@tiptap/pm": "^3.1.0" } }, "node_modules/@tiptap/extension-hard-break": { @@ -2716,18 +2799,30 @@ "@tiptap/core": "^3.1.0" } }, - "node_modules/@tiptap/extension-horizontal-rule": { + "node_modules/@tiptap/extension-highlight": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-3.1.0.tgz", - "integrity": "sha512-EjYW72H3YAQ/yuvoMz5YtrChVesrgQ1UNB/6WynEg+frvVsfGUcNv6B9zkRT7b+XEnOVzXUW8rNlSlkrWFiSbQ==", + "resolved": "https://registry.npmjs.org/@tiptap/extension-highlight/-/extension-highlight-3.1.0.tgz", + "integrity": "sha512-uRd9li79DVfQ2z4Q4pZn7UFmgY7hqTByPvI2/py4AvCgt3/HMwKj8N2izrUyCCrBclh2to+Oet0MqWZkDZhUQA==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^3.1.0", - "@tiptap/pm": "^3.1.0" + "@tiptap/core": "^3.1.0" + } + }, + "node_modules/@tiptap/extension-image": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-image/-/extension-image-3.1.0.tgz", + "integrity": "sha512-qCvmXlkGEwyr/TnbPfGcSzdSXeq4p2nHnWVi/naPisM3JnSpPxSAa07+LxmJ8mThmsPwPAOB5BxRaGOV/SEvyQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.1.0" } }, "node_modules/@tiptap/extension-italic": { @@ -2774,23 +2869,102 @@ "@tiptap/pm": "^3.1.0" } }, - "node_modules/@tiptap/extension-list-item": { + "node_modules/@tiptap/extension-paragraph": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-3.1.0.tgz", - "integrity": "sha512-bI8v+qnlrCGmU41j19W02NpNH3jPf3qzX7tw/LmlM8uVinvjlguZzbNSWzpUFOiscEjoUcuqzGr+Cwa2CaBrQw==", + "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-3.1.0.tgz", + "integrity": "sha512-UR0FUc38IsGkfQBHhSJ5V8UGJ4juZZqnn33BzrW1L7elhlVVUM3greBXxa7vdMFBE/IcjpvOM414vJRZoBgvzw==", "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/extension-list": "^3.1.0" + "@tiptap/core": "^3.1.0" + } + }, + "node_modules/@tiptap/extension-placeholder": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-placeholder/-/extension-placeholder-3.1.0.tgz", + "integrity": "sha512-okDVyKmJUwUKvluR3lOiD6b5z/I93W58EoB4jI5akgOb/6fr+8TB+pMncwWkneQCFSQ0ws0QfZ9zkWUYlUYIYw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extensions": "^3.1.0" + } + }, + "node_modules/@tiptap/extension-strike": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-3.1.0.tgz", + "integrity": "sha512-7DzMXM5NrtTC3uVcjYgImNuXKMXonPZXwf0Q+No/sKqxtU+yXjusjVMmZqNLbzvtAFKghO0GDJGD4RxBNX9FgQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.1.0" + } + }, + "node_modules/@tiptap/extension-table": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-table/-/extension-table-3.1.0.tgz", + "integrity": "sha512-A1MRDzpmKwgqWVMmo3PCwyt4g1GhLDavWYur+XjC40fA3vvow+aROfTZTcKJkAti4p5/6zyS/fRx2KA43Oumag==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.1.0", + "@tiptap/pm": "^3.1.0" } }, - "node_modules/@tiptap/extension-list-keymap": { + "node_modules/@tiptap/extension-table-cell": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-list-keymap/-/extension-list-keymap-3.1.0.tgz", - "integrity": "sha512-te50GvzfAaTV+SPR9iH/NGv/nDMaAKhYhr2m0XhuDaVmjgNIkWTKcTCxWt/9eljVJskFMvTHWXV3Tf/48basRg==", + "resolved": "https://registry.npmjs.org/@tiptap/extension-table-cell/-/extension-table-cell-3.1.0.tgz", + "integrity": "sha512-T3T7VlgLhMAABUepwrWPWT1Un6VNs21dtlFoZRYkpmp3aNTPL6Qy7of0l13epHGuiZaYp/pBeaQ/WyUOVROxMg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-table": "^3.1.0" + } + }, + "node_modules/@tiptap/extension-table-header": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-table-header/-/extension-table-header-3.1.0.tgz", + "integrity": "sha512-OawTXgi00OJ3VhoHtapHjlzhWXQdm3PLhW0d1FPQPly2I42sg2gRoke2KSpI7HKPbMI2zZpG89W5/3tXiDRaOA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-table": "^3.1.0" + } + }, + "node_modules/@tiptap/extension-table-row": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-table-row/-/extension-table-row-3.1.0.tgz", + "integrity": "sha512-J6Kkibpe0gofWFe/VOq0E+FJSCs4sjs9GW0vc+FvBkOI8uPTi255p3pjMIFeJt/o4uXYh4V+jGBBE+CqFTC8uA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-table": "^3.1.0" + } + }, + "node_modules/@tiptap/extension-task-item": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-task-item/-/extension-task-item-3.1.0.tgz", + "integrity": "sha512-/YNPrgv2jzYWBEJSf3YkdPWPr3f8I3310nz5DT3w01qy4HjFhkqa0dL/JKJTSYcx+trjd3i/fb/1TXOyhDGpKQ==", "license": "MIT", "funding": { "type": "github", @@ -2800,10 +2974,10 @@ "@tiptap/extension-list": "^3.1.0" } }, - "node_modules/@tiptap/extension-ordered-list": { + "node_modules/@tiptap/extension-task-list": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-3.1.0.tgz", - "integrity": "sha512-bK85PC89/sUyGM3BL0dey8rGBkuDRYA2ynMGa/p+JG0Esqb0o5aKtNACTUKTYOdrDJw5kxNVE4BPzCkqO9/rsQ==", + "resolved": "https://registry.npmjs.org/@tiptap/extension-task-list/-/extension-task-list-3.1.0.tgz", + "integrity": "sha512-FcY0j+yKhiapHIqa7+J933TIGhwmC3qugT5DsS2N7e9XB1Q6+WIVjIbqXus0BdO10DSeIxf9R4H/ObkSMyb8Nw==", "license": "MIT", "funding": { "type": "github", @@ -2813,10 +2987,10 @@ "@tiptap/extension-list": "^3.1.0" } }, - "node_modules/@tiptap/extension-paragraph": { + "node_modules/@tiptap/extension-text": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-3.1.0.tgz", - "integrity": "sha512-UR0FUc38IsGkfQBHhSJ5V8UGJ4juZZqnn33BzrW1L7elhlVVUM3greBXxa7vdMFBE/IcjpvOM414vJRZoBgvzw==", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-3.1.0.tgz", + "integrity": "sha512-BW1FEG4upSfhqBpBiPdEi8IMMJDmu0ThvZWYF385WVveQ5/jFK98RS2Kz7qt82jVvw2oyhOUL4Yy63T0Bh6W1w==", "license": "MIT", "funding": { "type": "github", @@ -2826,10 +3000,10 @@ "@tiptap/core": "^3.1.0" } }, - "node_modules/@tiptap/extension-strike": { + "node_modules/@tiptap/extension-text-align": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-3.1.0.tgz", - "integrity": "sha512-7DzMXM5NrtTC3uVcjYgImNuXKMXonPZXwf0Q+No/sKqxtU+yXjusjVMmZqNLbzvtAFKghO0GDJGD4RxBNX9FgQ==", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text-align/-/extension-text-align-3.1.0.tgz", + "integrity": "sha512-b4Tpj3BvRe41iFjxDSFXObdtOGyK8Hy6sy9EHc7vYDn+NhhZgTcnwUf6QX6H/7JcItRUNi17W9KNSA1+0ZzXBg==", "license": "MIT", "funding": { "type": "github", @@ -2839,10 +3013,10 @@ "@tiptap/core": "^3.1.0" } }, - "node_modules/@tiptap/extension-text": { + "node_modules/@tiptap/extension-text-style": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-3.1.0.tgz", - "integrity": "sha512-BW1FEG4upSfhqBpBiPdEi8IMMJDmu0ThvZWYF385WVveQ5/jFK98RS2Kz7qt82jVvw2oyhOUL4Yy63T0Bh6W1w==", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text-style/-/extension-text-style-3.1.0.tgz", + "integrity": "sha512-OPbOGD2SCSfosbzsr+nw9Uv2O14TpfYgCa8hIODLB7Sz1pRy3elqsAuIkA8G/po2TuPLD4Z4HxzL7dnPq/G5Lw==", "license": "MIT", "funding": { "type": "github", @@ -2865,6 +3039,19 @@ "@tiptap/core": "^3.1.0" } }, + "node_modules/@tiptap/extension-youtube": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@tiptap/extension-youtube/-/extension-youtube-3.1.0.tgz", + "integrity": "sha512-zJ+A8UTcynkjqU513bqv6CvspWqhcIfmHKE0h/XdjtAODEZ6COHDoxvxZMZ7ufXsDhFimmXegraWu+XEbp0tZw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.1.0" + } + }, "node_modules/@tiptap/extensions": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.1.0.tgz", @@ -2884,6 +3071,7 @@ "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.1.0.tgz", "integrity": "sha512-9Pjr+bC89/ATSl5J0UMVrr50TML3B5viDoMMpksgkSrnQSJyuGGfCc8DHd0TKydxucMcjVG/oq+evyCW9xXRRQ==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-changeset": "^2.3.0", "prosemirror-collab": "^1.3.1", @@ -2934,40 +3122,19 @@ "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/@tiptap/starter-kit": { + "node_modules/@tiptap/suggestion": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-3.1.0.tgz", - "integrity": "sha512-L+9WfA+XO4mwq4b0lEUr540q+jIENhZiVSNhOYdWlRyan+HCV60BkC8E/nBuqCk6tbM1jEqFQjVBqJWwjBsalQ==", + "resolved": "https://registry.npmjs.org/@tiptap/suggestion/-/suggestion-3.1.0.tgz", + "integrity": "sha512-UzMDxYhqiFqRsBMMsAxzwsseveOtiCGWb5CADZOsrj7EjNzuzJNy+Mr8jB3p3uM3Hmv3GBCLQkCYjEZfrIKZ1w==", "license": "MIT", - "dependencies": { - "@tiptap/core": "^3.1.0", - "@tiptap/extension-blockquote": "^3.1.0", - "@tiptap/extension-bold": "^3.1.0", - "@tiptap/extension-bullet-list": "^3.1.0", - "@tiptap/extension-code": "^3.1.0", - "@tiptap/extension-code-block": "^3.1.0", - "@tiptap/extension-document": "^3.1.0", - "@tiptap/extension-dropcursor": "^3.1.0", - "@tiptap/extension-gapcursor": "^3.1.0", - "@tiptap/extension-hard-break": "^3.1.0", - "@tiptap/extension-heading": "^3.1.0", - "@tiptap/extension-horizontal-rule": "^3.1.0", - "@tiptap/extension-italic": "^3.1.0", - "@tiptap/extension-link": "^3.1.0", - "@tiptap/extension-list": "^3.1.0", - "@tiptap/extension-list-item": "^3.1.0", - "@tiptap/extension-list-keymap": "^3.1.0", - "@tiptap/extension-ordered-list": "^3.1.0", - "@tiptap/extension-paragraph": "^3.1.0", - "@tiptap/extension-strike": "^3.1.0", - "@tiptap/extension-text": "^3.1.0", - "@tiptap/extension-underline": "^3.1.0", - "@tiptap/extensions": "^3.1.0", - "@tiptap/pm": "^3.1.0" - }, + "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "^3.1.0", + "@tiptap/pm": "^3.1.0" } }, "node_modules/@types/babel__core": { @@ -3039,13 +3206,15 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/markdown-it": { "version": "14.1.2", "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.2.tgz", "integrity": "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==", "license": "MIT", + "peer": true, "dependencies": { "@types/linkify-it": "^5", "@types/mdurl": "^2" @@ -3055,7 +3224,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/@types/node": { "version": "22.17.1", @@ -3068,9 +3238,9 @@ } }, "node_modules/@types/react": { - "version": "19.1.9", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.9.tgz", - "integrity": "sha512-WmdoynAX8Stew/36uTSVMcLJJ1KRh6L3IZRx1PZ7qJtBqT3dYTgyDTx8H1qoRghErydW7xw9mSJ3wS//tCRpFA==", + "version": "19.1.10", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.10.tgz", + "integrity": "sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg==", "devOptional": true, "license": "MIT", "dependencies": { @@ -3117,17 +3287,17 @@ "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.39.0.tgz", - "integrity": "sha512-bhEz6OZeUR+O/6yx9Jk6ohX6H9JSFTaiY0v9/PuKT3oGK0rn0jNplLmyFUGV+a9gfYnVNwGDwS/UkLIuXNb2Rw==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.39.1.tgz", + "integrity": "sha512-yYegZ5n3Yr6eOcqgj2nJH8cH/ZZgF+l0YIdKILSDjYFRjgYQMgv/lRjV5Z7Up04b9VYUondt8EPMqg7kTWgJ2g==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.39.0", - "@typescript-eslint/type-utils": "8.39.0", - "@typescript-eslint/utils": "8.39.0", - "@typescript-eslint/visitor-keys": "8.39.0", + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/type-utils": "8.39.1", + "@typescript-eslint/utils": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", @@ -3141,7 +3311,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^8.39.0", + "@typescript-eslint/parser": "^8.39.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } @@ -3157,16 +3327,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.39.0.tgz", - "integrity": "sha512-g3WpVQHngx0aLXn6kfIYCZxM6rRJlWzEkVpqEFLT3SgEDsp9cpCbxxgwnE504q4H+ruSDh/VGS6nqZIDynP+vg==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.39.1.tgz", + "integrity": "sha512-pUXGCuHnnKw6PyYq93lLRiZm3vjuslIy7tus1lIQTYVK9bL8XBgJnCWm8a0KcTtHC84Yya1Q6rtll+duSMj0dg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.39.0", - "@typescript-eslint/types": "8.39.0", - "@typescript-eslint/typescript-estree": "8.39.0", - "@typescript-eslint/visitor-keys": "8.39.0", + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", "debug": "^4.3.4" }, "engines": { @@ -3182,14 +3352,14 @@ } }, "node_modules/@typescript-eslint/project-service": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.0.tgz", - "integrity": "sha512-CTzJqaSq30V/Z2Og9jogzZt8lJRR5TKlAdXmWgdu4hgcC9Kww5flQ+xFvMxIBWVNdxJO7OifgdOK4PokMIWPew==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.1.tgz", + "integrity": "sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.39.0", - "@typescript-eslint/types": "^8.39.0", + "@typescript-eslint/tsconfig-utils": "^8.39.1", + "@typescript-eslint/types": "^8.39.1", "debug": "^4.3.4" }, "engines": { @@ -3204,14 +3374,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.0.tgz", - "integrity": "sha512-8QOzff9UKxOh6npZQ/4FQu4mjdOCGSdO3p44ww0hk8Vu+IGbg0tB/H1LcTARRDzGCC8pDGbh2rissBuuoPgH8A==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.1.tgz", + "integrity": "sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.39.0", - "@typescript-eslint/visitor-keys": "8.39.0" + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3222,9 +3392,9 @@ } }, "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.0.tgz", - "integrity": "sha512-Fd3/QjmFV2sKmvv3Mrj8r6N8CryYiCS8Wdb/6/rgOXAWGcFuc+VkQuG28uk/4kVNVZBQuuDHEDUpo/pQ32zsIQ==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.1.tgz", + "integrity": "sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==", "dev": true, "license": "MIT", "engines": { @@ -3239,15 +3409,15 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.39.0.tgz", - "integrity": "sha512-6B3z0c1DXVT2vYA9+z9axjtc09rqKUPRmijD5m9iv8iQpHBRYRMBcgxSiKTZKm6FwWw1/cI4v6em35OsKCiN5Q==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.39.1.tgz", + "integrity": "sha512-gu9/ahyatyAdQbKeHnhT4R+y3YLtqqHyvkfDxaBYk97EcbfChSJXyaJnIL3ygUv7OuZatePHmQvuH5ru0lnVeA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.39.0", - "@typescript-eslint/typescript-estree": "8.39.0", - "@typescript-eslint/utils": "8.39.0", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/utils": "8.39.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, @@ -3264,9 +3434,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.0.tgz", - "integrity": "sha512-ArDdaOllnCj3yn/lzKn9s0pBQYmmyme/v1HbGIGB0GB/knFI3fWMHloC+oYTJW46tVbYnGKTMDK4ah1sC2v0Kg==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.1.tgz", + "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", "dev": true, "license": "MIT", "engines": { @@ -3278,16 +3448,16 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.0.tgz", - "integrity": "sha512-ndWdiflRMvfIgQRpckQQLiB5qAKQ7w++V4LlCHwp62eym1HLB/kw7D9f2e8ytONls/jt89TEasgvb+VwnRprsw==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.1.tgz", + "integrity": "sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/project-service": "8.39.0", - "@typescript-eslint/tsconfig-utils": "8.39.0", - "@typescript-eslint/types": "8.39.0", - "@typescript-eslint/visitor-keys": "8.39.0", + "@typescript-eslint/project-service": "8.39.1", + "@typescript-eslint/tsconfig-utils": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -3346,16 +3516,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.39.0.tgz", - "integrity": "sha512-4GVSvNA0Vx1Ktwvf4sFE+exxJ3QGUorQG1/A5mRfRNZtkBT2xrA/BCO2H0eALx/PnvCS6/vmYwRdDA41EoffkQ==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.39.1.tgz", + "integrity": "sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", - "@typescript-eslint/scope-manager": "8.39.0", - "@typescript-eslint/types": "8.39.0", - "@typescript-eslint/typescript-estree": "8.39.0" + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3370,13 +3540,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.0.tgz", - "integrity": "sha512-ldgiJ+VAhQCfIjeOgu8Kj5nSxds0ktPOSO9p4+0VDH2R2pLvQraaM5Oen2d7NxzMCm+Sn/vJT+mv2H5u6b/3fA==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.1.tgz", + "integrity": "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.39.0", + "@typescript-eslint/types": "8.39.1", "eslint-visitor-keys": "^4.2.1" }, "engines": { @@ -3713,7 +3883,8 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/cross-spawn": { "version": "7.0.6", @@ -3813,12 +3984,60 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.199", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.199.tgz", - "integrity": "sha512-3gl0S7zQd88kCAZRO/DnxtBKuhMO4h0EaQIN3YgZfV6+pW+5+bf2AdQeHNESCoaQqo/gjGVYEf2YM4O5HJQqpQ==", + "version": "1.5.200", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.200.tgz", + "integrity": "sha512-rFCxROw7aOe4uPTfIAx+rXv9cEcGx+buAF4npnhtTqCJk5KDFRnh3+KYj7rdVh6lsFt5/aPs+Irj9rZ33WMA7w==", "dev": true, "license": "ISC" }, + "node_modules/emoji-picker-react": { + "version": "4.13.2", + "resolved": "https://registry.npmjs.org/emoji-picker-react/-/emoji-picker-react-4.13.2.tgz", + "integrity": "sha512-azaJQLTshEOZVhksgU136izJWJyZ4Clx6xQ6Vctzk1gOdPPAUbTa/JYDwZJ8rh97QxnjpyeftXl99eRlYr3vNA==", + "license": "MIT", + "dependencies": { + "flairup": "1.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16" + } + }, + "node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "license": "MIT" + }, + "node_modules/emojibase": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/emojibase/-/emojibase-16.0.0.tgz", + "integrity": "sha512-Nw2m7JLIO4Ou2X/yZPRNscHQXVbbr6SErjkJ7EooG7MbR3yDZszCv9KTizsXFc7yZl0n3WF+qUKIC/Lw6H9xaQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=18.12.0" + }, + "funding": { + "type": "ko-fi", + "url": "https://ko-fi.com/milesjohnson" + } + }, + "node_modules/emojibase-data": { + "version": "15.3.2", + "resolved": "https://registry.npmjs.org/emojibase-data/-/emojibase-data-15.3.2.tgz", + "integrity": "sha512-TpDyTDDTdqWIJixV5sTA6OQ0P0JfIIeK2tFRR3q56G9LK65ylAZ7z3KyBXokpvTTJ+mLUXQXbLNyVkjvnTLE+A==", + "license": "MIT", + "funding": { + "type": "ko-fi", + "url": "https://ko-fi.com/milesjohnson" + }, + "peerDependencies": { + "emojibase": "*" + } + }, "node_modules/enhanced-resolve": { "version": "5.18.3", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", @@ -3837,6 +4056,7 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "license": "BSD-2-Clause", + "peer": true, "engines": { "node": ">=0.12" }, @@ -3890,9 +4110,9 @@ } }, "node_modules/esbuild": { - "version": "0.25.8", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz", - "integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==", + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.9.tgz", + "integrity": "sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g==", "hasInstallScript": true, "license": "MIT", "bin": { @@ -3902,32 +4122,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.8", - "@esbuild/android-arm": "0.25.8", - "@esbuild/android-arm64": "0.25.8", - "@esbuild/android-x64": "0.25.8", - "@esbuild/darwin-arm64": "0.25.8", - "@esbuild/darwin-x64": "0.25.8", - "@esbuild/freebsd-arm64": "0.25.8", - "@esbuild/freebsd-x64": "0.25.8", - "@esbuild/linux-arm": "0.25.8", - "@esbuild/linux-arm64": "0.25.8", - "@esbuild/linux-ia32": "0.25.8", - "@esbuild/linux-loong64": "0.25.8", - "@esbuild/linux-mips64el": "0.25.8", - "@esbuild/linux-ppc64": "0.25.8", - "@esbuild/linux-riscv64": "0.25.8", - "@esbuild/linux-s390x": "0.25.8", - "@esbuild/linux-x64": "0.25.8", - "@esbuild/netbsd-arm64": "0.25.8", - "@esbuild/netbsd-x64": "0.25.8", - "@esbuild/openbsd-arm64": "0.25.8", - "@esbuild/openbsd-x64": "0.25.8", - "@esbuild/openharmony-arm64": "0.25.8", - "@esbuild/sunos-x64": "0.25.8", - "@esbuild/win32-arm64": "0.25.8", - "@esbuild/win32-ia32": "0.25.8", - "@esbuild/win32-x64": "0.25.8" + "@esbuild/aix-ppc64": "0.25.9", + "@esbuild/android-arm": "0.25.9", + "@esbuild/android-arm64": "0.25.9", + "@esbuild/android-x64": "0.25.9", + "@esbuild/darwin-arm64": "0.25.9", + "@esbuild/darwin-x64": "0.25.9", + "@esbuild/freebsd-arm64": "0.25.9", + "@esbuild/freebsd-x64": "0.25.9", + "@esbuild/linux-arm": "0.25.9", + "@esbuild/linux-arm64": "0.25.9", + "@esbuild/linux-ia32": "0.25.9", + "@esbuild/linux-loong64": "0.25.9", + "@esbuild/linux-mips64el": "0.25.9", + "@esbuild/linux-ppc64": "0.25.9", + "@esbuild/linux-riscv64": "0.25.9", + "@esbuild/linux-s390x": "0.25.9", + "@esbuild/linux-x64": "0.25.9", + "@esbuild/netbsd-arm64": "0.25.9", + "@esbuild/netbsd-x64": "0.25.9", + "@esbuild/openbsd-arm64": "0.25.9", + "@esbuild/openbsd-x64": "0.25.9", + "@esbuild/openharmony-arm64": "0.25.9", + "@esbuild/sunos-x64": "0.25.9", + "@esbuild/win32-arm64": "0.25.9", + "@esbuild/win32-ia32": "0.25.9", + "@esbuild/win32-x64": "0.25.9" } }, "node_modules/escalade": { @@ -4233,6 +4453,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/flairup": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flairup/-/flairup-1.0.0.tgz", + "integrity": "sha512-IKlE+pNvL2R+kVL1kEhUYqRxVqeFnjiIvHWDMLFXNaqyUdFXQM2wte44EfMYJNHkW16X991t2Zg8apKkhv7OBA==", + "license": "MIT" + }, "node_modules/flat-cache": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", @@ -4522,6 +4748,12 @@ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc" } }, + "node_modules/is-emoji-supported": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/is-emoji-supported/-/is-emoji-supported-0.0.5.tgz", + "integrity": "sha512-WOlXUhDDHxYqcSmFZis+xWhhqXiK2SU0iYiqmth5Ip0FHLZQAt9rKL5ahnilE8/86WH8tZ3bmNNNC+bTzamqlw==", + "license": "MIT" + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -4894,6 +5126,7 @@ "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", "license": "MIT", + "peer": true, "dependencies": { "uc.micro": "^2.0.0" } @@ -4978,6 +5211,7 @@ "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", "license": "MIT", + "peer": true, "dependencies": { "argparse": "^2.0.1", "entities": "^4.4.0", @@ -5003,7 +5237,8 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/merge2": { "version": "1.4.1", @@ -5179,7 +5414,8 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz", "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/p-limit": { "version": "3.1.0", @@ -5308,6 +5544,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.3.1.tgz", "integrity": "sha512-j0kORIBm8ayJNl3zQvD1TTPHJX3g042et6y/KQhZhnPrruO8exkTgG8X+NRpj7kIyMMEx74Xb3DyMIBtO0IKkQ==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-transform": "^1.0.0" } @@ -5317,6 +5554,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-collab/-/prosemirror-collab-1.3.1.tgz", "integrity": "sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-state": "^1.0.0" } @@ -5326,6 +5564,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.1.tgz", "integrity": "sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-model": "^1.0.0", "prosemirror-state": "^1.0.0", @@ -5337,6 +5576,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.2.tgz", "integrity": "sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-state": "^1.0.0", "prosemirror-transform": "^1.1.0", @@ -5348,6 +5588,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.3.2.tgz", "integrity": "sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-keymap": "^1.0.0", "prosemirror-model": "^1.0.0", @@ -5360,6 +5601,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.4.1.tgz", "integrity": "sha512-2JZD8z2JviJrboD9cPuX/Sv/1ChFng+xh2tChQ2X4bB2HeK+rra/bmJ3xGntCcjhOqIzSDG6Id7e8RJ9QPXLEQ==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-state": "^1.2.2", "prosemirror-transform": "^1.0.0", @@ -5372,6 +5614,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.5.0.tgz", "integrity": "sha512-K0xJRCmt+uSw7xesnHmcn72yBGTbY45vm8gXI4LZXbx2Z0jwh5aF9xrGQgrVPu0WbyFVFF3E/o9VhJYz6SQWnA==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-state": "^1.0.0", "prosemirror-transform": "^1.0.0" @@ -5382,6 +5625,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.3.tgz", "integrity": "sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-state": "^1.0.0", "w3c-keyname": "^2.2.0" @@ -5392,6 +5636,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-markdown/-/prosemirror-markdown-1.13.2.tgz", "integrity": "sha512-FPD9rHPdA9fqzNmIIDhhnYQ6WgNoSWX9StUZ8LEKapaXU9i6XgykaHKhp6XMyXlOWetmaFgGDS/nu/w9/vUc5g==", "license": "MIT", + "peer": true, "dependencies": { "@types/markdown-it": "^14.0.0", "markdown-it": "^14.0.0", @@ -5403,6 +5648,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-menu/-/prosemirror-menu-1.2.5.tgz", "integrity": "sha512-qwXzynnpBIeg1D7BAtjOusR+81xCp53j7iWu/IargiRZqRjGIlQuu1f3jFi+ehrHhWMLoyOQTSRx/IWZJqOYtQ==", "license": "MIT", + "peer": true, "dependencies": { "crelt": "^1.0.0", "prosemirror-commands": "^1.0.0", @@ -5415,6 +5661,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.3.tgz", "integrity": "sha512-dY2HdaNXlARknJbrManZ1WyUtos+AP97AmvqdOQtWtrrC5g4mohVX5DTi9rXNFSk09eczLq9GuNTtq3EfMeMGA==", "license": "MIT", + "peer": true, "dependencies": { "orderedmap": "^2.0.0" } @@ -5424,6 +5671,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-schema-basic/-/prosemirror-schema-basic-1.2.4.tgz", "integrity": "sha512-ELxP4TlX3yr2v5rM7Sb70SqStq5NvI15c0j9j/gjsrO5vaw+fnnpovCLEGIcpeGfifkuqJwl4fon6b+KdrODYQ==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-model": "^1.25.0" } @@ -5433,6 +5681,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.1.tgz", "integrity": "sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-model": "^1.0.0", "prosemirror-state": "^1.0.0", @@ -5444,6 +5693,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.3.tgz", "integrity": "sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-model": "^1.0.0", "prosemirror-transform": "^1.0.0", @@ -5455,6 +5705,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.7.1.tgz", "integrity": "sha512-eRQ97Bf+i9Eby99QbyAiyov43iOKgWa7QCGly+lrDt7efZ1v8NWolhXiB43hSDGIXT1UXgbs4KJN3a06FGpr1Q==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-keymap": "^1.2.2", "prosemirror-model": "^1.25.0", @@ -5468,6 +5719,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-trailing-node/-/prosemirror-trailing-node-3.0.0.tgz", "integrity": "sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ==", "license": "MIT", + "peer": true, "dependencies": { "@remirror/core-constants": "3.0.0", "escape-string-regexp": "^4.0.0" @@ -5483,6 +5735,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.10.4.tgz", "integrity": "sha512-pwDy22nAnGqNR1feOQKHxoFkkUtepoFAd3r2hbEDsnf4wp57kKA36hXsB3njA9FtONBEwSDnDeCiJe+ItD+ykw==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-model": "^1.21.0" } @@ -5492,6 +5745,7 @@ "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.40.1.tgz", "integrity": "sha512-pbwUjt3G7TlsQQHDiYSupWBhJswpLVB09xXm1YiJPdkjkh9Pe7Y51XdLh5VWIZmROLY8UpUpG03lkdhm9lzIBA==", "license": "MIT", + "peer": true, "dependencies": { "prosemirror-model": "^1.20.0", "prosemirror-state": "^1.0.0", @@ -5519,6 +5773,7 @@ "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", "license": "MIT", + "peer": true, "engines": { "node": ">=6" } @@ -5783,7 +6038,8 @@ "version": "1.3.4", "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz", "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/run-parallel": { "version": "1.2.0", @@ -6001,6 +6257,15 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tippy.js": { + "version": "6.3.7", + "resolved": "https://registry.npmjs.org/tippy.js/-/tippy.js-6.3.7.tgz", + "integrity": "sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==", + "license": "MIT", + "dependencies": { + "@popperjs/core": "^2.9.0" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -6071,16 +6336,16 @@ } }, "node_modules/typescript-eslint": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.39.0.tgz", - "integrity": "sha512-lH8FvtdtzcHJCkMOKnN73LIn6SLTpoojgJqDAxPm1jCR14eWSGPX8ul/gggBdPMk/d5+u9V854vTYQ8T5jF/1Q==", + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.39.1.tgz", + "integrity": "sha512-GDUv6/NDYngUlNvwaHM1RamYftxf782IyEDbdj3SeaIHHv8fNQVRC++fITT7kUJV/5rIA/tkoRSSskt6osEfqg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/eslint-plugin": "8.39.0", - "@typescript-eslint/parser": "8.39.0", - "@typescript-eslint/typescript-estree": "8.39.0", - "@typescript-eslint/utils": "8.39.0" + "@typescript-eslint/eslint-plugin": "8.39.1", + "@typescript-eslint/parser": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/utils": "8.39.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -6098,7 +6363,8 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/undici-types": { "version": "6.21.0", @@ -6304,7 +6570,8 @@ "version": "2.2.8", "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/which": { "version": "2.0.2", diff --git a/package.json b/package.json index e425084..7480595 100644 --- a/package.json +++ b/package.json @@ -18,18 +18,48 @@ "@radix-ui/react-dropdown-menu": "^2.1.15", "@radix-ui/react-label": "^2.1.7", "@radix-ui/react-popover": "^1.1.14", + "@radix-ui/react-scroll-area": "^1.2.9", "@radix-ui/react-select": "^2.2.5", "@radix-ui/react-separator": "^1.1.7", "@radix-ui/react-slot": "^1.2.3", "@radix-ui/react-tabs": "^1.1.12", "@tailwindcss/vite": "^4.1.6", - "@tiptap/pm": "^3.1.0", + "@tiptap/extension-blockquote": "^3.1.0", + "@tiptap/extension-bold": "^3.1.0", + "@tiptap/extension-code": "^3.1.0", + "@tiptap/extension-code-block": "^3.1.0", + "@tiptap/extension-color": "^3.1.0", + "@tiptap/extension-document": "^3.1.0", + "@tiptap/extension-emoji": "^3.1.0", + "@tiptap/extension-file-handler": "^3.1.0", + "@tiptap/extension-hard-break": "^3.1.0", + "@tiptap/extension-heading": "^3.1.0", + "@tiptap/extension-highlight": "^3.1.0", + "@tiptap/extension-image": "^3.1.0", + "@tiptap/extension-italic": "^3.1.0", + "@tiptap/extension-link": "^3.1.0", + "@tiptap/extension-list": "^3.1.0", + "@tiptap/extension-paragraph": "^3.1.0", + "@tiptap/extension-placeholder": "^3.1.0", + "@tiptap/extension-strike": "^3.1.0", + "@tiptap/extension-table": "^3.1.0", + "@tiptap/extension-table-cell": "^3.1.0", + "@tiptap/extension-table-header": "^3.1.0", + "@tiptap/extension-table-row": "^3.1.0", + "@tiptap/extension-task-item": "^3.1.0", + "@tiptap/extension-task-list": "^3.1.0", + "@tiptap/extension-text": "^3.1.0", + "@tiptap/extension-text-align": "^3.1.0", + "@tiptap/extension-text-style": "^3.1.0", + "@tiptap/extension-underline": "^3.1.0", + "@tiptap/extension-youtube": "^3.1.0", + "@tiptap/extensions": "^3.1.0", "@tiptap/react": "^3.1.0", - "@tiptap/starter-kit": "^3.1.0", "axios": "^1.11.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "dotenv": "^17.2.1", + "emoji-picker-react": "^4.13.2", "input-otp": "^1.4.2", "lodash.throttle": "^4.1.1", "lucide-react": "^0.510.0", @@ -43,7 +73,8 @@ "recoil": "^0.7.7", "sonner": "^2.0.6", "tailwind-merge": "^3.3.0", - "tailwindcss": "^4.1.6" + "tailwindcss": "^4.1.6", + "tippy.js": "^6.3.7" }, "devDependencies": { "@eslint/js": "^9.25.0", diff --git a/src/components/dash-navbar.tsx b/src/components/dash-navbar.tsx index 568c6eb..989df79 100644 --- a/src/components/dash-navbar.tsx +++ b/src/components/dash-navbar.tsx @@ -7,7 +7,7 @@ import { DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { ModeToggle } from "./mode-toggle"; -import { useAdminData } from "@/store/hooks/useAdminData"; +import { useAdminData } from "@/store/hooks/users/useAdminData"; import { Skeleton } from "./ui/skeleton"; import { Link } from "react-router-dom"; diff --git a/src/components/dashboard-banner.tsx b/src/components/dashboard-banner.tsx new file mode 100644 index 0000000..374a75b --- /dev/null +++ b/src/components/dashboard-banner.tsx @@ -0,0 +1,25 @@ +import type { DashboardBannerData } from "@/types"; + +const DashboardBanner = ({ + bannerTitle, + bannerDescription, + bannerButton, + date, +}: DashboardBannerData) => { + return ( +
+
+
+

+ {bannerTitle} +

+

{bannerDescription}

+

{date}

+
+ {bannerButton} +
+
+ ); +}; + +export default DashboardBanner; diff --git a/src/components/dashboard-status-card.tsx b/src/components/dashboard-status-card.tsx new file mode 100644 index 0000000..47afd4f --- /dev/null +++ b/src/components/dashboard-status-card.tsx @@ -0,0 +1,28 @@ +import { Card, CardContent } from "@/components/ui/card"; +import type { DashboardStatusCard } from "@/types"; + +const DasshboardStatusCard = ({ + statusIcon, + iconColor, + statusNumber, + ststasDescription, + classname, +}: DashboardStatusCard) => { + return ( + + +
+
+
{statusIcon}
+
+
+

{statusNumber}

+

{ststasDescription}

+
+
+
+
+ ); +}; + +export default DasshboardStatusCard; diff --git a/src/components/dashboard-welcome.tsx b/src/components/dashboard-welcome.tsx index 569a6b6..ec98cd9 100644 --- a/src/components/dashboard-welcome.tsx +++ b/src/components/dashboard-welcome.tsx @@ -1,4 +1,4 @@ -import { useAdminData } from "@/store/hooks/useAdminData"; +import { useAdminData } from "@/store/hooks/users/useAdminData"; import { AlertCircle, Verified } from "lucide-react"; import { Link } from "react-router-dom"; diff --git a/src/components/editor/constant/index.ts b/src/components/editor/constant/index.ts new file mode 100644 index 0000000..a1cd169 --- /dev/null +++ b/src/components/editor/constant/index.ts @@ -0,0 +1,221 @@ +/** Default lang */ +export const DEFAULT_LANG_VALUE = "en"; + +/** Throttle time for editor input (milliseconds) */ +export const EDITOR_UPDATE_THROTTLE_WAIT_TIME = 200; + +/** + * watch throttling time must be less than the update time + * otherwise the cursor position will reach the end + */ +export const EDITOR_UPDATE_WATCH_THROTTLE_WAIT_TIME = + EDITOR_UPDATE_THROTTLE_WAIT_TIME - 80; + +/** Minimum size for image adjustments */ +export const IMAGE_MIN_SIZE = 20; +/** Maximum size for image adjustments */ +export const IMAGE_MAX_SIZE = 100_000; +/** Throttle time during adjustments for images (milliseconds) */ +export const IMAGE_THROTTLE_WAIT_TIME = 16; + +/** Default number of rows and columns for grids when creating a table */ +export const TABLE_INIT_GRID_SIZE = 10; +/** Maximum number of rows and columns for grids when creating a table */ +export const TABLE_MAX_GRID_SIZE = 10; +/** Minimum number of rows and columns for grids when creating a table */ +export const TABLE_DEFAULT_SELECTED_GRID_SIZE = 2; + +export const DEFAULT_COLOR = "#262626"; +/** Default color list for text color and text highlight */ +export const COLORS_LIST = [ + "#000000", + "#262626", + "#595959", + "#8C8C8C", + "#BFBFBF", + "#D9D9D9", + "#E9E9E9", + "#F5F5F5", + "#FAFAFA", + "#FFFFFF", + "#F5222D", + "#FA541C", + "#FA8C16", + "#FADB14", + "#52C41A", + "#13C2C2", + "#1890FF", + "#2F54EB", + "#722ED1", + "#EB2F96", + "#FFE8E6", + "#FFECE0", + "#FFEFD1", + "#FCFCCA", + "#E4F7D2", + "#D3F5F0", + "#D4EEFC", + "#DEE8FC", + "#EFE1FA", + "#FAE1EB", + "#FFA39E", + "#FFBB96", + "#FFD591", + "#FFFB8F", + "#B7EB8F", + "#87E8DE", + "#91D5FF", + "#ADC6FF", + "#D3ADF7", + "#FFADD2", + "#FF4D4F", + "#FF7A45", + "#FFA940", + "#FFEC3D", + "#73D13D", + "#36CFC9", + "#40A9FF", + "#597EF7", + "#9254DE", + "#F759AB", + "#CF1322", + "#D4380D", + "#D46B08", + "#D4B106", + "#389E0D", + "#08979C", + "#096DD9", + "#1D39C4", + "#531DAB", + "#C41D7F", + "#820014", + "#871400", + "#873800", + "#614700", + "#135200", + "#00474F", + "#003A8C", + "#061178", + "#22075E", + "#780650", +] as const; + +/** Default font family list */ +export const DEFAULT_FONT_FAMILY_LIST = [ + "Inter", + "Comic Sans MS, Comic Sans", + "serif", + "cursive", + "Arial", + "Arial Black", + "Georgia", + "Impact", + "Tahoma", + "Times New Roman", + "Verdana", + "Courier New", + "Lucida Console", + "Monaco", + "monospace", +]; + +/** Default font size list */ +export const DEFAULT_FONT_SIZE_LIST = [ + "10px", + "11px", + "12px", + "14px", + "16px", + "18px", + "20px", + "22px", + "24px", + "26px", + "28px", + "36px", + "48px", + "72px", +] as const; + +/** Default font size value */ +export const DEFAULT_FONT_SIZE_VALUE = "default"; + +/** Options for setting image size in the bubble menu */ +export enum IMAGE_SIZE { + "size-small" = 200, + "size-medium" = 500, + "size-large" = "100%", +} + +/** Options for setting video size in the bubble menu */ +export enum VIDEO_SIZE { + "size-small" = 480, + "size-medium" = 640, + "size-large" = "100%", +} + +/** Line Height List */ +export const DEFAULT_LINE_HEIGHT_LIST = [ + "100%", + "115%", + "150%", + "200%", + "250%", + "300%", +]; +export const LINE_HEIGHT_100 = 1.7; +export const DEFAULT_LINE_HEIGHT = "1"; + +/** display in menus */ +export const NODE_TYPE_MENU: any = { + image: [ + "divider", + "image-size-small", + "image-size-medium", + "image-size-large", + "divider", + "image-left", + "image-center", + "image-right", + "divider", + "image-aspect-ratio", + "remove", + ], + text: [ + "divider", + "text-bubble", + "divider", + "bold", + "italic", + "underline", + "strike", + "code", + "link", + "divider", + "color", + "highlight", + "textAlign", + ], + video: [ + "video-size-small", + "video-size-medium", + "video-size-large", + "divider", + "remove", + ], + table: ["removeTable"], +}; + +/** display in bubble text menu */ +export const BUBBLE_TEXT_LIST = [ + "bold", + "italic", + "underline", + "strike", + "code", + "link", + "divider", + "color", + "highlight", + "textAlign", +]; diff --git a/src/components/editor/editor-header.tsx b/src/components/editor/editor-header.tsx new file mode 100644 index 0000000..4abe3cb --- /dev/null +++ b/src/components/editor/editor-header.tsx @@ -0,0 +1,80 @@ +import { ArrowLeft, Eye, Save } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { Badge } from "@/components/ui/badge"; +import { Label } from "@/components/ui/label"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; + +interface EditorHeaderProps { + status: string; + category: string; + isPreview: boolean; + onBack: () => void; + onCategoryChange: (category: string) => void; + onPreview: () => void; + onSave: () => void; + onPublish: () => void; +} + +export const EditorHeader = ({ + status, + category, + isPreview, + onBack, + onCategoryChange, + onPreview, + onSave, + onPublish, +}: EditorHeaderProps) => { + return ( +
+
+
+
+ + + {status} + +
+ +
+ + + + + + + + +
+
+
+
+ ); +}; \ No newline at end of file diff --git a/src/components/editor/editor-layout.tsx b/src/components/editor/editor-layout.tsx new file mode 100644 index 0000000..4597b5b --- /dev/null +++ b/src/components/editor/editor-layout.tsx @@ -0,0 +1,35 @@ +import { TiptapEditor } from "@/components/editor/tiptap-editor"; +import { ContentPreview } from "@/features/content-management/content-preview"; + +interface EditorLayoutProps { + mode: "simple"; + isPreview: boolean; + content: string; + onContentChange: (content: string) => void; +} + +export const EditorLayout = ({ + isPreview, + content, + onContentChange +}: EditorLayoutProps) => { + // Simple Mode Layout - Content First + return ( +
+ {/* Main Content Editor */} + {isPreview ? ( +
+ +
+ ) : ( + + )} +
+ ); +}; diff --git a/src/components/editor/tiptap-editor.tsx b/src/components/editor/tiptap-editor.tsx new file mode 100644 index 0000000..ad656f2 --- /dev/null +++ b/src/components/editor/tiptap-editor.tsx @@ -0,0 +1,930 @@ +import { useEditor, EditorContent } from "@tiptap/react"; +import { BubbleMenu, FloatingMenu } from "@tiptap/react/menus"; +import { Document } from "@tiptap/extension-document"; +import { Paragraph } from "@tiptap/extension-paragraph"; +import { Text } from "@tiptap/extension-text"; +import { + Bold, + underscoreInputRegex, + underscorePasteRegex, +} from "@tiptap/extension-bold"; +import { Italic } from "@tiptap/extension-italic"; +import { Strike } from "@tiptap/extension-strike"; +import { Code } from "@tiptap/extension-code"; +import { CodeBlock } from "@tiptap/extension-code-block"; +import { Underline } from "@tiptap/extension-underline"; +import { Heading } from "@tiptap/extension-heading"; +import { Blockquote } from "@tiptap/extension-blockquote"; +import { BulletList, ListItem, OrderedList } from "@tiptap/extension-list"; +import { TaskList } from "@tiptap/extension-task-list"; +import { TaskItem } from "@tiptap/extension-task-item"; +import { Link } from "@tiptap/extension-link"; +import { Image } from "@tiptap/extension-image"; +import { Table } from "@tiptap/extension-table"; +import { TableRow } from "@tiptap/extension-table-row"; +import { TableHeader } from "@tiptap/extension-table-header"; +import { TableCell } from "@tiptap/extension-table-cell"; +import { TextAlign } from "@tiptap/extension-text-align"; +import { + TextStyle, + BackgroundColor, + Color, + FontFamily, + FontSize, + LineHeight, + TextStyleKit, +} from "@tiptap/extension-text-style"; +import { Highlight } from "@tiptap/extension-highlight"; +import { Placeholder } from "@tiptap/extension-placeholder"; +import { HardBreak } from "@tiptap/extension-hard-break"; +import Emoji, { emojis, gitHubEmojis } from "@tiptap/extension-emoji"; +import FileHandler from "@tiptap/extension-file-handler"; +import { Dropcursor } from "@tiptap/extensions"; +import { useState, useCallback } from "react"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; +import { UndoRedo } from "@tiptap/extensions"; +import { + Bold as BoldIcon, + Italic as ItalicIcon, + Strikethrough, + Code as CodeIcon, + Heading1, + Heading2, + Heading3, + List, + ListOrdered, + Quote, + Link2, + Image as ImageIcon, + Type, + Sparkles, + CheckSquare, + FileText, + Table as TableIcon, + Minus, + Bot, + PenTool, + AlignLeft, + AlignCenter, + AlignRight, + AlignJustify, + Palette, + Highlighter, + Underline as UnderlineIcon, + Undo, + Redo, + Smile, + Youtube as YoutubeIcon, +} from "lucide-react"; +import { cn } from "@/lib/utils"; +import { toast } from "sonner"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "../ui/select"; +import { Label } from "../ui/label"; + +interface TiptapEditorProps { + content: string; + onChange: (content: string) => void; + placeholder?: string; + className?: string; + mode?: "simple"; +} + +export const TiptapEditor = ({ + content, + onChange, + placeholder = "Start writing...", + className, +}: TiptapEditorProps) => { + const [linkUrl, setLinkUrl] = useState(""); + const [youtubeUrl, setYoutubeUrl] = useState(""); + const [isAiLoading, setIsAiLoading] = useState(false); + const [textColor, setTextColor] = useState("#000000"); + const [backgroundColor, setBackgroundColor] = useState("#ffff00"); + const [showLinkPopover, setShowLinkPopover] = useState(false); + const [showYoutubePopover, setShowYoutubePopover] = useState(false); + + const editor = useEditor({ + extensions: [ + Document, + Paragraph, + Text, + Bold, + Italic, + Strike, + Underline, + Code, + FontFamily, + FontSize, + LineHeight, + TextStyleKit, + UndoRedo, + Dropcursor, + CodeBlock.configure({ + HTMLAttributes: { + class: "bg-gray-100 dark:bg-gray-800 p-4 rounded-lg my-4", + }, + }), + Heading.configure({ + levels: [1, 2, 3], + }), + Blockquote.configure({ + HTMLAttributes: { + class: "border-l-4 border-gray-300 pl-4 italic my-4", + }, + }), + BulletList.configure({ + HTMLAttributes: { + class: "list-disc ml-6 my-4", + }, + }), + OrderedList.configure({ + HTMLAttributes: { + class: "list-decimal ml-6 my-4", + }, + }), + ListItem, + TaskList.configure({ + HTMLAttributes: { + class: "not-prose pl-2 my-4", + }, + }), + TaskItem.configure({ + nested: true, + HTMLAttributes: { + class: "flex items-start my-2", + }, + }), + Link.configure({ + openOnClick: false, + autolink: true, + defaultProtocol: "https", + protocols: ["http", "https"], + isAllowedUri: (url, ctx) => { + try { + // construct URL + const parsedUrl = url.includes(":") + ? new URL(url) + : new URL(`${ctx.defaultProtocol}://${url}`); + + if (!ctx.defaultValidate(parsedUrl.href)) { + return false; + } + + const disallowedProtocols = ["ftp", "file", "mailto"]; + const protocol = parsedUrl.protocol.replace(":", ""); + + if (disallowedProtocols.includes(protocol)) { + return false; + } + + const allowedProtocols = ctx.protocols.map((p) => + typeof p === "string" ? p : p.scheme + ); + + if (!allowedProtocols.includes(protocol)) { + return false; + } + + const disallowedDomains = [ + "example-phishing.com", + "malicious-site.net", + ]; + const domain = parsedUrl.hostname; + + if (disallowedDomains.includes(domain)) { + return false; + } + + return true; + } catch { + return false; + } + }, + shouldAutoLink: (url) => { + try { + const parsedUrl = url.includes(":") + ? new URL(url) + : new URL(`https://${url}`); + + const disallowedDomains = [ + "example-no-autolink.com", + "another-no-autolink.com", + ]; + const domain = parsedUrl.hostname; + + return !disallowedDomains.includes(domain); + } catch { + return false; + } + }, + }), + Image.configure({ + HTMLAttributes: { + class: "max-w-full h-auto rounded-lg my-4", + }, + }), + FileHandler.configure({ + allowedMimeTypes: [ + "image/png", + "image/jpeg", + "image/gif", + "image/webp", + ], + onDrop: (currentEditor, files, pos) => { + files.forEach((file) => { + const fileReader = new FileReader(); + fileReader.readAsDataURL(file); + fileReader.onload = () => { + currentEditor + .chain() + .insertContentAt(pos, { + type: "image", + attrs: { + src: fileReader.result, + }, + }) + .focus() + .run(); + }; + }); + }, + onPaste: (currentEditor, files, htmlContent) => { + files.forEach((file) => { + if (htmlContent) { + console.log(htmlContent); + return false; + } + const fileReader = new FileReader(); + fileReader.readAsDataURL(file); + fileReader.onload = () => { + currentEditor + .chain() + .insertContentAt(currentEditor.state.selection.anchor, { + type: "image", + attrs: { + src: fileReader.result, + }, + }) + .focus() + .run(); + }; + }); + }, + }), + Table.configure({ + resizable: true, + HTMLAttributes: { + class: + "border-collapse table-auto w-full border border-gray-300 my-4", + }, + }), + TableRow.configure({ + HTMLAttributes: { + class: "border border-gray-300", + }, + }), + TableHeader.configure({ + HTMLAttributes: { + class: "border border-gray-300 bg-gray-50 font-bold p-2", + }, + }), + TableCell.configure({ + HTMLAttributes: { + class: "border border-gray-300 p-2", + }, + }), + TextAlign.configure({ + types: ["heading", "paragraph"], + }), + TextStyle, + Color, + BackgroundColor, + Highlight.configure({ + multicolor: true, + }), + HardBreak, + Emoji.configure({ + emojis: gitHubEmojis, + enableEmoticons: true, + }), + + Placeholder.configure({ + placeholder, + showOnlyWhenEditable: true, + showOnlyCurrent: false, + }), + ], + content, + onUpdate: ({ editor }) => { + onChange(editor.getHTML()); + }, + editorProps: { + attributes: { + class: + "prose prose-sm sm:prose lg:prose-lg xl:prose-xl mx-auto focus:outline-none max-w-full min-h-[400px] p-4", + }, + }, + }); + + const enhanceWithAI = useCallback( + async (action: "improve" | "continue" | "summarize") => { + if (!editor || isAiLoading) return; + + const selectedText = editor.state.doc.textBetween( + editor.state.selection.from, + editor.state.selection.to + ); + + const contextText = selectedText || editor.getText(); + + if (!contextText.trim()) { + toast.error("Please select text or write something to enhance with AI"); + return; + } + + setIsAiLoading(true); + + try { + await new Promise((resolve) => setTimeout(resolve, 2000)); + + let enhancedText = ""; + switch (action) { + case "improve": + enhancedText = `Enhanced: ${contextText}`; + break; + case "continue": + enhancedText = `${contextText}\n\nContinued with AI-generated content that flows naturally from the previous text...`; + break; + case "summarize": + enhancedText = `Summary: This text discusses ${contextText.substring( + 0, + 50 + )}...`; + break; + } + + if (selectedText) { + editor.chain().focus().insertContent(enhancedText).run(); + } else { + editor.chain().focus().insertContent(`\n\n${enhancedText}`).run(); + } + + toast.success(`Text ${action}d with AI`); + } catch (error) { + toast.error("AI enhancement failed"); + } finally { + setIsAiLoading(false); + } + }, + [editor, isAiLoading] + ); + + const setLink = useCallback(() => { + if (!editor) return; + + const previousUrl = editor.getAttributes("link").href; + const url = linkUrl || previousUrl; + + if (url === "") { + editor.chain().focus().extendMarkRange("link").unsetLink().run(); + setLinkUrl(""); + setShowLinkPopover(false); + return; + } + + if (url) { + try { + editor + .chain() + .focus() + .extendMarkRange("link") + .setLink({ href: url }) + .run(); + setLinkUrl(""); + setShowLinkPopover(false); + toast.success("Link added successfully"); + } catch (e) { + toast.error("Failed to add link"); + } + } + }, [editor, linkUrl]); + + const addImage = useCallback(() => { + if (!editor) return; + + const url = window.prompt("Enter image URL"); + if (url) { + editor.chain().focus().setImage({ src: url }).run(); + toast.success("Image added successfully"); + } + }, [editor]); + + const insertTable = () => { + if (editor) { + editor + .chain() + .focus() + .insertTable({ rows: 3, cols: 3, withHeaderRow: true }) + .run(); + } + }; + + // const insertHorizontalRule = () => { + // if (editor) { + // editor.chain().focus().setHorizontalRule().run(); + // } + // }; + + const insertEmoji = () => { + if (editor) { + const emoji = window.prompt( + "Enter emoji shortcode (e.g., smile, fire, heart):" + ); + if (emoji) { + editor.chain().focus().setEmoji(emoji).run(); + } + } + }; + + if (!editor) { + return
Loading editor...
; + } + + return ( +
+ {/* Main Toolbar */} +
+
+ {/* AI Tools */} +
+ + + + + +
+ + {/* Undo/Redo */} +
+ + + +
+ + {/* Text Formatting */} +
+ + + + + + + +
+ + {/* Headings */} +
+ + + + + + + + + + + + + +
+ + {/* Lists */} +
+ + + + + + + + + +
+ + {/* Alignment */} +
+ + + + + + + +
+ + {/* Color and Highlight */} +
+ + + + + +
+
+ +
+ { + setTextColor(e.target.value); + editor.chain().focus().setColor(e.target.value).run(); + }} + className="w-8 h-8 border rounded cursor-pointer" + /> + +
+
+ +
+ +
+ { + setBackgroundColor(e.target.value); + editor + .chain() + .focus() + .setBackgroundColor(e.target.value) + .run(); + }} + className="w-8 h-8 border rounded cursor-pointer" + /> + +
+
+
+
+
+ + +
+ + {/* Insert Elements */} +
+ + + + + +
+ setLinkUrl(e.target.value)} + onKeyDown={(e) => e.key === "Enter" && setLink()} + /> +
+ + + +
+
+
+
+ + + + + + + + +
+
+
+ + {/* Editor Content */} +
+ +
+
+ ); +}; diff --git a/src/components/otp-step.tsx b/src/components/otp-step.tsx index 758f7ab..f9d274c 100644 --- a/src/components/otp-step.tsx +++ b/src/components/otp-step.tsx @@ -13,7 +13,7 @@ import { useState } from "react"; import { useNavigate } from "react-router"; import { toast } from "sonner"; import { useRecoilRefresher_UNSTABLE } from "recoil"; -import { admin } from "@/store/atoms/admin"; +import { admin } from "@/store/atoms/users/admin"; type OtpStepProps = { apiEndpoint: string; diff --git a/src/components/service-card.tsx b/src/components/service-card.tsx index f289803..dd85a86 100644 --- a/src/components/service-card.tsx +++ b/src/components/service-card.tsx @@ -2,6 +2,7 @@ import { ArrowRight } from "lucide-react"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils"; +import { Link } from "react-router-dom"; interface ServiceCardProps { icon: React.ComponentType<{ className?: string }>; @@ -10,6 +11,7 @@ interface ServiceCardProps { buttonText: string; buttonVariant?: "default" | "outline" | "secondary"; className?: string; + link: string; } export const ServiceCard = ({ @@ -19,6 +21,7 @@ export const ServiceCard = ({ buttonText, buttonVariant = "outline", className, + link, }: ServiceCardProps) => { return ( {description}

- diff --git a/src/components/setting-profile.tsx b/src/components/setting-profile.tsx index 5bb410f..20b3496 100644 --- a/src/components/setting-profile.tsx +++ b/src/components/setting-profile.tsx @@ -5,13 +5,13 @@ import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Button } from "@/components/ui/button"; import { useState } from "react"; -import { useAdminData } from "@/store/hooks/useAdminData"; +import { useAdminData } from "@/store/hooks/users/useAdminData"; import axios from "axios"; import { toast } from "sonner"; import { InputHandler } from "@/lib/utils"; import { Skeleton } from "@/components/ui/skeleton"; import { useRecoilRefresher_UNSTABLE } from "recoil"; -import { admin } from "@/store/atoms/admin"; +import { admin } from "@/store/atoms/users/admin"; const base_api = import.meta.env.VITE_SERVER_BASE_URL; diff --git a/src/components/tiptap-node/image-node/image-node.scss b/src/components/tiptap-node/image-node/image-node.scss new file mode 100644 index 0000000..10d4231 --- /dev/null +++ b/src/components/tiptap-node/image-node/image-node.scss @@ -0,0 +1,31 @@ +.tiptap.ProseMirror { + img { + max-width: 100%; + height: auto; + display: block; + } + + > img:not([data-type="emoji"] img) { + margin: 2rem 0; + outline: 0.125rem solid transparent; + border-radius: var(--tt-radius-xs, 0.25rem); + } + + img:not([data-type="emoji"] img).ProseMirror-selectednode { + outline-color: var(--tt-brand-color-500); + } + + // Thread image handling + .tiptap-thread:has(> img) { + margin: 2rem 0; + + img { + outline: 0.125rem solid transparent; + border-radius: var(--tt-radius-xs, 0.25rem); + } + } + + .tiptap-thread img { + margin: 0; + } +} diff --git a/src/components/ui/scroll-area.tsx b/src/components/ui/scroll-area.tsx new file mode 100644 index 0000000..9376f59 --- /dev/null +++ b/src/components/ui/scroll-area.tsx @@ -0,0 +1,56 @@ +import * as React from "react" +import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" + +import { cn } from "@/lib/utils" + +function ScrollArea({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + + {children} + + + + + ) +} + +function ScrollBar({ + className, + orientation = "vertical", + ...props +}: React.ComponentProps) { + return ( + + + + ) +} + +export { ScrollArea, ScrollBar } diff --git a/src/features/content-management/content-editor.tsx b/src/features/content-management/content-editor.tsx new file mode 100644 index 0000000..36244e6 --- /dev/null +++ b/src/features/content-management/content-editor.tsx @@ -0,0 +1,75 @@ +import { useState, useEffect } from "react"; +import { useNavigate, useSearchParams } from "react-router-dom"; +import { toast } from "sonner"; +import { EditorHeader } from "@/components/editor/editor-header"; +import { EditorLayout } from "@/components/editor/editor-layout"; + +export const ContentEditor = () => { + const navigate = useNavigate(); + const [searchParams] = useSearchParams(); + const isEditing = searchParams.get("edit") === "true"; + + // State + const [content, setContent] = useState(""); + const [category, setCategory] = useState(""); + const [status, setStatus] = useState("Draft"); + const [isPreview, setIsPreview] = useState(false); + + useEffect(() => { + if (isEditing) { + setContent("

This is sample content for editing...

"); + setCategory("Academic"); + setStatus("Published"); + } + }, [isEditing]); + + // Handlers + const handleSave = () => { + + if (!content.trim()) { + toast.error("Please add some content"); + return; + } + setStatus("Draft"); + toast.success("Draft saved successfully!"); + }; + + const handlePublish = () => { + + if (!content.trim()) { + toast.error("Please add some content"); + return; + } + if (!category) { + toast.error("Please select a category"); + return; + } + setStatus("Published"); + toast.success("Article published successfully!"); + }; + + + return ( +
+ navigate("/content-management")} + onCategoryChange={setCategory} + onPreview={() => setIsPreview(!isPreview)} + onSave={handleSave} + onPublish={handlePublish} + /> + +
+ +
+
+ ); +}; \ No newline at end of file diff --git a/src/features/content-management/content-preview.tsx b/src/features/content-management/content-preview.tsx new file mode 100644 index 0000000..69f1409 --- /dev/null +++ b/src/features/content-management/content-preview.tsx @@ -0,0 +1,16 @@ +interface ContentPreviewProps { + content: string; + className?: string; +} + +export const ContentPreview = ({ content, className = "" }: ContentPreviewProps) => { + return ( +
+
No content to preview...

", + }} + /> +
+ ); +}; diff --git a/src/features/content-management/cover-image.tsx b/src/features/content-management/cover-image.tsx new file mode 100644 index 0000000..683b907 --- /dev/null +++ b/src/features/content-management/cover-image.tsx @@ -0,0 +1,94 @@ +import { useState } from "react"; +import { ImagePlus, Upload } from "lucide-react"; +import { Button } from "@/components/ui/button"; + +interface CoverImageUploaderProps { + coverImage: string | null; + onImageUpload: (file: File, url: string) => void; + onRemoveImage: () => void; + className?: string; +} + +export const CoverImageUploader = ({ + coverImage, + onImageUpload, + onRemoveImage, + className = "", +}: CoverImageUploaderProps) => { + const [showUploadInput, setShowUploadInput] = useState(false); + + const handleFileUpload = (event: React.ChangeEvent) => { + const file = event.target.files?.[0]; + if (file) { + const url = URL.createObjectURL(file); + onImageUpload(file, url); + setShowUploadInput(false); + } + }; + + const handleCancel = () => { + setShowUploadInput(false); + onRemoveImage(); + }; + + if (coverImage) { + return ( +
+ Cover + +
+ ); + } + + if (showUploadInput) { + return ( +
+
+ + +
+
+ +
+
+ ); + } + + return ( + + ); +}; diff --git a/src/features/content-management/image-uploader.tsx b/src/features/content-management/image-uploader.tsx new file mode 100644 index 0000000..a54b5a8 --- /dev/null +++ b/src/features/content-management/image-uploader.tsx @@ -0,0 +1,136 @@ +import { useState, useRef } from "react"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Upload, Link2, X } from "lucide-react"; +import { toast } from "sonner"; + +interface ImageUploaderProps { + onImageUpload: (url: string) => void; + onClose: () => void; +} + +export const ImageUploader = ({ onImageUpload, onClose }: ImageUploaderProps) => { + const [imageUrl, setImageUrl] = useState(""); + const [isUploading, setIsUploading] = useState(false); + const fileInputRef = useRef(null); + + const handleFileUpload = async (event: React.ChangeEvent) => { + const file = event.target.files?.[0]; + if (!file) return; + + // Validate file type + if (!file.type.startsWith("image/")) { + toast.error("Please select an image file"); + return; + } + + // Validate file size (5MB limit) + if (file.size > 5 * 1024 * 1024) { + toast.error("Image size must be less than 5MB"); + return; + } + + setIsUploading(true); + try { + // Create object URL for preview (in real app, upload to server) + const url = URL.createObjectURL(file); + onImageUpload(url); + toast.success("Image uploaded successfully!"); + onClose(); + } catch (error) { + toast.error("Failed to upload image"); + } finally { + setIsUploading(false); + } + }; + + const handleUrlSubmit = () => { + if (!imageUrl.trim()) { + toast.error("Please enter an image URL"); + return; + } + + // Basic URL validation + try { + new URL(imageUrl); + onImageUpload(imageUrl); + toast.success("Image added successfully!"); + onClose(); + } catch { + toast.error("Please enter a valid URL"); + } + }; + + return ( +
+
+

Add Image

+ +
+ + {/* URL Input */} +
+ +
+ setImageUrl(e.target.value)} + onKeyDown={(e) => e.key === "Enter" && handleUrlSubmit()} + /> + +
+
+ +
+
+
+
+
+ or +
+
+ + {/* File Upload */} +
+ +
fileInputRef.current?.click()} + > + +

+ Click to upload or drag and drop +

+

+ PNG, JPG, WEBP up to 5MB +

+
+ +
+ + {isUploading && ( +
+ Uploading image... +
+ )} +
+ ); +}; diff --git a/src/features/content-management/subtitle-input.tsx b/src/features/content-management/subtitle-input.tsx new file mode 100644 index 0000000..dba0f40 --- /dev/null +++ b/src/features/content-management/subtitle-input.tsx @@ -0,0 +1,50 @@ +import { Type } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; + +interface SubtitleInputProps { + value: string; + onChange: (value: string) => void; + showInput: boolean; + onShowInput: (show: boolean) => void; + className?: string; +} + +export const SubtitleInput = ({ + value, + onChange, + showInput, + onShowInput, + className = "", +}: SubtitleInputProps) => { + const handleBlur = () => { + if (!value.trim()) { + onShowInput(false); + } + }; + + if (value || showInput) { + return ( +
+ onChange(e.target.value)} + placeholder="Add a subtitle..." + className="text-xl text-muted-foreground border-none px-0 py-1 h-auto placeholder:text-muted-foreground focus-visible:ring-0 focus-visible:ring-offset-0" + onBlur={handleBlur} + /> +
+ ); + } + + return ( + + ); +}; diff --git a/src/features/content-management/title-input.tsx b/src/features/content-management/title-input.tsx new file mode 100644 index 0000000..9759f07 --- /dev/null +++ b/src/features/content-management/title-input.tsx @@ -0,0 +1,27 @@ +import { Input } from "@/components/ui/input"; + +interface TitleInputProps { + value: string; + onChange: (value: string) => void; + placeholder?: string; + className?: string; +} + +export const TitleInput = ({ + value, + onChange, + placeholder = "Untitled", + className = "", +}: TitleInputProps) => { + return ( +
+ onChange(e.target.value)} + placeholder={placeholder} + className="text-4xl font-bold border-none px-0 py-2 h-auto text-foreground placeholder:text-muted-foreground focus-visible:ring-0 focus-visible:ring-offset-0" + style={{ fontSize: "2.5rem", lineHeight: "1.2" }} + /> +
+ ); +}; diff --git a/src/hooks/use-route-guard.ts b/src/hooks/use-route-guard.ts index b27df2f..4b580ee 100644 --- a/src/hooks/use-route-guard.ts +++ b/src/hooks/use-route-guard.ts @@ -1,5 +1,5 @@ import { useNavigate } from "react-router-dom"; -import { useAdminData } from "@/store/hooks/useAdminData"; +import { useAdminData } from "@/store/hooks/users/useAdminData"; export const useRouteGuards = () => { const { adminInfo, loading } = useAdminData(); diff --git a/src/pages/auth/sign-in.tsx b/src/pages/auth/sign-in.tsx index daa87c4..6f110fa 100644 --- a/src/pages/auth/sign-in.tsx +++ b/src/pages/auth/sign-in.tsx @@ -13,7 +13,7 @@ import { Link } from "react-router-dom"; import { toast } from "sonner"; import { useNavigate } from "react-router"; import { useRecoilRefresher_UNSTABLE } from "recoil"; -import { admin } from "@/store/atoms/admin"; +import { admin } from "@/store/atoms/users/admin"; interface UserData { email?: string; diff --git a/src/pages/dashboard/academic.tsx b/src/pages/dashboard/academic.tsx index ac17962..d53c221 100644 --- a/src/pages/dashboard/academic.tsx +++ b/src/pages/dashboard/academic.tsx @@ -5,83 +5,45 @@ import ErrorBoundary from "@/components/error-boundary"; import AcademicProgramsTab from "@/features/academic/programs"; import AcademicDepartmentTab from "@/features/academic/departments"; import AcademicSemesterTab from "@/features/academic/semester"; +import DasshboardStatusCard from "@/components/dashboard-status-card"; +import DashboardBanner from "@/components/dashboard-banner"; const Academic = () => { return (
{/* Header */} -
-
-
-

- Academic Management -

-

- Manage courses, programs, departments, and academic structure -

-
-
-
+ {/* Stats Cards */} -
- - -
-
-
-
-
-

4

-

Active Courses

-
-
-
-
- - -
-
-
-
-
-

3

-

- Academic Programs -

-
-
-
-
- - -
-
-
-
-
-

5

-

Departments

-
-
-
-
- - -
-
-
-
-
-

summer-25

-

- Current Semester -

-
-
-
-
+
+ + + + + + + + +
{/* Academic Management Tabs */} diff --git a/src/pages/dashboard/announcement.tsx b/src/pages/dashboard/announcement.tsx index cb08b7b..0ab030e 100644 --- a/src/pages/dashboard/announcement.tsx +++ b/src/pages/dashboard/announcement.tsx @@ -1,82 +1,58 @@ import { Eye } from "lucide-react"; -import { Card, CardContent } from "@/components/ui/card"; import AnnouncementData from "../../features/announcement"; import CreateAnnouncement from "@/features/announcement/create-announcement"; +import DashboardBanner from "@/components/dashboard-banner"; +import ErrorBoundary from "@/components/error-boundary"; +import DasshboardStatusCard from "@/components/dashboard-status-card"; const Announcement = () => { return (
{/* Header */} -
-
-
-

- Announcements -

-

- Create and manage university announcements -

-
- -
-
+ + } + /> {/* Stats Cards */} -
- - -
-
-
-
-
-

4

-

- Total Announcements -

-
-
-
-
- - -
-
- -
-
-

3365

-

Total views

-
-
-
-
- - -
-
-
-
-
-

5

-

Published

-
-
-
-
- - -
-
-
-
-
-

2

-

High Priority

-
-
-
-
+
+ + + + + + } + ststasDescription="Total views" + iconColor="bg-green-100" + /> + + + + + + + +
{/* Announcements List */} diff --git a/src/pages/dashboard/content-editor.tsx b/src/pages/dashboard/content-editor.tsx deleted file mode 100644 index 173734a..0000000 --- a/src/pages/dashboard/content-editor.tsx +++ /dev/null @@ -1,3 +0,0 @@ -export const AdminContentEditorPage = () => { - return
hi
; -}; diff --git a/src/pages/dashboard/dashboard.tsx b/src/pages/dashboard/dashboard.tsx index 23dfa64..fb774f8 100644 --- a/src/pages/dashboard/dashboard.tsx +++ b/src/pages/dashboard/dashboard.tsx @@ -1,25 +1,12 @@ -import { - Users, - FileText, - GraduationCap, - BarChart3, - Shield, - Settings, -} from "lucide-react"; +import { Users, FileText, GraduationCap, Settings } from "lucide-react"; import { ServiceCard } from "@/components/service-card"; import { Help } from "@/components/help"; import { TodaysHighlights } from "@/components/todays-highlights"; import { SystemOverview } from "@/components/system-overview"; import ErrorBoundary from "@/components/error-boundary"; import DashboardWelcome from "@/components/dashboard-welcome"; +import type { AdminService } from "@/types"; -interface AdminService { - icon: React.ComponentType<{ className?: string }>; - title: string; - description: string; - buttonText: string; - buttonVariant?: "default" | "outline" | "secondary"; -} const adminServiceCards: AdminService[] = [ { @@ -28,6 +15,7 @@ const adminServiceCards: AdminService[] = [ description: "Manage students and faculty", buttonText: "Manage Users", buttonVariant: "outline", + url: "/users", }, { icon: FileText, @@ -35,6 +23,7 @@ const adminServiceCards: AdminService[] = [ description: "Create and manage content", buttonText: "Manage Content", buttonVariant: "outline", + url: "/content-management", }, { icon: GraduationCap, @@ -42,20 +31,7 @@ const adminServiceCards: AdminService[] = [ description: "Courses and schedules", buttonText: "Manage Academic", buttonVariant: "outline", - }, - { - icon: BarChart3, - title: "Analytics", - description: "Reports and insights", - buttonText: "View Analytics", - buttonVariant: "outline", - }, - { - icon: Shield, - title: "Security", - description: "System security and access", - buttonText: "Security Settings", - buttonVariant: "outline", + url: "/academic", }, { icon: Settings, @@ -63,6 +39,7 @@ const adminServiceCards: AdminService[] = [ description: "System configuration", buttonText: "Configure", buttonVariant: "outline", + url: "/settings", }, ]; @@ -84,6 +61,7 @@ export const AdminDashboard = () => { title={service.title} description={service.description} buttonText={service.buttonText} + link={service.url} buttonVariant={service.buttonVariant} /> ))} diff --git a/src/pages/dashboard/events.tsx b/src/pages/dashboard/events.tsx index 9407083..d176c37 100644 --- a/src/pages/dashboard/events.tsx +++ b/src/pages/dashboard/events.tsx @@ -1,85 +1,54 @@ -import { Calendar, Clock } from "lucide-react"; -import { Card, CardContent } from "@/components/ui/card"; import EventsData from "@/features/events"; import CreateEvents from "@/features/events/create-events"; +import DashboardBanner from "@/components/dashboard-banner"; +import ErrorBoundary from "@/components/error-boundary"; +import DasshboardStatusCard from "@/components/dashboard-status-card"; const Events = () => { return (
{/* Header */} -
-
-
-

- Event Management -

-

- Create and manage university events -

-
- -
-
+ } + /> {/* Stats Cards */} -
- - -
-
- -
-
-

4

-

Total Events

-
-
-
-
- - -
-
-
-
-
-

3

-

- Total Registrations -

-
-
-
-
- - -
-
- -
-
-

5

-

Upcoming

-
-
-
-
- - -
-
-
-
-
-

2

-

- Active Registrations -

-
-
-
-
+
+ + + + + + + + + + + +
{/* Events List */} diff --git a/src/pages/dashboard/users.tsx b/src/pages/dashboard/users.tsx index 52778d2..406412b 100644 --- a/src/pages/dashboard/users.tsx +++ b/src/pages/dashboard/users.tsx @@ -5,6 +5,9 @@ import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Avatar, AvatarFallback } from "@/components/ui/avatar"; +import DashboardBanner from "@/components/dashboard-banner"; +import ErrorBoundary from "@/components/error-boundary"; +import DasshboardStatusCard from "@/components/dashboard-status-card"; interface StudentData { id: string; @@ -53,77 +56,51 @@ const Users = () => { return (
{/* Header */} -
-
-
-

- User Management -

-

- Manage students, faculty, and staff accounts -

-
+ Add new user -
-
+ } + /> {/* Stats Cards */} -
- - -
-
-
-
-
-

2031

-

Total Students

-
-
-
-
- - -
-
-
-
-
-

503

-

Faculty Members

-
-
-
-
- - -
-
-
-
-
-

40

-

Staff Members

-
-
-
-
- - -
-
-
-
-
-

5

-

Inactive Users

-
-
-
-
+
+ + + + + + + + + + + +
{/* User Management Tabs */} diff --git a/src/routes/index.tsx b/src/routes/index.tsx index bb0052f..15d1845 100644 --- a/src/routes/index.tsx +++ b/src/routes/index.tsx @@ -18,7 +18,7 @@ import NotFound from "@/pages/not-found"; import { Routes, Route } from "react-router-dom"; import { DashboardProtectedRoute } from "@/components/route-protection/dashboard-protected-route"; import { AuthProtectedRoute } from "@/components/route-protection/auth-protected-route"; -import { AdminContentEditorPage } from "@/pages/dashboard/content-editor"; +import { ContentEditor } from "@/features/content-management/content-editor"; const Paths = () => { return ( @@ -62,7 +62,7 @@ const Paths = () => { } /> } /> } /> - } /> + } /> {/* Not Found */} diff --git a/src/store/atoms/admin.ts b/src/store/atoms/users/admin.ts similarity index 63% rename from src/store/atoms/admin.ts rename to src/store/atoms/users/admin.ts index 2c1577a..02f1900 100644 --- a/src/store/atoms/admin.ts +++ b/src/store/atoms/users/admin.ts @@ -1,5 +1,5 @@ import { atom } from "recoil"; -import { adminSelector } from "../selectors/admin"; +import { adminSelector } from "@/store/selectors/users/admin"; export const admin = atom({ key: "AdminAtom", diff --git a/src/store/hooks/useAdminData.ts b/src/store/hooks/users/useAdminData.ts similarity index 89% rename from src/store/hooks/useAdminData.ts rename to src/store/hooks/users/useAdminData.ts index 6cc1c14..9755b97 100644 --- a/src/store/hooks/useAdminData.ts +++ b/src/store/hooks/users/useAdminData.ts @@ -1,5 +1,5 @@ import { useRecoilStateLoadable } from "recoil"; -import { admin } from "../atoms/admin"; +import { admin } from "@/store/atoms/users/admin"; export const useAdminData = () => { const [adminData] = useRecoilStateLoadable(admin); diff --git a/src/store/selectors/admin.ts b/src/store/selectors/users/admin.ts similarity index 100% rename from src/store/selectors/admin.ts rename to src/store/selectors/users/admin.ts diff --git a/src/styles/_keyframe-animations.scss b/src/styles/_keyframe-animations.scss new file mode 100644 index 0000000..dd98b7c --- /dev/null +++ b/src/styles/_keyframe-animations.scss @@ -0,0 +1,91 @@ +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes fadeOut { + from { + opacity: 1; + } + to { + opacity: 0; + } +} + +@keyframes zoomIn { + from { + transform: scale(0.95); + } + to { + transform: scale(1); + } +} + +@keyframes zoomOut { + from { + transform: scale(1); + } + to { + transform: scale(0.95); + } +} + +@keyframes zoom { + 0% { + opacity: 0; + transform: scale(0.95); + } + 100% { + opacity: 1; + transform: scale(1); + } +} + +@keyframes slideFromTop { + from { + transform: translateY(-0.5rem); + } + to { + transform: translateY(0); + } +} + +@keyframes slideFromRight { + from { + transform: translateX(0.5rem); + } + to { + transform: translateX(0); + } +} + +@keyframes slideFromLeft { + from { + transform: translateX(-0.5rem); + } + to { + transform: translateX(0); + } +} + +@keyframes slideFromBottom { + from { + transform: translateY(0.5rem); + } + to { + transform: translateY(0); + } +} + +@keyframes spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} diff --git a/src/styles/_variables.scss b/src/styles/_variables.scss new file mode 100644 index 0000000..113a16b --- /dev/null +++ b/src/styles/_variables.scss @@ -0,0 +1,296 @@ +:root { + /****************** + Basics + ******************/ + + overflow-wrap: break-word; + text-size-adjust: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + + /****************** + Colors variables + ******************/ + + /* Gray alpha (light mode) */ + --tt-gray-light-a-50: rgba(56, 56, 56, 0.04); + --tt-gray-light-a-100: rgba(15, 22, 36, 0.05); + --tt-gray-light-a-200: rgba(37, 39, 45, 0.1); + --tt-gray-light-a-300: rgba(47, 50, 55, 0.2); + --tt-gray-light-a-400: rgba(40, 44, 51, 0.42); + --tt-gray-light-a-500: rgba(52, 55, 60, 0.64); + --tt-gray-light-a-600: rgba(36, 39, 46, 0.78); + --tt-gray-light-a-700: rgba(35, 37, 42, 0.87); + --tt-gray-light-a-800: rgba(30, 32, 36, 0.95); + --tt-gray-light-a-900: rgba(29, 30, 32, 0.98); + + /* Gray (light mode) */ + --tt-gray-light-50: rgba(250, 250, 250, 1); + --tt-gray-light-100: rgba(244, 244, 245, 1); + --tt-gray-light-200: rgba(234, 234, 235, 1); + --tt-gray-light-300: rgba(213, 214, 215, 1); + --tt-gray-light-400: rgba(166, 167, 171, 1); + --tt-gray-light-500: rgba(125, 127, 130, 1); + --tt-gray-light-600: rgba(83, 86, 90, 1); + --tt-gray-light-700: rgba(64, 65, 69, 1); + --tt-gray-light-800: rgba(44, 45, 48, 1); + --tt-gray-light-900: rgba(34, 35, 37, 1); + + /* Gray alpha (dark mode) */ + --tt-gray-dark-a-50: rgba(232, 232, 253, 0.05); + --tt-gray-dark-a-100: rgba(231, 231, 243, 0.07); + --tt-gray-dark-a-200: rgba(238, 238, 246, 0.11); + --tt-gray-dark-a-300: rgba(239, 239, 245, 0.22); + --tt-gray-dark-a-400: rgba(244, 244, 255, 0.37); + --tt-gray-dark-a-500: rgba(236, 238, 253, 0.5); + --tt-gray-dark-a-600: rgba(247, 247, 253, 0.64); + --tt-gray-dark-a-700: rgba(251, 251, 254, 0.75); + --tt-gray-dark-a-800: rgba(253, 253, 253, 0.88); + --tt-gray-dark-a-900: rgba(255, 255, 255, 0.96); + + /* Gray (dark mode) */ + --tt-gray-dark-50: rgba(25, 25, 26, 1); + --tt-gray-dark-100: rgba(32, 32, 34, 1); + --tt-gray-dark-200: rgba(45, 45, 47, 1); + --tt-gray-dark-300: rgba(70, 70, 73, 1); + --tt-gray-dark-400: rgba(99, 99, 105, 1); + --tt-gray-dark-500: rgba(124, 124, 131, 1); + --tt-gray-dark-600: rgba(163, 163, 168, 1); + --tt-gray-dark-700: rgba(192, 192, 195, 1); + --tt-gray-dark-800: rgba(224, 224, 225, 1); + --tt-gray-dark-900: rgba(245, 245, 245, 1); + + /* Brand colors */ + --tt-brand-color-50: rgba(239, 238, 255, 1); + --tt-brand-color-100: rgba(222, 219, 255, 1); + --tt-brand-color-200: rgba(195, 189, 255, 1); + --tt-brand-color-300: rgba(157, 138, 255, 1); + --tt-brand-color-400: rgba(122, 82, 255, 1); + --tt-brand-color-500: rgba(98, 41, 255, 1); + --tt-brand-color-600: rgba(84, 0, 229, 1); + --tt-brand-color-700: rgba(75, 0, 204, 1); + --tt-brand-color-800: rgba(56, 0, 153, 1); + --tt-brand-color-900: rgba(43, 25, 102, 1); + --tt-brand-color-950: hsla(257, 100%, 9%, 1); + + /* Green */ + --tt-color-green-inc-5: hsla(129, 100%, 97%, 1); + --tt-color-green-inc-4: hsla(129, 100%, 92%, 1); + --tt-color-green-inc-3: hsla(131, 100%, 86%, 1); + --tt-color-green-inc-2: hsla(133, 98%, 78%, 1); + --tt-color-green-inc-1: hsla(137, 99%, 70%, 1); + --tt-color-green-base: hsla(147, 99%, 50%, 1); + --tt-color-green-dec-1: hsla(147, 97%, 41%, 1); + --tt-color-green-dec-2: hsla(146, 98%, 32%, 1); + --tt-color-green-dec-3: hsla(146, 100%, 24%, 1); + --tt-color-green-dec-4: hsla(144, 100%, 16%, 1); + --tt-color-green-dec-5: hsla(140, 100%, 9%, 1); + + /* Yellow */ + --tt-color-yellow-inc-5: hsla(50, 100%, 97%, 1); + --tt-color-yellow-inc-4: hsla(50, 100%, 91%, 1); + --tt-color-yellow-inc-3: hsla(50, 100%, 84%, 1); + --tt-color-yellow-inc-2: hsla(50, 100%, 77%, 1); + --tt-color-yellow-inc-1: hsla(50, 100%, 68%, 1); + --tt-color-yellow-base: hsla(52, 100%, 50%, 1); + --tt-color-yellow-dec-1: hsla(52, 100%, 41%, 1); + --tt-color-yellow-dec-2: hsla(52, 100%, 32%, 1); + --tt-color-yellow-dec-3: hsla(52, 100%, 24%, 1); + --tt-color-yellow-dec-4: hsla(51, 100%, 16%, 1); + --tt-color-yellow-dec-5: hsla(50, 100%, 9%, 1); + + /* Red */ + --tt-color-red-inc-5: hsla(11, 100%, 96%, 1); + --tt-color-red-inc-4: hsla(11, 100%, 88%, 1); + --tt-color-red-inc-3: hsla(10, 100%, 80%, 1); + --tt-color-red-inc-2: hsla(9, 100%, 73%, 1); + --tt-color-red-inc-1: hsla(7, 100%, 64%, 1); + --tt-color-red-base: hsla(7, 100%, 54%, 1); + --tt-color-red-dec-1: hsla(7, 100%, 41%, 1); + --tt-color-red-dec-2: hsla(5, 100%, 32%, 1); + --tt-color-red-dec-3: hsla(4, 100%, 24%, 1); + --tt-color-red-dec-4: hsla(3, 100%, 16%, 1); + --tt-color-red-dec-5: hsla(1, 100%, 9%, 1); + + /* Basic colors */ + --white: rgba(255, 255, 255, 1); + --black: rgba(14, 14, 17, 1); + --transparent: rgba(255, 255, 255, 0); + + /****************** + Shadow variables + ******************/ + + /* Shadows Light */ + --tt-shadow-elevated-md: + 0px 16px 48px 0px rgba(17, 24, 39, 0.04), + 0px 12px 24px 0px rgba(17, 24, 39, 0.04), + 0px 6px 8px 0px rgba(17, 24, 39, 0.02), + 0px 2px 3px 0px rgba(17, 24, 39, 0.02); + + /************************************************** + Radius variables + **************************************************/ + + --tt-radius-xxs: 0.125rem; /* 2px */ + --tt-radius-xs: 0.25rem; /* 4px */ + --tt-radius-sm: 0.375rem; /* 6px */ + --tt-radius-md: 0.5rem; /* 8px */ + --tt-radius-lg: 0.75rem; /* 12px */ + --tt-radius-xl: 1rem; /* 16px */ + + /************************************************** + Transition variables + **************************************************/ + + --tt-transition-duration-short: 0.1s; + --tt-transition-duration-default: 0.2s; + --tt-transition-duration-long: 0.64s; + --tt-transition-easing-default: cubic-bezier(0.46, 0.03, 0.52, 0.96); + --tt-transition-easing-cubic: cubic-bezier(0.65, 0.05, 0.36, 1); + --tt-transition-easing-quart: cubic-bezier(0.77, 0, 0.18, 1); + --tt-transition-easing-circ: cubic-bezier(0.79, 0.14, 0.15, 0.86); + --tt-transition-easing-back: cubic-bezier(0.68, -0.55, 0.27, 1.55); + + /****************** + Contrast variables + ******************/ + + --tt-accent-contrast: 8%; + --tt-destructive-contrast: 8%; + --tt-foreground-contrast: 8%; + + &, + *, + ::before, + ::after { + box-sizing: border-box; + transition: none var(--tt-transition-duration-default) + var(--tt-transition-easing-default); + } +} + +:root { + /************************************************** + Global colors + **************************************************/ + + /* Global colors - Light mode */ + --tt-bg-color: var(--white); + --tt-border-color: var(--tt-gray-light-a-200); + --tt-border-color-tint: var(--tt-gray-light-a-100); + --tt-sidebar-bg-color: var(--tt-gray-light-100); + --tt-scrollbar-color: var(--tt-gray-light-a-200); + --tt-cursor-color: var(--tt-brand-color-500); + --tt-selection-color: rgba(157, 138, 255, 0.2); + --tt-card-bg-color: var(--white); + --tt-card-border-color: var(--tt-gray-light-a-100); +} + +/* Global colors - Dark mode */ +.dark { + --tt-bg-color: var(--black); + --tt-border-color: var(--tt-gray-dark-a-200); + --tt-border-color-tint: var(--tt-gray-dark-a-100); + --tt-sidebar-bg-color: var(--tt-gray-dark-100); + --tt-scrollbar-color: var(--tt-gray-dark-a-200); + --tt-cursor-color: var(--tt-brand-color-400); + --tt-selection-color: rgba(122, 82, 255, 0.2); + --tt-card-bg-color: var(--tt-gray-dark-50); + --tt-card-border-color: var(--tt-gray-dark-a-50); + + --tt-shadow-elevated-md: + 0px 16px 48px 0px rgba(0, 0, 0, 0.5), 0px 12px 24px 0px rgba(0, 0, 0, 0.24), + 0px 6px 8px 0px rgba(0, 0, 0, 0.22), 0px 2px 3px 0px rgba(0, 0, 0, 0.12); +} + +/* Text colors */ +:root { + --tt-color-text-gray: hsl(45, 2%, 46%); + --tt-color-text-brown: hsl(19, 31%, 47%); + --tt-color-text-orange: hsl(30, 89%, 45%); + --tt-color-text-yellow: hsl(38, 62%, 49%); + --tt-color-text-green: hsl(148, 32%, 39%); + --tt-color-text-blue: hsl(202, 54%, 43%); + --tt-color-text-purple: hsl(274, 32%, 54%); + --tt-color-text-pink: hsl(328, 49%, 53%); + --tt-color-text-red: hsl(2, 62%, 55%); + + --tt-color-text-gray-contrast: hsla(39, 26%, 26%, 0.15); + --tt-color-text-brown-contrast: hsla(18, 43%, 69%, 0.35); + --tt-color-text-orange-contrast: hsla(24, 73%, 55%, 0.27); + --tt-color-text-yellow-contrast: hsla(44, 82%, 59%, 0.39); + --tt-color-text-green-contrast: hsla(126, 29%, 60%, 0.27); + --tt-color-text-blue-contrast: hsla(202, 54%, 59%, 0.27); + --tt-color-text-purple-contrast: hsla(274, 37%, 64%, 0.27); + --tt-color-text-pink-contrast: hsla(331, 60%, 71%, 0.27); + --tt-color-text-red-contrast: hsla(8, 79%, 79%, 0.4); +} + +.dark { + --tt-color-text-gray: hsl(0, 0%, 61%); + --tt-color-text-brown: hsl(18, 35%, 58%); + --tt-color-text-orange: hsl(25, 53%, 53%); + --tt-color-text-yellow: hsl(36, 54%, 55%); + --tt-color-text-green: hsl(145, 32%, 47%); + --tt-color-text-blue: hsl(202, 64%, 52%); + --tt-color-text-purple: hsl(270, 55%, 62%); + --tt-color-text-pink: hsl(329, 57%, 58%); + --tt-color-text-red: hsl(1, 69%, 60%); + + --tt-color-text-gray-contrast: hsla(0, 0%, 100%, 0.09); + --tt-color-text-brown-contrast: hsla(17, 45%, 50%, 0.25); + --tt-color-text-orange-contrast: hsla(27, 82%, 53%, 0.2); + --tt-color-text-yellow-contrast: hsla(35, 49%, 47%, 0.2); + --tt-color-text-green-contrast: hsla(151, 55%, 39%, 0.2); + --tt-color-text-blue-contrast: hsla(202, 54%, 43%, 0.2); + --tt-color-text-purple-contrast: hsla(271, 56%, 60%, 0.18); + --tt-color-text-pink-contrast: hsla(331, 67%, 58%, 0.22); + --tt-color-text-red-contrast: hsla(0, 67%, 60%, 0.25); +} + +/* Highlight colors */ +:root { + --tt-color-highlight-yellow: #fef9c3; + --tt-color-highlight-green: #dcfce7; + --tt-color-highlight-blue: #e0f2fe; + --tt-color-highlight-purple: #f3e8ff; + --tt-color-highlight-red: #ffe4e6; + --tt-color-highlight-gray: rgb(248, 248, 247); + --tt-color-highlight-brown: rgb(244, 238, 238); + --tt-color-highlight-orange: rgb(251, 236, 221); + --tt-color-highlight-pink: rgb(252, 241, 246); + + --tt-color-highlight-yellow-contrast: #fbe604; + --tt-color-highlight-green-contrast: #c7fad8; + --tt-color-highlight-blue-contrast: #ceeafd; + --tt-color-highlight-purple-contrast: #e4ccff; + --tt-color-highlight-red-contrast: #ffccd0; + --tt-color-highlight-gray-contrast: rgba(84, 72, 49, 0.15); + --tt-color-highlight-brown-contrast: rgba(210, 162, 141, 0.35); + --tt-color-highlight-orange-contrast: rgba(224, 124, 57, 0.27); + --tt-color-highlight-pink-contrast: rgba(225, 136, 179, 0.27); +} + +.dark { + --tt-color-highlight-yellow: #6b6524; + --tt-color-highlight-green: #509568; + --tt-color-highlight-blue: #6e92aa; + --tt-color-highlight-purple: #583e74; + --tt-color-highlight-red: #743e42; + --tt-color-highlight-gray: rgb(47, 47, 47); + --tt-color-highlight-brown: rgb(74, 50, 40); + --tt-color-highlight-orange: rgb(92, 59, 35); + --tt-color-highlight-pink: rgb(78, 44, 60); + + --tt-color-highlight-yellow-contrast: #58531e; + --tt-color-highlight-green-contrast: #47855d; + --tt-color-highlight-blue-contrast: #5e86a1; + --tt-color-highlight-purple-contrast: #4c3564; + --tt-color-highlight-red-contrast: #643539; + --tt-color-highlight-gray-contrast: rgba(255, 255, 255, 0.094); + --tt-color-highlight-brown-contrast: rgba(184, 101, 69, 0.25); + --tt-color-highlight-orange-contrast: rgba(233, 126, 37, 0.2); + --tt-color-highlight-pink-contrast: rgba(220, 76, 145, 0.22); +} diff --git a/src/types/index.d.ts b/src/types/index.d.ts index e7722f2..48abdd2 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -1,3 +1,35 @@ +// dashboard + +import type React from "react"; + +export interface AdminService { + icon: React.ComponentType<{ className?: string }>; + title: string; + description: string; + buttonText: string; + buttonVariant?: "default" | "outline" | "secondary"; + url: string; +} + +// status cards +export interface DashboardStatusCard { + classname?: string; + statusIcon?: React.ReactElement; + statusNumber: number; + iconColor?: string; + ststasDescription: string; +} + +// dashboard banner + +export interface DashboardBannerData { + bannerTitle: string; + bannerDescription: string; + bannerIcon?: React.ReactElement; + bannerButton?: React.ReactElement; + date?: string; +} + // academic export interface CourseData { @@ -115,3 +147,29 @@ export interface EditorData { onBack: () => void; initialData?: EditorData; } + +// editor types +/** + * Interface for RichTextEditor component props + */ +export interface RichTextEditorProps { + content: string; + extensions: AnyExtension[]; + output: "html" | "json" | "text"; + modelValue?: string | object; + dark?: boolean; + dense?: boolean; + disabled?: boolean; + label?: string; + hideToolbar?: boolean; + disableBubble?: boolean; + hideBubble?: boolean; + removeDefaultWrapper?: boolean; + maxWidth?: string | number; + minHeight?: string | number; + maxHeight?: string | number; + contentClass?: string | string[] | Record; + onChangeContent?: (val: any) => void; + bubbleMenu?: BubbleMenuProps; + useEditorOptions?: UseEditorOptions; +}