chore: upgrade React and Next.js to latest versions

Update project dependencies to React 19 and Next.js 15, including TypeScript type adjustments and async parameter handling across multiple components
This commit is contained in:
swve 2025-03-11 12:50:56 +01:00
parent 81c4190b00
commit 63be0f0ff3
28 changed files with 2781 additions and 2878 deletions

View file

@ -3,12 +3,12 @@ import LoginClient from './login'
import { Metadata } from 'next'
type MetadataProps = {
params: { orgslug: string }
searchParams: { [key: string]: string | string[] | undefined }
params: Promise<{ orgslug: string }>
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
export async function generateMetadata(params: MetadataProps): Promise<Metadata> {
const orgslug = params.searchParams.orgslug
const orgslug = (await params.searchParams).orgslug
//const orgslug = params.orgslug
// Get Org context information
@ -23,7 +23,7 @@ export async function generateMetadata(params: MetadataProps): Promise<Metadata>
}
const Login = async (params: MetadataProps) => {
const orgslug = params.searchParams.orgslug
const orgslug = (await params.searchParams).orgslug
const org = await getOrganizationContextInfo(orgslug, {
revalidate: 0,
tags: ['organizations'],

View file

@ -5,14 +5,14 @@ import { Suspense } from 'react'
import PageLoading from '@components/Objects/Loaders/PageLoading'
type MetadataProps = {
params: { orgslug: string; courseid: string }
searchParams: { [key: string]: string | string[] | undefined }
params: Promise<{ orgslug: string; courseid: string }>
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
export async function generateMetadata(
params
: MetadataProps): Promise<Metadata> {
const orgslug = params.searchParams.orgslug
const orgslug = (await params.searchParams).orgslug
// Get Org context information
const org = await getOrganizationContextInfo(orgslug, {
revalidate: 0,
@ -25,7 +25,7 @@ export async function generateMetadata(
}
const SignUp = async (params: any) => {
const orgslug = params.searchParams.orgslug
const orgslug = (await params.searchParams).orgslug
const org = await getOrganizationContextInfo(orgslug, {
revalidate: 0,
tags: ['organizations'],

View file

@ -1,3 +1,4 @@
import { default as React } from 'react'
import dynamic from 'next/dynamic'
import { getCourseMetadata } from '@services/courses/courses'
@ -8,17 +9,16 @@ import EditorOptionsProvider from '@components/Contexts/Editor/EditorContext'
import AIEditorProvider from '@components/Contexts/AI/AIEditorContext'
import { nextAuthOptions } from 'app/auth/options'
import { getServerSession } from 'next-auth'
const EditorWrapper = dynamic(() => import('@components/Objects/Editor/EditorWrapper'), { ssr: false })
import EditorWrapper from '@components/Objects/Editor/EditorWrapper'
type MetadataProps = {
params: { orgslug: string; courseid: string; activityid: string }
searchParams: { [key: string]: string | string[] | undefined }
params: Promise<{ orgslug: string; courseid: string; activityid: string }>
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
export async function generateMetadata({
params,
}: MetadataProps): Promise<Metadata> {
export async function generateMetadata(props: MetadataProps): Promise<Metadata> {
const params = await props.params;
const session = await getServerSession(nextAuthOptions)
const access_token = session?.tokens?.access_token
// Get Org context information
@ -37,8 +37,8 @@ export async function generateMetadata({
const EditActivity = async (params: any) => {
const session = await getServerSession(nextAuthOptions)
const access_token = session?.tokens?.access_token
const activityuuid = params.params.activityuuid
const courseid = params.params.courseid
const activityuuid = (await params.params).activityuuid
const courseid = (await params.params).courseid
const courseInfo = await getCourseMetadata(
courseid,
{ revalidate: 0, tags: ['courses'] },

View file

@ -31,7 +31,6 @@ export default function RootLayout({
animate="enter" // Animated state to variants.enter
exit="exit" // Exit state (used later) to variants.exit
transition={{ type: 'linear' }} // Set the transition to linear
className=""
>
{children}
</motion.main>

View file

@ -9,13 +9,12 @@ import { getServerSession } from 'next-auth'
import Link from 'next/link'
type MetadataProps = {
params: { orgslug: string; courseid: string; collectionid: string }
searchParams: { [key: string]: string | string[] | undefined }
params: Promise<{ orgslug: string; courseid: string; collectionid: string }>
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
export async function generateMetadata({
params,
}: MetadataProps): Promise<Metadata> {
export async function generateMetadata(props: MetadataProps): Promise<Metadata> {
const params = await props.params;
const session = await getServerSession(nextAuthOptions)
const access_token = session?.tokens?.access_token
@ -55,13 +54,13 @@ export async function generateMetadata({
const CollectionPage = async (params: any) => {
const session = await getServerSession(nextAuthOptions)
const access_token = session?.tokens?.access_token
const org = await getOrganizationContextInfo(params.params.orgslug, {
const org = await getOrganizationContextInfo((await params.params).orgslug, {
revalidate: 1800,
tags: ['organizations'],
})
const orgslug = params.params.orgslug
const orgslug = (await params.params).orgslug
const col = await getCollectionById(
params.params.collectionid,
(await params.params).collectionid,
access_token ? access_token : null,
{ revalidate: 0, tags: ['collections'] }
)

View file

@ -14,13 +14,12 @@ import { getOrgThumbnailMediaDirectory } from '@services/media/media'
import ContentPlaceHolderIfUserIsNotAdmin from '@components/Objects/ContentPlaceHolder'
type MetadataProps = {
params: { orgslug: string; courseid: string }
searchParams: { [key: string]: string | string[] | undefined }
params: Promise<{ orgslug: string; courseid: string }>
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
export async function generateMetadata({
params,
}: MetadataProps): Promise<Metadata> {
export async function generateMetadata(props: MetadataProps): Promise<Metadata> {
const params = await props.params;
// Get Org context information
const org = await getOrganizationContextInfo(params.orgslug, {
revalidate: 0,
@ -60,7 +59,7 @@ export async function generateMetadata({
const CollectionsPage = async (params: any) => {
const session = await getServerSession(nextAuthOptions)
const access_token = session?.tokens?.access_token
const orgslug = params.params.orgslug
const orgslug = (await params.params).orgslug
const org = await getOrganizationContextInfo(orgslug, {
revalidate: 1800,
tags: ['organizations'],

View file

@ -461,7 +461,7 @@ function ActivityChapterDropdown(props: {
<div className="relative" ref={dropdownRef}>
<button
onClick={toggleDropdown}
className="flex items-center justify-center bg-white nice-shadow p-2.5 rounded-full"
className="flex items-center justify-center bg-white nice-shadow p-2.5 rounded-full cursor-pointer"
aria-label="View all activities"
title="View all activities"
>
@ -469,12 +469,12 @@ function ActivityChapterDropdown(props: {
</button>
{isOpen && (
<div className={`absolute z-50 mt-2 ${isMobile ? 'left-0 w-[90vw] sm:w-80' : 'left-0 w-80'} max-h-[70vh] overflow-y-auto bg-white rounded-lg shadow-xl border border-gray-200 py-2 animate-in fade-in duration-200`}>
<div className={`absolute z-50 mt-2 ${isMobile ? 'left-0 w-[90vw] sm:w-80' : 'left-0 w-80'} max-h-[70vh] cursor-pointer overflow-y-auto bg-white rounded-lg shadow-xl border border-gray-200 py-2 animate-in fade-in duration-200`}>
<div className="px-4 py-2 border-b border-gray-100 flex justify-between items-center">
<h3 className="font-bold text-gray-800">Course Content</h3>
<button
onClick={() => setIsOpen(false)}
className="text-gray-500 hover:text-gray-700 p-1 rounded-full hover:bg-gray-100"
className="text-gray-500 hover:text-gray-700 p-1 rounded-full hover:bg-gray-100 cursor-pointer"
>
<X size={18} />
</button>
@ -630,7 +630,7 @@ function ActivityNavigation(props: {
<>
<button
onClick={() => navigateToActivity(prevActivity)}
className={`flex items-center space-x-1.5 p-2 rounded-md transition-all duration-200 ${
className={`flex items-center space-x-1.5 p-2 rounded-md transition-all duration-200 cursor-pointer ${
prevActivity
? 'text-gray-700'
: 'opacity-50 text-gray-400 cursor-not-allowed'
@ -649,7 +649,7 @@ function ActivityNavigation(props: {
<button
onClick={() => navigateToActivity(nextActivity)}
className={`flex items-center space-x-1.5 p-2 rounded-md transition-all duration-200 ${
className={`flex items-center space-x-1.5 p-2 rounded-md transition-all duration-200 cursor-pointer ${
nextActivity
? 'text-gray-700'
: 'opacity-50 text-gray-400 cursor-not-allowed'
@ -672,7 +672,7 @@ function ActivityNavigation(props: {
<div className="justify-self-start">
<button
onClick={() => navigateToActivity(prevActivity)}
className={`flex items-center space-x-1.5 px-3.5 py-2 rounded-md transition-all duration-200 ${
className={`flex items-center space-x-1.5 px-3.5 py-2 rounded-md transition-all duration-200 cursor-pointer ${
prevActivity
? 'bg-white nice-shadow text-gray-700'
: 'bg-gray-100 text-gray-400 cursor-not-allowed'
@ -697,7 +697,7 @@ function ActivityNavigation(props: {
<div className="justify-self-end">
<button
onClick={() => navigateToActivity(nextActivity)}
className={`flex items-center space-x-1.5 px-3.5 py-2 rounded-md transition-all duration-200 ${
className={`flex items-center space-x-1.5 px-3.5 py-2 rounded-md transition-all duration-200 cursor-pointer ${
nextActivity
? 'bg-white nice-shadow text-gray-700'
: 'bg-gray-100 text-gray-400 cursor-not-allowed'

View file

@ -7,13 +7,12 @@ import { getServerSession } from 'next-auth'
import { nextAuthOptions } from 'app/auth/options'
type MetadataProps = {
params: { orgslug: string; courseuuid: string; activityid: string }
searchParams: { [key: string]: string | string[] | undefined }
params: Promise<{ orgslug: string; courseuuid: string; activityid: string }>
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
export async function generateMetadata({
params,
}: MetadataProps): Promise<Metadata> {
export async function generateMetadata(props: MetadataProps): Promise<Metadata> {
const params = await props.params;
const session = await getServerSession(nextAuthOptions)
const access_token = session?.tokens?.access_token
@ -60,9 +59,9 @@ export async function generateMetadata({
const ActivityPage = async (params: any) => {
const session = await getServerSession(nextAuthOptions)
const access_token = session?.tokens?.access_token
const activityid = params.params.activityid
const courseuuid = params.params.courseuuid
const orgslug = params.params.orgslug
const activityid = (await params.params).activityid
const courseuuid = (await params.params).courseuuid
const orgslug = (await params.params).orgslug
const course_meta = await getCourseMetadata(
courseuuid,

View file

@ -8,13 +8,12 @@ import { nextAuthOptions } from 'app/auth/options'
import { getServerSession } from 'next-auth'
type MetadataProps = {
params: { orgslug: string; courseuuid: string }
searchParams: { [key: string]: string | string[] | undefined }
params: Promise<{ orgslug: string; courseuuid: string }>
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
export async function generateMetadata({
params,
}: MetadataProps): Promise<Metadata> {
export async function generateMetadata(props: MetadataProps): Promise<Metadata> {
const params = await props.params;
const session = await getServerSession(nextAuthOptions)
const access_token = session?.tokens?.access_token
@ -67,8 +66,8 @@ export async function generateMetadata({
}
const CoursePage = async (params: any) => {
const courseuuid = params.params.courseuuid
const orgslug = params.params.orgslug
const courseuuid = (await params.params).courseuuid
const orgslug = (await params.params).orgslug
const session = await getServerSession(nextAuthOptions)
const access_token = session?.tokens?.access_token
const course_meta = await getCourseMetadata(

View file

@ -8,13 +8,12 @@ import { getOrgCourses } from '@services/courses/courses'
import { getOrgThumbnailMediaDirectory } from '@services/media/media'
type MetadataProps = {
params: { orgslug: string }
searchParams: { [key: string]: string | string[] | undefined }
params: Promise<{ orgslug: string }>
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
export async function generateMetadata({
params,
}: MetadataProps): Promise<Metadata> {
export async function generateMetadata(props: MetadataProps): Promise<Metadata> {
const params = await props.params;
// Get Org context information
const org = await getOrganizationContextInfo(params.orgslug, {
revalidate: 0,
@ -53,7 +52,7 @@ export async function generateMetadata({
}
const CoursesPage = async (params: any) => {
const orgslug = params.params.orgslug
const orgslug = (await params.params).orgslug
const org = await getOrganizationContextInfo(orgslug, {
revalidate: 1800,
tags: ['organizations'],

View file

@ -1,16 +1,22 @@
'use client'
'use client';
import { use } from "react";
import '@styles/globals.css'
import { SessionProvider } from 'next-auth/react'
import Watermark from '@components/Objects/Watermark'
import { OrgMenu } from '@components/Objects/Menus/OrgMenu'
export default function RootLayout({
children,
params,
}: {
export default function RootLayout(
props: {
children: React.ReactNode
params: any
}) {
params: Promise<any>
}
) {
const params = use(props.params);
const {
children
} = props;
return (
<>
<SessionProvider>

View file

@ -20,13 +20,12 @@ import LandingClassic from '@components/Landings/LandingClassic'
import LandingCustom from '@components/Landings/LandingCustom'
type MetadataProps = {
params: { orgslug: string }
searchParams: { [key: string]: string | string[] | undefined }
params: Promise<{ orgslug: string }>
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
export async function generateMetadata({
params,
}: MetadataProps): Promise<Metadata> {
export async function generateMetadata(props: MetadataProps): Promise<Metadata> {
const params = await props.params;
// Get Org context information
const org = await getOrganizationContextInfo(params.orgslug, {
revalidate: 0,
@ -64,7 +63,7 @@ export async function generateMetadata({
}
const OrgHomePage = async (params: any) => {
const orgslug = params.params.orgslug
const orgslug = (await params.params).orgslug
const session = await getServerSession(nextAuthOptions)
const access_token = session?.tokens?.access_token
const courses = await getOrgCourses(

View file

@ -6,13 +6,12 @@ import { getServerSession } from 'next-auth'
import { nextAuthOptions } from 'app/auth/options'
type MetadataProps = {
params: { orgslug: string }
searchParams: { [key: string]: string | string[] | undefined }
params: Promise<{ orgslug: string }>
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
export async function generateMetadata({
params,
}: MetadataProps): Promise<Metadata> {
export async function generateMetadata(props: MetadataProps): Promise<Metadata> {
const params = await props.params;
const session = await getServerSession(nextAuthOptions)
const access_token = session?.tokens?.access_token
// Get Org context information
@ -28,7 +27,7 @@ export async function generateMetadata({
}
const TrailPage = async (params: any) => {
let orgslug = params.params.orgslug
let orgslug = (await params.params).orgslug
return (
<div>

View file

@ -1,6 +1,6 @@
'use client'
import { getUriWithOrg } from '@services/config/config'
import React from 'react'
import React, { use } from 'react';
import { CourseProvider } from '../../../../../../../../components/Contexts/CourseContext'
import Link from 'next/link'
import { CourseOverviewTop } from '@components/Dashboard/Misc/CourseOverviewTop'
@ -16,7 +16,8 @@ export type CourseOverviewParams = {
subpage: string
}
function CourseOverviewPage({ params }: { params: CourseOverviewParams }) {
function CourseOverviewPage(props: { params: Promise<CourseOverviewParams> }) {
const params = use(props.params);
function getEntireCourseUUID(courseuuid: string) {
// add course_ to uuid
return `course_${courseuuid}`

View file

@ -7,13 +7,12 @@ import { getServerSession } from 'next-auth'
import { getOrgCourses } from '@services/courses/courses'
type MetadataProps = {
params: { orgslug: string }
searchParams: { [key: string]: string | string[] | undefined }
params: Promise<{ orgslug: string }>
searchParams: Promise<{ [key: string]: string | string[] | undefined }>
}
export async function generateMetadata({
params,
}: MetadataProps): Promise<Metadata> {
export async function generateMetadata(props: MetadataProps): Promise<Metadata> {
const params = await props.params;
// Get Org context information
const org = await getOrganizationContextInfo(params.orgslug, {
revalidate: 1800,
@ -44,7 +43,7 @@ export async function generateMetadata({
}
async function CoursesPage(params: any) {
const orgslug = params.params.orgslug
const orgslug = (await params.params).orgslug
const org = await getOrganizationContextInfo(orgslug, {
revalidate: 1800,
tags: ['organizations'],

View file

@ -6,13 +6,18 @@ export const metadata: Metadata = {
title: 'LearnHouse Dashboard',
}
function DashboardLayout({
children,
params,
}: {
async function DashboardLayout(
props: {
children: React.ReactNode
params: any
}) {
params: Promise<any>
}
) {
const params = await props.params;
const {
children
} = props;
return (
<>
<ClientAdminLayout

View file

@ -3,7 +3,7 @@ import BreadCrumbs from '@components/Dashboard/Misc/BreadCrumbs'
import { getUriWithOrg } from '@services/config/config'
import { ImageIcon, Info, LockIcon, SearchIcon, TextIcon, LucideIcon, Share2Icon, LayoutDashboardIcon } from 'lucide-react'
import Link from 'next/link'
import React, { useEffect } from 'react'
import React, { useEffect, use } from 'react';
import { motion } from 'framer-motion'
import OrgEditGeneral from '@components/Dashboard/Pages/Org/OrgEditGeneral/OrgEditGeneral'
import OrgEditImages from '@components/Dashboard/Pages/Org/OrgEditImages/OrgEditImages'
@ -49,7 +49,8 @@ function TabLink({ tab, isActive, orgslug }: {
)
}
function OrgPage({ params }: { params: OrgParams }) {
function OrgPage(props: { params: Promise<OrgParams> }) {
const params = use(props.params);
const [H1Label, setH1Label] = React.useState('')
const [H2Label, setH2Label] = React.useState('')

View file

@ -1,5 +1,5 @@
'use client'
import React from 'react'
import React, { use } from 'react';
import { motion } from 'framer-motion'
import BreadCrumbs from '@components/Dashboard/Misc/BreadCrumbs'
import Link from 'next/link'
@ -17,7 +17,8 @@ export type PaymentsParams = {
orgslug: string
}
function PaymentsPage({ params }: { params: PaymentsParams }) {
function PaymentsPage(props: { params: Promise<PaymentsParams> }) {
const params = use(props.params);
const session = useLHSession() as any
const org = useOrg() as any
const subpage = params.subpage || 'customers'

View file

@ -1,5 +1,5 @@
'use client'
import React, { useEffect } from 'react'
import React, { useEffect, use } from 'react';
import { motion } from 'framer-motion'
import UserEditGeneral from '@components/Dashboard/Pages/UserAccount/UserEditGeneral/UserEditGeneral'
import UserEditPassword from '@components/Dashboard/Pages/UserAccount/UserEditPassword/UserEditPassword'
@ -14,7 +14,8 @@ export type SettingsParams = {
orgslug: string
}
function SettingsPage({ params }: { params: SettingsParams }) {
function SettingsPage(props: { params: Promise<SettingsParams> }) {
const params = use(props.params);
const session = useLHSession() as any
useEffect(() => {}, [session])

View file

@ -1,5 +1,5 @@
'use client'
import React, { useEffect } from 'react'
import React, { useEffect, use } from 'react';
import { motion } from 'framer-motion'
import Link from 'next/link'
import { useMediaQuery } from 'usehooks-ts'
@ -18,7 +18,8 @@ export type SettingsParams = {
orgslug: string
}
function UsersSettingsPage({ params }: { params: SettingsParams }) {
function UsersSettingsPage(props: { params: Promise<SettingsParams> }) {
const params = use(props.params);
const session = useLHSession() as any
const org = useOrg() as any
const [H1Label, setH1Label] = React.useState('')

View file

@ -1,17 +1,23 @@
'use client'
'use client';
import { use } from "react";
import { OrgProvider } from '@components/Contexts/OrgContext'
import NextTopLoader from 'nextjs-toploader';
import Toast from '@components/Objects/StyledElements/Toast/Toast'
import '@styles/globals.css'
import Onboarding from '@components/Objects/Onboarding/Onboarding';
export default function RootLayout({
children,
params,
}: {
export default function RootLayout(
props: {
children: React.ReactNode
params: any
}) {
params: Promise<any>
}
) {
const params = use(props.params);
const {
children
} = props;
return (
<div>
<OrgProvider orgslug={params.orgslug}>

View file

@ -70,7 +70,7 @@ function UserEditGeneral() {
toast.success('Profile Updated Successfully', { duration: 4000 })
// Show message about logging in with new email
toast((t) => (
toast((t: any) => (
<div className="flex items-center gap-2">
<span>Please login again with your new email: {newEmail}</span>
</div>

View file

@ -33,7 +33,7 @@ function UserEditPassword() {
// Show success message and notify about logout
toast.success('Password updated successfully', { duration: 4000 })
toast((t) => (
toast((t: any) => (
<div className="flex items-center gap-2">
<span>Please login again with your new password</span>
</div>

View file

@ -1,5 +1,5 @@
'use client'
import { default as React } from 'react'
import { default as React, type JSX } from 'react';
import Editor from './Editor'
import { updateActivity } from '@services/courses/activities'
import { toast } from 'react-hot-toast'
@ -7,8 +7,6 @@ import Toast from '@components/Objects/StyledElements/Toast/Toast'
import { OrgProvider } from '@components/Contexts/OrgContext'
import { useLHSession } from '@components/Contexts/LHSessionContext'
interface EditorWrapperProps {
content: string
activity: any

View file

@ -4,7 +4,7 @@ import { styled } from '@stitches/react'
import { blackA } from '@radix-ui/colors'
import { Info } from 'lucide-react'
const FormLayout = (props: any, onSubmit: any) => (
const FormLayout: React.FC<{ children: React.ReactNode; onSubmit: (e: any) => void }> = (props) => (
<FormRoot className="h-fit" onSubmit={props.onSubmit}>
{props.children}
</FormRoot>

View file

@ -23,7 +23,7 @@ export default function StyledComponentsRegistry({
return (
<StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
{children as React.ReactChild}
{children as React.ReactElement<any> | number | string}
</StyleSheetManager>
)
);
}

View file

@ -3,7 +3,7 @@
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev --turbo",
"dev": "next dev --turbopack",
"dev-https": "next dev --experimental-https -p 443",
"build": "next build",
"start": "next start",
@ -13,92 +13,99 @@
"dependencies": {
"@emoji-mart/data": "^1.2.1",
"@emoji-mart/react": "^1.1.1",
"@icons-pack/react-simple-icons": "^10.1.0",
"@icons-pack/react-simple-icons": "^10.2.0",
"@radix-ui/colors": "^0.1.9",
"@radix-ui/react-aspect-ratio": "^1.1.0",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@radix-ui/react-aspect-ratio": "^1.1.2",
"@radix-ui/react-dialog": "^1.1.6",
"@radix-ui/react-dropdown-menu": "^2.1.6",
"@radix-ui/react-form": "^0.0.3",
"@radix-ui/react-icons": "^1.3.1",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-select": "^2.1.2",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-switch": "^1.1.1",
"@radix-ui/react-tabs": "^1.1.1",
"@radix-ui/react-toggle": "^1.1.0",
"@radix-ui/react-toggle-group": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.3",
"@sentry/nextjs": "^9.1.0",
"@sentry/utils": "^8.35.0",
"@radix-ui/react-icons": "^1.3.2",
"@radix-ui/react-label": "^2.1.2",
"@radix-ui/react-select": "^2.1.6",
"@radix-ui/react-slot": "^1.1.2",
"@radix-ui/react-switch": "^1.1.3",
"@radix-ui/react-tabs": "^1.1.3",
"@radix-ui/react-toggle": "^1.1.2",
"@radix-ui/react-toggle-group": "^1.1.2",
"@radix-ui/react-tooltip": "^1.1.8",
"@sentry/nextjs": "^9.5.0",
"@sentry/utils": "^8.55.0",
"@stitches/react": "^1.2.8",
"@tanstack/react-table": "^8.20.5",
"@tiptap/core": "^2.9.1",
"@tiptap/extension-code-block-lowlight": "^2.9.1",
"@tiptap/extension-table": "^2.9.1",
"@tiptap/extension-table-cell": "^2.9.1",
"@tiptap/extension-table-header": "^2.9.1",
"@tiptap/extension-table-row": "^2.9.1",
"@tiptap/extension-youtube": "^2.9.1",
"@tiptap/html": "^2.9.1",
"@tiptap/pm": "^2.9.1",
"@tiptap/react": "^2.9.1",
"@tiptap/starter-kit": "^2.9.1",
"@types/dompurify": "^3.0.5",
"@tanstack/react-table": "^8.21.2",
"@tiptap/core": "^2.11.5",
"@tiptap/extension-code-block-lowlight": "^2.11.5",
"@tiptap/extension-table": "^2.11.5",
"@tiptap/extension-table-cell": "^2.11.5",
"@tiptap/extension-table-header": "^2.11.5",
"@tiptap/extension-table-row": "^2.11.5",
"@tiptap/extension-youtube": "^2.11.5",
"@tiptap/html": "^2.11.5",
"@tiptap/pm": "^2.11.5",
"@tiptap/react": "^2.11.5",
"@tiptap/starter-kit": "^2.11.5",
"@types/dompurify": "^3.2.0",
"@types/randomcolor": "^0.5.9",
"avvvatars-react": "^0.4.2",
"class-variance-authority": "^0.7.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"currency-codes": "^2.2.0",
"dayjs": "^1.11.13",
"dompurify": "^3.2.4",
"emblor": "^1.4.7",
"formik": "^2.4.6",
"framer-motion": "^10.18.0",
"framer-motion": "^12.4.12",
"get-youtube-id": "^1.0.1",
"highlight.js": "^11.10.0",
"highlight.js": "^11.11.1",
"katex": "^0.16.21",
"lowlight": "^3.1.0",
"lowlight": "^3.3.0",
"lucide-react": "^0.453.0",
"next": "14.2.23",
"next-auth": "^4.24.10",
"next": "15.2.2",
"next-auth": "^4.24.11",
"nextjs-toploader": "^1.6.12",
"prosemirror-state": "^1.4.3",
"randomcolor": "^0.6.2",
"re-resizable": "^6.10.0",
"react": "^18.3.1",
"re-resizable": "^6.11.2",
"react": "19.0.0",
"react-beautiful-dnd": "^13.1.1",
"react-confetti": "^6.1.0",
"react-dom": "^18.3.1",
"react-hot-toast": "^2.4.1",
"react-confetti": "^6.4.0",
"react-dom": "19.0.0",
"react-hot-toast": "^2.5.2",
"react-katex": "^3.0.1",
"react-spinners": "^0.13.8",
"react-youtube": "^10.1.0",
"require-in-the-middle": "^7.5.2",
"sharp": "^0.33.5",
"styled-components": "^6.1.13",
"swr": "^2.2.5",
"tailwind-merge": "^2.5.4",
"styled-components": "^6.1.15",
"swr": "^2.3.3",
"tailwind-merge": "^2.6.0",
"tailwind-scrollbar": "^3.1.0",
"tailwindcss-animate": "^1.0.7",
"unsplash-js": "^7.0.19",
"usehooks-ts": "^3.1.0",
"usehooks-ts": "^3.1.1",
"uuid": "^9.0.1",
"yup": "^1.4.0"
"yup": "^1.6.1"
},
"devDependencies": {
"@tailwindcss/postcss": "^4.0.12",
"@types/node": "20.12.2",
"@types/react": "18.2.74",
"@types/react": "19.0.10",
"@types/react-beautiful-dnd": "^13.1.8",
"@types/react-dom": "18.2.23",
"@types/react-dom": "19.0.4",
"@types/react-katex": "^3.0.4",
"@types/react-transition-group": "^4.4.11",
"@types/react-transition-group": "^4.4.12",
"@types/styled-components": "^5.1.34",
"@types/uuid": "^9.0.8",
"eslint": "^8.57.1",
"eslint-config-next": "^14.2.16",
"eslint-config-next": "15.2.1",
"eslint-plugin-unused-imports": "^3.2.0",
"postcss": "^8.4.47",
"postcss": "^8.5.3",
"tailwindcss": "^4.0.12",
"typescript": "5.4.4"
},
"pnpm": {
"overrides": {
"@types/react": "19.0.10",
"@types/react-dom": "19.0.4"
}
}
}

5301
apps/web/pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff