Skip to content

Commit

Permalink
⬆️ Upgrade to React19 & Next15 (#64)
Browse files Browse the repository at this point in the history
* ⬆️ React19 & Next15

* 🔄 rename next.config.js to next.config.ts and update type annotations in layout.tsx

* 🔄 refactor generateStaticParams to use for loops instead of flatMap for better readability

* 🔄 update type of children prop in CategoryLayout from ReactNode to JSX.Element and improve variable naming for clarity

* 🔄 refactor generateMetadata and CategoryLayout to improve type definitions and simplify props structure

* 🔄 update children prop type in layout components from JSX.Element to ReactNode for improved flexibility

* remove unnecessary pnpm overrides from package.json

* 🔄 update TypeScript version and refactor layout component props for improved type safety and clarity

* 🔄 update dependencies: upgrade @testing-library/react, react, @types/react, @number-flow/react, embla-carousel-react, motion, qrcode.react, and react-dom for improved compatibility and features

* 🔄 update trend prop in GithubStarsButton from false to 0 for improved functionality
  • Loading branch information
damien-schneider authored Dec 13, 2024
1 parent 433ca8d commit 1237a34
Show file tree
Hide file tree
Showing 29 changed files with 1,827 additions and 1,668 deletions.
2 changes: 1 addition & 1 deletion apps/website/next-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
4 changes: 2 additions & 2 deletions apps/website/next.config.js → apps/website/next.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
// experimental: {
// serverComponentsExternalPackages: ["shiki", "vscode-oniguruma"],
// },
Expand Down
48 changes: 24 additions & 24 deletions apps/website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,56 +7,56 @@
},
"dependencies": {
"@cuicui/ui": "workspace:*",
"@radix-ui/react-dialog": "1.1.1",
"@radix-ui/react-dropdown-menu": "2.1.1",
"@radix-ui/react-scroll-area": "1.1.0",
"@radix-ui/react-select": "2.0.0",
"@radix-ui/react-slot": "1.1.0",
"@radix-ui/react-tabs": "1.1.0",
"@radix-ui/react-dialog": "1.1.3",
"@radix-ui/react-dropdown-menu": "2.1.3",
"@radix-ui/react-scroll-area": "1.2.2",
"@radix-ui/react-select": "2.1.3",
"@radix-ui/react-slot": "1.1.1",
"@radix-ui/react-tabs": "1.1.2",
"class-variance-authority": "0.7.0",
"clsx": "^2.x",
"cmdk": "^1.x",
"date-fns": "^3.x",
"clsx": "^2.1.1",
"cmdk": "^1.0.4",
"date-fns": "^3.6.0",
"dom-to-image-more": "3.4.5",
"fs-extra": "11.2.0",
"lucide-react": "^0.x",
"motion": "^11.x",
"next": "14.2.3",
"lucide-react": "^0.468.0",
"motion": "^11.14.1",
"next": "15.1.0",
"next-mdx-remote": "5.0.0",
"next-themes": "0.3.0",
"next-themes": "0.4.4",
"path": "0.12.7",
"react": "18.2.0",
"react-dom": "18.2.0",
"react": "19.0.0",
"react-dom": "19.0.0",
"react-frame-component": "5.2.7",
"react-resizable-panels": "2.0.22",
"react-resizable-panels": "2.1.7",
"sharp": "0.33.4",
"sonner": "^1.x",
"sonner": "^1.7.1",
"tailwind-merge": "2.3.0",
"vite-tsconfig-paths": "5.0.1",
"zustand": "^4.x"
"zustand": "^4.5.5"
},
"description": "An open-source all-in-one library for building an advanced SaaS application, a personal website, or anything else with micro-interactions, advanced user experiences, and a focus on performance and code quality.",
"devDependencies": {
"@tailwindcss/forms": "0.5.7",
"@tailwindcss/typography": "0.5.12",
"@testing-library/dom": "10.4.0",
"@testing-library/react": "16.0.0",
"@testing-library/react": "16.1.0",
"@types/dom-to-image": "2.6.7",
"@types/node": "20.12.7",
"@types/react": "18.2.79",
"@types/react-dom": "18.2.25",
"@types/react": "19.0.1",
"@types/react-dom": "19.0.2",
"@vitejs/plugin-react": "4.3.1",
"autoprefixer": "10.4.19",
"eslint": "9.0.0",
"eslint-config-next": "14.2.2",
"eslint-config-next": "15.1.0",
"jsdom": "25.0.0",
"lint-staged": "15.2.2",
"postcss": "8.4.38",
"shiki": "1.18.0",
"tailwindcss": "3.4.3",
"tailwindcss-animate": "1.0.7",
"turbo": "2.2.0",
"typescript": "5.4.5",
"typescript": "5.7.2",
"vitest": "2.0.5"
},
"git": {
Expand All @@ -79,7 +79,7 @@
"scripts": {
"build": "pnpm pre-build && next build",
"pre-build": "pnpm scripts/generate-latest-changelog-date.mjs && pnpm scripts/generate-package-list-check.mjs",
"dev": "next dev --turbo",
"dev": "next dev --turbopack",
"start": "next start",
"generate-package-list-check": "node scripts/generate-package-list-check.js",
"lint": "next lint",
Expand Down
50 changes: 30 additions & 20 deletions apps/website/src/app/(site)/[section]/[category]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { Metadata } from "next";
import Head from "next/head";
import Link from "next/link";
import { notFound } from "next/navigation";
Expand All @@ -7,22 +6,22 @@ import { NEXT_PUBLIC_SITE_URL } from "#/src/lib/site.const";
import { findCategoryBySlug } from "#/src/utils/section-category-components-utils/find-category-by-slug";
import { findSectionBySlug } from "#/src/utils/section-category-components-utils/find-section-by-slug";

type Props = {
children: ReactNode;
params: {
export async function generateMetadata({
params,
}: {
params: Promise<{
section: string;
category: string;
};
};

export function generateMetadata({ params }: Props): Metadata {
const section = findSectionBySlug(params.section);
}>;
}) {
const { section: sectionParam, category: categoryParam } = await params;
const section = findSectionBySlug(sectionParam);
if (!section) {
return {};
}

if (section.type === "page") {
const page = section.pageList.find((page) => page.slug === params.category);
const page = section.pageList.find((page) => page.slug === categoryParam);
if (page) {
return {
title: page.name,
Expand All @@ -40,7 +39,7 @@ export function generateMetadata({ params }: Props): Metadata {
return {};
}

const category = findCategoryBySlug(section, params.category);
const category = findCategoryBySlug(section, categoryParam);
if (category) {
return {
title: `${category.name} React Components`,
Expand All @@ -58,29 +57,40 @@ export function generateMetadata({ params }: Props): Metadata {
return {};
}

export default function CategoryLayout({ children, params }: Props) {
const section = findSectionBySlug(params.section);
if (!section) {
export default async function CategoryLayout({
params,
children,
}: {
children: ReactNode;
params: Promise<{
section: string;
category: string;
}>;
}) {
const { section: sectionParam, category: categoryParam } = await params;

const sectionInList = findSectionBySlug(sectionParam);
if (!sectionInList) {
return notFound();
}
const category = findCategoryBySlug(section, params.category);
if (!category) {
const categoryInList = findCategoryBySlug(sectionInList, categoryParam);
if (!categoryInList) {
return notFound();
}
return (
<>
<div>
<Head>
<Link
href={`${NEXT_PUBLIC_SITE_URL}/${section.slug}/${category.slug}`}
href={`${NEXT_PUBLIC_SITE_URL}/${sectionInList.slug}/${categoryInList.slug}`}
key="canonical"
rel="canonical"
/>
<meta content="all" name="robots" />
</Head>
<h1 className="bg-gradient-to-b from-black to-black/40 dark:from-white dark:to-white/10 bg-clip-text font-medium text-transparent text-3xl sm:text-5xl inline tracking-tighter">
{category.name} components
{categoryInList.name} components
</h1>
{children}
</>
</div>
);
}
67 changes: 39 additions & 28 deletions apps/website/src/app/(site)/[section]/[category]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,74 +8,85 @@ import type {
} from "@cuicui/ui/lib/types/component";
import { findCategoryBySlug } from "#/src/utils/section-category-components-utils/find-category-by-slug";
type Props = {
params: {
params: Promise<{
section: string;
category: string;
};
}>;
};

export async function generateStaticParams() {
const params = sectionList.flatMap((section) => {
export function generateStaticParams() {
const paramsArray = [];
for (const section of sectionList) {
if (
section.type === "multiple-component" ||
section.type === "single-component"
) {
return section.categoriesList.map((category) => ({
section: section.slug,
category: category.slug,
}));
for (const category of section.categoriesList) {
paramsArray.push({
section: section.slug,
category: category.slug,
});
}
}
if (section.type === "page") {
return section.pageList.map((page) => ({
section: section.slug,
category: page.slug,
}));
for (const page of section.pageList) {
paramsArray.push({
section: section.slug,
category: page.slug,
});
}
}
});
}

// Return the generated params array
return params;
return paramsArray;
}

export default async function Page({ params }: Readonly<Props>) {
const section = sectionList.find(
(section) => section.slug === params.section,
export default async function Page({ params }: Props) {
const { section: sectionParam, category: categoryParam } = await params;
const sectionInList = sectionList.find(
(section) => section.slug === sectionParam,
);
if (!section) {
if (!sectionInList) {
return notFound();
}
if (section?.type === "page") {
const page = section.pageList.find((page) => page.slug === params.category);
if (sectionInList?.type === "page") {
const page = sectionInList.pageList.find(
(page) => page.slug === categoryParam,
);
if (!page) {
return notFound();
}
return page.component;
}

if (section?.type === "single-component") {
if (sectionInList?.type === "single-component") {
const category = findCategoryBySlug(
section,
params.category,
sectionInList,
categoryParam,
) as SingleComponentCategoryType | null;
if (!category) {
return notFound();
}
return (
<SingleComponentCategory sectionSlug={section.slug} category={category} />
<SingleComponentCategory
sectionSlug={sectionInList.slug}
category={category}
/>
);
}

if (section?.type === "multiple-component") {
if (sectionInList?.type === "multiple-component") {
const category = findCategoryBySlug(
section,
params.category,
sectionInList,
categoryParam,
) as CategoryType | null;
if (!category) {
return notFound();
}
return (
<MultipleComponentCategory
sectionSlug={section.slug}
sectionSlug={sectionInList.slug}
category={category}
/>
);
Expand Down
29 changes: 16 additions & 13 deletions apps/website/src/app/(site)/[section]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,38 @@ import { findSectionBySlug } from "#/src/utils/section-category-components-utils

type Props = {
children: ReactNode;
params: {
params: Promise<{
section: string;
category: string;
};
}>;
};

export function generateMetadata({ params }: Props): Metadata {
const section = findSectionBySlug(params.section);
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { section: sectionParam } = await params;
const sectionInList = findSectionBySlug(sectionParam);

// optionally access and extend (rather than replace) parent metadata

if (!section) {
if (!sectionInList) {
return {};
}
return {
title: section.name,
description: section.description,
title: sectionInList.name,
description: sectionInList.description,
openGraph: {
title: section.name,
description: section.description,
title: sectionInList.name,
description: sectionInList.description,
},
alternates: {
canonical: `${NEXT_PUBLIC_SITE_URL}/${section.slug}`,
canonical: `${NEXT_PUBLIC_SITE_URL}/${sectionInList.slug}`,
},
};
}

export default function SectionLayout({ children, params }: Props) {
const section = findSectionBySlug(params.section);
export default async function SectionLayout({ params, children }: Props) {
const { section: sectionParam } = await params;

const section = findSectionBySlug(sectionParam);

if (!section) {
return notFound();
}
Expand Down
Loading

0 comments on commit 1237a34

Please sign in to comment.