diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6aa3230f..2cc55900 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -681,9 +681,6 @@ importers: '@pantheon-systems/pcc-react-sdk': specifier: workspace:* version: link:../../packages/react-sdk - '@pantheon-systems/pds-toolkit-react': - specifier: 1.0.0-dev.55 - version: 1.0.0-dev.55(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-popover': specifier: ^1.1.1 version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -705,9 +702,6 @@ importers: dotenv: specifier: ^16.4.5 version: 16.4.5 - jotai: - specifier: ^2.7.0 - version: 2.7.0(@types/react@18.3.3)(react@18.3.1) markdown-to-txt: specifier: ^2.0.1 version: 2.0.1 @@ -751,9 +745,6 @@ importers: autoprefixer: specifier: ^10.4.17 version: 10.4.17(postcss@8.4.35) - c8: - specifier: ^7.14.0 - version: 7.14.0 eslint: specifier: ^8.57.0 version: 8.57.0 @@ -805,18 +796,12 @@ importers: class-variance-authority: specifier: ^0.7.0 version: 0.7.0 - classnames: - specifier: ^2.5.1 - version: 2.5.1 clsx: specifier: ^2.1.1 version: 2.1.1 dotenv: specifier: ^16.4.5 version: 16.4.5 - jotai: - specifier: ^2.7.0 - version: 2.7.0(@types/react@18.3.3)(react@18.3.1) markdown-to-txt: specifier: ^2.0.1 version: 2.0.1 @@ -899,12 +884,12 @@ importers: '@pantheon-systems/pcc-react-sdk': specifier: workspace:* version: link:../../packages/react-sdk - '@pantheon-systems/pds-toolkit-react': - specifier: 1.0.0-dev.55 - version: 1.0.0-dev.55(prop-types@15.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-popover': specifier: ^1.1.1 version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': + specifier: ^1.1.0 + version: 1.1.0(@types/react@18.3.3)(react@18.3.1) '@tailwindcss/typography': specifier: ^0.5.10 version: 0.5.10(tailwindcss@3.4.1) @@ -917,9 +902,6 @@ importers: dotenv: specifier: ^16.4.5 version: 16.4.5 - jotai: - specifier: ^2.7.0 - version: 2.7.0(@types/react@18.3.3)(react@18.3.1) markdown-to-txt: specifier: ^2.0.1 version: 2.0.1 @@ -969,9 +951,6 @@ importers: autoprefixer: specifier: ^10.4.17 version: 10.4.17(postcss@8.4.35) - c8: - specifier: ^7.14.0 - version: 7.14.0 eslint: specifier: ^8.57.0 version: 8.57.0 @@ -10148,18 +10127,6 @@ packages: joi@17.12.2: resolution: {integrity: sha512-RonXAIzCiHLc8ss3Ibuz45u28GOsWE1UpfDXLbN/9NKbL4tCJf8TWYVKsoYuuh+sAUt7fsSNpA+r2+TBA6Wjmw==} - jotai@2.7.0: - resolution: {integrity: sha512-4qsyFKu4MprI39rj2uoItyhu24NoCHzkOV7z70PQr65SpzV6CSyhQvVIfbNlNqOIOspNMdf5OK+kTXLvqe63Jw==} - engines: {node: '>=12.20.0'} - peerDependencies: - '@types/react': '>=17.0.0' - react: '>=17.0.0' - peerDependenciesMeta: - '@types/react': - optional: true - react: - optional: true - joycon@3.1.1: resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} engines: {node: '>=10'} @@ -27488,11 +27455,6 @@ snapshots: '@sideway/formula': 3.0.1 '@sideway/pinpoint': 2.0.0 - jotai@2.7.0(@types/react@18.3.3)(react@18.3.1): - optionalDependencies: - '@types/react': 18.3.3 - react: 18.3.1 - joycon@3.1.1: {} js-tokens@4.0.0: {} diff --git a/starters/nextjs-starter-approuter-ts/README.md b/starters/nextjs-starter-approuter-ts/README.md index ad66e4b2..312fbde9 100644 --- a/starters/nextjs-starter-approuter-ts/README.md +++ b/starters/nextjs-starter-approuter-ts/README.md @@ -1,4 +1,4 @@ -# Pantheon Decoupled Kit Next Pantheon Content Cloud Starter +# Pantheon Content Cloud Next.js Starter ## Getting Started diff --git a/starters/nextjs-starter-approuter-ts/__tests__/hasConfiguredPantheonClient.test.ts b/starters/nextjs-starter-approuter-ts/__tests__/hasConfiguredPantheonClient.test.ts index 418f06d1..ca9904ed 100644 --- a/starters/nextjs-starter-approuter-ts/__tests__/hasConfiguredPantheonClient.test.ts +++ b/starters/nextjs-starter-approuter-ts/__tests__/hasConfiguredPantheonClient.test.ts @@ -2,7 +2,7 @@ import { pantheonAPIOptions } from "../app/api/pantheoncloud/[...command]/api-op describe("hasConfiguredPantheonClient", () => { it("Pantheon API options have been filled out", () => { - expect(pantheonAPIOptions.smartComponentMap.LEAD_CAPTURE).toBeDefined(); + expect(pantheonAPIOptions.smartComponentMap.MEDIA_PREVIEW).toBeDefined(); }); it("Resolve document by article id", () => { diff --git a/starters/nextjs-starter-approuter-ts/app/articles/page.tsx b/starters/nextjs-starter-approuter-ts/app/articles/page.tsx index a0507ee9..e5805320 100644 --- a/starters/nextjs-starter-approuter-ts/app/articles/page.tsx +++ b/starters/nextjs-starter-approuter-ts/app/articles/page.tsx @@ -38,7 +38,7 @@ export default async function ArticlesListTemplate() { ); } -export async function generateMetadata() { +export function generateMetadata() { return { title: "Decoupled Next PCC Demo", description: "Generated by create-pantheon-decoupled-kit.", diff --git a/starters/nextjs-starter-approuter-ts/app/examples/page.tsx b/starters/nextjs-starter-approuter-ts/app/examples/page.tsx index 315386aa..5297e740 100644 --- a/starters/nextjs-starter-approuter-ts/app/examples/page.tsx +++ b/starters/nextjs-starter-approuter-ts/app/examples/page.tsx @@ -7,12 +7,14 @@ export default function ExamplesPageTemplate() {
-
+

- This page outlines a growing list of common use cases that can be - used as a reference when building using this starter kit. If you - don't need them for your site, feel free to delete the - `pages/examples` directory in your codebase. + + This page outlines a growing list of common use cases that can be + used as a reference when building using this starter kit. If you + don't need them for your site, feel free to delete the + `pages/examples` directory in your codebase. +

  • @@ -37,7 +39,7 @@ export default function ExamplesPageTemplate() { ); } -export async function generateMetadata({}) { +export function generateMetadata() { return { title: "Examples", description: "Examples", diff --git a/starters/nextjs-starter-approuter-ts/app/examples/ssg-isr/[uri]/page.tsx b/starters/nextjs-starter-approuter-ts/app/examples/ssg-isr/[uri]/page.tsx index 5b64f78d..939ebcc6 100644 --- a/starters/nextjs-starter-approuter-ts/app/examples/ssg-isr/[uri]/page.tsx +++ b/starters/nextjs-starter-approuter-ts/app/examples/ssg-isr/[uri]/page.tsx @@ -1,9 +1,7 @@ import { PCCConvenienceFunctions } from "@pantheon-systems/pcc-react-sdk/server"; import { Metadata } from "next"; -import { unstable_cache } from "next/cache"; import { notFound } from "next/navigation"; import { StaticArticleView } from "../../../../components/article-view"; -import { ArticleGrid } from "../../../../components/grid"; import Layout from "../../../../components/layout"; import { getSeoMetadata } from "../../../../lib/utils"; diff --git a/starters/nextjs-starter-approuter-ts/app/examples/ssg-isr/page.tsx b/starters/nextjs-starter-approuter-ts/app/examples/ssg-isr/page.tsx index 310fb6a1..143f7ac8 100644 --- a/starters/nextjs-starter-approuter-ts/app/examples/ssg-isr/page.tsx +++ b/starters/nextjs-starter-approuter-ts/app/examples/ssg-isr/page.tsx @@ -16,6 +16,7 @@ async function fetchNextPages(cursor: string) { pageSize: PAGE_SIZE, cursor, }); + return { data, newCursor, @@ -40,7 +41,7 @@ export default async function SSGISRExampleTemplate() { cursor={cursor} fetcher={fetchNextPages} additionalHeader={ -
    +

    By default, this starter kit is optimized for SSR and Edge @@ -56,7 +57,7 @@ export default async function SSGISRExampleTemplate() { ); } -export async function generateStaticParams() { +export function generateStaticParams() { // This function is empty because we're not generating any dynamic routes // It's included to demonstrate where you would put the logic for generating // static params if needed in the future diff --git a/starters/nextjs-starter-approuter-ts/app/global-error.tsx b/starters/nextjs-starter-approuter-ts/app/global-error.tsx index bd9980e9..b086ee8b 100644 --- a/starters/nextjs-starter-approuter-ts/app/global-error.tsx +++ b/starters/nextjs-starter-approuter-ts/app/global-error.tsx @@ -1,24 +1,26 @@ -'use client' +"use client"; import Image from "next/image"; import Link from "next/link"; import Layout from "../components/layout"; import { Button } from "../components/ui/button"; - export default function GlobalError() { return ( -

    -
    +
    +
    -

    500

    -

    Internal server error

    -

    - An error occurred while processing your request. Try again or return to homepage. +

    500

    +

    + Internal server error +

    +

    + An error occurred while processing your request. Try again or + return to homepage.

    -
    +
    @@ -29,12 +31,12 @@ export default function GlobalError() {
    -
    +
    Pantheon Logo
    @@ -42,9 +44,10 @@ export default function GlobalError() { ); } -export async function generateMetadata() { +export function generateMetadata() { return { title: "Internal server error", - description: "An error occurred while processing your request. Try again or return to homepage.", + description: + "An error occurred while processing your request. Try again or return to homepage.", }; } diff --git a/starters/nextjs-starter-approuter-ts/app/not-found.tsx b/starters/nextjs-starter-approuter-ts/app/not-found.tsx index be6e98a7..167062fa 100644 --- a/starters/nextjs-starter-approuter-ts/app/not-found.tsx +++ b/starters/nextjs-starter-approuter-ts/app/not-found.tsx @@ -6,17 +6,19 @@ import { Button } from "../components/ui/button"; export default function NotFound() { return ( -
    -
    +
    +
    -

    404

    -

    Page not found

    -

    +

    404

    +

    + Page not found +

    +

    The page might not exist or is temporarily unavailable. Check the URL or return to homepage.

    -
    +
    @@ -27,12 +29,12 @@ export default function NotFound() {
    -
    +
    Pantheon Logo
    @@ -40,9 +42,10 @@ export default function NotFound() { ); } -export async function generateMetadata() { +export function generateMetadata() { return { title: "Page not found", - description: "The page might not exist or is temporarily unavailable. Check the URL or return to homepage.", + description: + "The page might not exist or is temporarily unavailable. Check the URL or return to homepage.", }; } diff --git a/starters/nextjs-starter-approuter-ts/app/page.tsx b/starters/nextjs-starter-approuter-ts/app/page.tsx index f0352e98..9e0b5229 100644 --- a/starters/nextjs-starter-approuter-ts/app/page.tsx +++ b/starters/nextjs-starter-approuter-ts/app/page.tsx @@ -57,7 +57,7 @@ export default async function Home() { ); } -export async function generateMetadata({}) { +export function generateMetadata() { return { title: "Decoupled Next PCC Demo", description: "Generated by create-pantheon-decoupled-kit.", diff --git a/starters/nextjs-starter-approuter-ts/app/tags/page.tsx b/starters/nextjs-starter-approuter-ts/app/tags/page.tsx deleted file mode 100644 index bb99c6a4..00000000 --- a/starters/nextjs-starter-approuter-ts/app/tags/page.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { PCCConvenienceFunctions } from "@pantheon-systems/pcc-react-sdk/server"; -import Image from "next/image"; -import Layout from "../../components/layout"; -import { Tags } from "../../components/tags"; -import TagResults from "./tag-results"; - -export default async function TagSearch({ searchParams }) { - const [articles, tags] = await Promise.all([ - await PCCConvenienceFunctions.getAllArticles( - { - publishingLevel: "PRODUCTION", - }, - { - tagContains: searchParams.q, - }, - ), - PCCConvenienceFunctions.getTags(), - ]); - - const searchString = searchParams.q || ""; - - const HomepageHeader = () => ( -
    -

    - Welcome to" - - Next.js! - -

    -
    -
    - Decoupled PCC on{" "} - Pantheon Logo -
    -
    -
    - ); - - return ( - - - -
    -

    Site-wide

    - -
    -
    - ); -} - -export function generateMetadata() { - return { - title: "Decoupled Next PCC Demo", - description: "Generated by create-pantheon-decoupled-kit.", - }; -} diff --git a/starters/nextjs-starter-approuter-ts/app/tags/tag-results.tsx b/starters/nextjs-starter-approuter-ts/app/tags/tag-results.tsx deleted file mode 100644 index e3cfb263..00000000 --- a/starters/nextjs-starter-approuter-ts/app/tags/tag-results.tsx +++ /dev/null @@ -1,34 +0,0 @@ -"use client"; - -import { ArticleWithoutContent } from "@pantheon-systems/pcc-react-sdk"; -import { useSetAtom } from "jotai"; -import { useEffect } from "react"; -import { PostGrid } from "../../components/grid"; -import { searchQueryAtom } from "../../components/searchbar"; - -interface Props { - articles: ArticleWithoutContent[]; - searchString: string; -} - -export default function TagResults({ articles, searchString }: Props) { - const setSearchQuery = useSetAtom(searchQueryAtom); - - useEffect(() => { - setSearchQuery(searchString); - // Don't include searchString as a hook dependency because we only - // want to update it when this component initially mounts. - }, [setSearchQuery]); // eslint-disable-line react-hooks/exhaustive-deps - - return searchString.trim().length ? ( - <> - {" "} -

    - Article with tag "{searchString}" -

    -
    - -
    - - ) : null; -} diff --git a/starters/nextjs-starter-approuter-ts/components/smart-components/client-components.ts b/starters/nextjs-starter-approuter-ts/components/smart-components/client-components.ts index c06e7c65..c86bf2a0 100644 --- a/starters/nextjs-starter-approuter-ts/components/smart-components/client-components.ts +++ b/starters/nextjs-starter-approuter-ts/components/smart-components/client-components.ts @@ -1,8 +1,13 @@ import { SmartComponentMap } from "@pantheon-systems/pcc-react-sdk/components"; +import LeadCapture from "./lead-capture"; import MediaPreview from "./media-preview"; import { serverSmartComponentMap } from "./server-components"; const clientSmartComponentMap: SmartComponentMap = { + LEAD_CAPTURE: { + ...serverSmartComponentMap.LEAD_CAPTURE, + reactComponent: LeadCapture, + }, MEDIA_PREVIEW: { ...serverSmartComponentMap.MEDIA_PREVIEW, reactComponent: MediaPreview, diff --git a/starters/nextjs-starter-approuter-ts/components/smart-components/lead-capture.tsx b/starters/nextjs-starter-approuter-ts/components/smart-components/lead-capture.tsx new file mode 100644 index 00000000..66061512 --- /dev/null +++ b/starters/nextjs-starter-approuter-ts/components/smart-components/lead-capture.tsx @@ -0,0 +1,61 @@ +"use client"; + +import React, { useState } from "react"; +import { Button } from "../ui/button"; + +interface Props { + heading: string; + description: string; + inputLabel: string; + submitButtonText?: string; + onSubmit?: (e: React.FormEvent) => void | Promise; +} + +const LeadCapture = ({ + heading, + description, + inputLabel, + submitButtonText, + onSubmit, +}: Props) => { + const [submitted, setSubmitted] = useState(false); + + const defaultSubmitHandler = async (e: React.FormEvent) => { + e.preventDefault(); + + if (onSubmit) { + await onSubmit(e); + } else { + alert("Form submitted successfully"); + } + + setSubmitted(true); + }; + + return ( +
    + {submitted ? ( + <> +

    Thank you.

    +

    The form was submitted successfully.

    + + ) : ( +
    +

    {heading}

    +

    {description}

    + + +
    + )} +
    + ); +}; + +export default LeadCapture; diff --git a/starters/nextjs-starter-approuter-ts/components/smart-components/server-components.ts b/starters/nextjs-starter-approuter-ts/components/smart-components/server-components.ts index 2a7151ff..979aec5c 100644 --- a/starters/nextjs-starter-approuter-ts/components/smart-components/server-components.ts +++ b/starters/nextjs-starter-approuter-ts/components/smart-components/server-components.ts @@ -1,6 +1,32 @@ import { ServersideSmartComponentMap } from "@pantheon-systems/pcc-react-sdk/components"; const serverSmartComponentMap: ServersideSmartComponentMap = { + LEAD_CAPTURE: { + title: "Lead Capture Form", + iconUrl: null, + fields: { + heading: { + displayName: "Heading", + required: true, + type: "string", + }, + description: { + displayName: "Description", + required: true, + type: "string", + }, + inputLabel: { + displayName: "Input Label", + required: true, + type: "string", + }, + submitButtonText: { + displayName: "Submit Button Text", + required: false, + type: "string", + }, + }, + }, MEDIA_PREVIEW: { title: "Media Preview", iconUrl: null, diff --git a/starters/nextjs-starter-approuter-ts/hooks/usePagination.ts b/starters/nextjs-starter-approuter-ts/hooks/usePagination.ts index c7e9a3c5..9a9f41f8 100644 --- a/starters/nextjs-starter-approuter-ts/hooks/usePagination.ts +++ b/starters/nextjs-starter-approuter-ts/hooks/usePagination.ts @@ -1,7 +1,7 @@ import { ArticleWithoutContent, PaginatedArticle, -} from "@pantheon-systems/pcc-sdk-core/types"; +} from "@pantheon-systems/pcc-react-sdk"; import { useEffect, useState } from "react"; interface Props { diff --git a/starters/nextjs-starter-approuter-ts/package.json b/starters/nextjs-starter-approuter-ts/package.json index 40be861f..6308884a 100644 --- a/starters/nextjs-starter-approuter-ts/package.json +++ b/starters/nextjs-starter-approuter-ts/package.json @@ -3,11 +3,11 @@ "version": "1.1.6", "private": true, "license": "GPL-3.0-or-later", - "description": "", - "homepage": "", - "bugs": "", - "repository": "", - "author": "", + "description": "A starter for building a Pantheon Content Cloud (PCC) powered site with Next.js App Router and TypeScript", + "homepage": "https://pcc.pantheon.io/docs", + "repository": "https://github.com/pantheon-systems/pantheon-content-cloud-sdk/tree/main/starters/nextjs-starter-approuter-ts", + "bugs": "https://github.com/pantheon-systems/pantheon-content-cloud-sdk/issues", + "author": "@pantheon-systems", "scripts": { "dev": "next dev -p 3001", "build": "next build && cp -r .next/static .next/standalone/.next && cp -r public .next/standalone", @@ -28,10 +28,8 @@ "@radix-ui/react-slot": "^1.1.0", "@tailwindcss/typography": "^0.5.10", "class-variance-authority": "^0.7.0", - "classnames": "^2.5.1", "clsx": "^2.1.1", "dotenv": "^16.4.5", - "jotai": "^2.7.0", "markdown-to-txt": "^2.0.1", "next": "^14.2.5", "query-string": "^8.2.0", diff --git a/starters/nextjs-starter-ts/README.md b/starters/nextjs-starter-ts/README.md index e5705712..cff20a49 100644 --- a/starters/nextjs-starter-ts/README.md +++ b/starters/nextjs-starter-ts/README.md @@ -1,4 +1,4 @@ -# Pantheon Decoupled Kit Next Pantheon Content Cloud Starter +# Pantheon Content Cloud Next.js Starter ## Getting Started diff --git a/starters/nextjs-starter-ts/__tests__/hasConfiguredPantheonClient.test.ts b/starters/nextjs-starter-ts/__tests__/hasConfiguredPantheonClient.test.ts index 56564cb5..bcf96a1e 100644 --- a/starters/nextjs-starter-ts/__tests__/hasConfiguredPantheonClient.test.ts +++ b/starters/nextjs-starter-ts/__tests__/hasConfiguredPantheonClient.test.ts @@ -2,7 +2,7 @@ import { pantheonAPIOptions } from "../pages/api/pantheoncloud/[...command]"; describe("hasConfiguredPantheonClient", () => { it("Pantheon API options have been filled out", () => { - expect(pantheonAPIOptions.smartComponentMap.LEAD_CAPTURE).toBeDefined(); + expect(pantheonAPIOptions.smartComponentMap.MEDIA_PREVIEW).toBeDefined(); }); it("Resolve document by article id", () => { diff --git a/starters/nextjs-starter-ts/components/smart-components/index.ts b/starters/nextjs-starter-ts/components/smart-components/index.ts index a2eeff94..7253e118 100644 --- a/starters/nextjs-starter-ts/components/smart-components/index.ts +++ b/starters/nextjs-starter-ts/components/smart-components/index.ts @@ -2,10 +2,37 @@ import { ServersideSmartComponentMap, SmartComponentMap, } from "@pantheon-systems/pcc-react-sdk/components"; -import MediaPreview from "./media-preview"; import { withSmartComponentErrorBoundary } from "./error-boundary"; +import LeadCapture from "./lead-capture"; +import MediaPreview from "./media-preview"; export const serverSmartComponentMap = { + LEAD_CAPTURE: { + title: "Lead Capture Form", + iconUrl: null, + fields: { + heading: { + displayName: "Heading", + required: true, + type: "string", + }, + description: { + displayName: "Description", + required: true, + type: "string", + }, + inputLabel: { + displayName: "Input Label", + required: true, + type: "string", + }, + submitButtonText: { + displayName: "Submit Button Text", + required: false, + type: "string", + }, + }, + }, MEDIA_PREVIEW: { title: "Media Preview", iconUrl: null, @@ -26,5 +53,9 @@ export const clientSmartComponentMap: SmartComponentMap = { ...serverSmartComponentMap.MEDIA_PREVIEW, reactComponent: withSmartComponentErrorBoundary(MediaPreview), }, + LEAD_CAPTURE: { + ...serverSmartComponentMap.LEAD_CAPTURE, + reactComponent: withSmartComponentErrorBoundary(LeadCapture), + }, }; diff --git a/starters/nextjs-starter-ts/components/smart-components/lead-capture.tsx b/starters/nextjs-starter-ts/components/smart-components/lead-capture.tsx new file mode 100644 index 00000000..4904f632 --- /dev/null +++ b/starters/nextjs-starter-ts/components/smart-components/lead-capture.tsx @@ -0,0 +1,59 @@ +import { useState } from "react"; +import { Button } from "../ui/button"; + +interface Props { + heading: string; + description: string; + inputLabel: string; + submitButtonText?: string; + onSubmit?: (e: React.FormEvent) => void | Promise; +} + +const LeadCapture = ({ + heading, + description, + inputLabel, + submitButtonText, + onSubmit, +}: Props) => { + const [submitted, setSubmitted] = useState(false); + + const defaultSubmitHandler = async (e: React.FormEvent) => { + e.preventDefault(); + + if (onSubmit) { + await onSubmit(e); + } else { + alert("Form submitted successfully"); + } + + setSubmitted(true); + }; + + return ( +
    + {submitted ? ( + <> +

    Thank you.

    +

    The form was submitted successfully.

    + + ) : ( +
    +

    {heading}

    +

    {description}

    + + +
    + )} +
    + ); +}; + +export default LeadCapture; diff --git a/starters/nextjs-starter-ts/hooks/usePagination.ts b/starters/nextjs-starter-ts/hooks/usePagination.ts index 35165287..d619a36d 100644 --- a/starters/nextjs-starter-ts/hooks/usePagination.ts +++ b/starters/nextjs-starter-ts/hooks/usePagination.ts @@ -1,7 +1,7 @@ import { ArticleWithoutContent, PaginatedArticle, -} from "@pantheon-systems/pcc-sdk-core/types"; +} from "@pantheon-systems/pcc-react-sdk"; import { useCallback, useEffect, useState } from "react"; import useSWR from "swr"; diff --git a/starters/nextjs-starter-ts/package.json b/starters/nextjs-starter-ts/package.json index 63bb6db7..9cff3eb1 100644 --- a/starters/nextjs-starter-ts/package.json +++ b/starters/nextjs-starter-ts/package.json @@ -3,11 +3,11 @@ "version": "1.0.0", "private": true, "license": "GPL-3.0-or-later", - "description": "", - "homepage": "", - "bugs": "", - "repository": "", - "author": "", + "description": "A starter for building a Pantheon Content Cloud (PCC) powered site with Next.js and TypeScript", + "homepage": "https://pcc.pantheon.io/docs", + "repository": "https://github.com/pantheon-systems/pantheon-content-cloud-sdk/tree/main/starters/nextjs-starter-ts", + "bugs": "https://github.com/pantheon-systems/pantheon-content-cloud-sdk/issues", + "author": "@pantheon-systems", "scripts": { "dev": "next dev -p 3001", "build": "next build && cp -r .next/static .next/standalone/.next && cp -r public .next/standalone", @@ -24,13 +24,12 @@ }, "dependencies": { "@pantheon-systems/pcc-react-sdk": "~3.7.0", - "@pantheon-systems/pds-toolkit-react": "1.0.0-dev.55", "@radix-ui/react-popover": "^1.1.1", + "@radix-ui/react-slot": "^1.1.0", "@tailwindcss/typography": "^0.5.10", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "dotenv": "^16.4.5", - "jotai": "^2.7.0", "markdown-to-txt": "^2.0.1", "next": "^14.2.5", "next-seo": "^5.15.0", @@ -49,7 +48,6 @@ "@types/react-dom": "^18.3.0", "@vitejs/plugin-react": "^4.2.1", "autoprefixer": "^10.4.17", - "c8": "^7.14.0", "eslint": "^8.57.0", "eslint-config-next": "^14.2.3", "jsdom": "^22.1.0", diff --git a/starters/nextjs-starter-ts/pages/examples/index.tsx b/starters/nextjs-starter-ts/pages/examples/index.tsx index 50ae582b..78426980 100644 --- a/starters/nextjs-starter-ts/pages/examples/index.tsx +++ b/starters/nextjs-starter-ts/pages/examples/index.tsx @@ -10,12 +10,14 @@ export default function ExamplesPageTemplate() {
    -
    +

    - This page outlines a growing list of common use cases that can be - used as a reference when building using this starter kit. If you - don't need them for your site, feel free to delete the - `pages/examples` directory in your codebase. + + This page outlines a growing list of common use cases that can be + used as a reference when building using this starter kit. If you + don't need them for your site, feel free to delete the + `pages/examples` directory in your codebase. +

    • diff --git a/starters/nextjs-starter-ts/pages/examples/ssg-isr/index.tsx b/starters/nextjs-starter-ts/pages/examples/ssg-isr/index.tsx index 1416ffaf..440246a1 100644 --- a/starters/nextjs-starter-ts/pages/examples/ssg-isr/index.tsx +++ b/starters/nextjs-starter-ts/pages/examples/ssg-isr/index.tsx @@ -35,7 +35,7 @@ export default function SSGISRExampleTemplate({ />
      -
      +

      By default, this starter kit is optimized for SSR and Edge Caching diff --git a/starters/nextjs-starter/README.md b/starters/nextjs-starter/README.md index 58e49d38..20423cd7 100644 --- a/starters/nextjs-starter/README.md +++ b/starters/nextjs-starter/README.md @@ -1,4 +1,4 @@ -# Pantheon Decoupled Kit Next Pantheon Content Cloud Starter +# Pantheon Content Cloud Next.js Starter ## Getting Started diff --git a/starters/nextjs-starter/__tests__/hasConfiguredPantheonClient.test.js b/starters/nextjs-starter/__tests__/hasConfiguredPantheonClient.test.js index b62364b3..182d3209 100644 --- a/starters/nextjs-starter/__tests__/hasConfiguredPantheonClient.test.js +++ b/starters/nextjs-starter/__tests__/hasConfiguredPantheonClient.test.js @@ -2,7 +2,7 @@ import { pantheonAPIOptions } from "../pages/api/pantheoncloud/[...command]"; describe("hasConfiguredPantheonClient", () => { it("Pantheon API options have been filled out", () => { - expect(pantheonAPIOptions.smartComponentMap.LEAD_CAPTURE).toBeDefined(); + expect(pantheonAPIOptions.smartComponentMap.MEDIA_PREVIEW).toBeDefined(); }); it("Resolve document by article id", () => { diff --git a/starters/nextjs-starter/components/searchbar.jsx b/starters/nextjs-starter/components/searchbar.jsx deleted file mode 100644 index c5107563..00000000 --- a/starters/nextjs-starter/components/searchbar.jsx +++ /dev/null @@ -1,42 +0,0 @@ -import { useState } from "react"; -import { useRouter } from "next/router"; -import classNames from "classnames"; -import { atom, useAtom } from "jotai"; - -export const searchQueryAtom = atom(""); - -export const Searchbar = () => { - const router = useRouter(); - const [isFocused, setIsFocused] = useState(false); - const [searchQuery, setSearchQuery] = useAtom(searchQueryAtom); - - return ( -

      - setIsFocused(true)} - onBlur={() => setIsFocused(false)} - value={searchQuery} - onChange={(e) => setSearchQuery(e.target.value)} - onKeyDown={(e) => { - if (e.key === "Enter") { - router.push({ - pathname: "/search", - query: { - q: searchQuery, - }, - }); - } - }} - /> -
      - ); -}; diff --git a/starters/nextjs-starter/components/smart-components/index.jsx b/starters/nextjs-starter/components/smart-components/index.jsx index d87b560d..81d2a2a5 100644 --- a/starters/nextjs-starter/components/smart-components/index.jsx +++ b/starters/nextjs-starter/components/smart-components/index.jsx @@ -1,7 +1,34 @@ import { withSmartComponentErrorBoundary } from "./error-boundary"; +import LeadCapture from "./lead-capture"; import MediaPreview from "./media-preview"; export const serverSmartComponentMap = { + LEAD_CAPTURE: { + title: "Lead Capture Form", + iconUrl: null, + fields: { + heading: { + displayName: "Heading", + required: true, + type: "string", + }, + description: { + displayName: "Description", + required: true, + type: "string", + }, + inputLabel: { + displayName: "Input Label", + required: true, + type: "string", + }, + submitButtonText: { + displayName: "Submit Button Text", + required: false, + type: "string", + }, + }, + }, MEDIA_PREVIEW: { title: "Media Preview", iconUrl: null, @@ -22,5 +49,8 @@ export const clientSmartComponentMap = { ...serverSmartComponentMap.MEDIA_PREVIEW, reactComponent: withSmartComponentErrorBoundary(MediaPreview), }, + LEAD_CAPTURE: { + ...serverSmartComponentMap.LEAD_CAPTURE, + reactComponent: withSmartComponentErrorBoundary(LeadCapture), + }, }; - diff --git a/starters/nextjs-starter/components/smart-components/lead-capture.jsx b/starters/nextjs-starter/components/smart-components/lead-capture.jsx new file mode 100644 index 00000000..899060c7 --- /dev/null +++ b/starters/nextjs-starter/components/smart-components/lead-capture.jsx @@ -0,0 +1,51 @@ +import { useState } from "react"; +import { Button } from "../ui/button"; + +const LeadCapture = ({ + heading, + description, + inputLabel, + submitButtonText, + onSubmit, +}) => { + const [submitted, setSubmitted] = useState(false); + + const defaultSubmitHandler = async (e) => { + e.preventDefault(); + + if (onSubmit) { + await onSubmit(e); + } else { + alert("Form submitted successfully"); + } + + setSubmitted(true); + }; + + return ( +
      + {submitted ? ( + <> +

      Thank you.

      +

      The form was submitted successfully.

      + + ) : ( +
      +

      {heading}

      +

      {description}

      + + +
      + )} +
      + ); +}; + +export default LeadCapture; diff --git a/starters/nextjs-starter/package.json b/starters/nextjs-starter/package.json index ff3be6cf..db7dfcad 100644 --- a/starters/nextjs-starter/package.json +++ b/starters/nextjs-starter/package.json @@ -3,11 +3,11 @@ "version": "1.0.0", "private": true, "license": "GPL-3.0-or-later", - "description": "", - "homepage": "", - "bugs": "", - "repository": "", - "author": "", + "description": "A starter for building a Pantheon Content Cloud (PCC) powered site with Next.js", + "homepage": "https://pcc.pantheon.io/docs", + "repository": "https://github.com/pantheon-systems/pantheon-content-cloud-sdk/tree/main/starters/nextjs-starter", + "bugs": "https://github.com/pantheon-systems/pantheon-content-cloud-sdk/issues", + "author": "@pantheon-systems", "scripts": { "dev": "next dev -p 3000", "build": "next build && cp -r .next/static .next/standalone/.next && cp -r public .next/standalone", @@ -24,7 +24,6 @@ }, "dependencies": { "@pantheon-systems/pcc-react-sdk": "~3.7.0", - "@pantheon-systems/pds-toolkit-react": "1.0.0-dev.55", "@radix-ui/react-popover": "^1.1.1", "@radix-ui/react-slot": "^1.1.0", "@tailwindcss/typography": "^0.5.10", @@ -32,7 +31,6 @@ "classnames": "^2.5.1", "clsx": "^2.1.1", "dotenv": "^16.4.5", - "jotai": "^2.7.0", "markdown-to-txt": "^2.0.1", "next": "^14.2.5", "next-seo": "^5.15.0", @@ -49,7 +47,6 @@ "@testing-library/react": "13.4.0", "@vitejs/plugin-react": "^4.2.1", "autoprefixer": "^10.4.17", - "c8": "^7.14.0", "eslint": "^8.57.0", "eslint-config-next": "^14.2.3", "jsdom": "^22.1.0", diff --git a/starters/nextjs-starter/pages/examples/index.jsx b/starters/nextjs-starter/pages/examples/index.jsx index 50ae582b..78426980 100644 --- a/starters/nextjs-starter/pages/examples/index.jsx +++ b/starters/nextjs-starter/pages/examples/index.jsx @@ -10,12 +10,14 @@ export default function ExamplesPageTemplate() {
      -
      +

      - This page outlines a growing list of common use cases that can be - used as a reference when building using this starter kit. If you - don't need them for your site, feel free to delete the - `pages/examples` directory in your codebase. + + This page outlines a growing list of common use cases that can be + used as a reference when building using this starter kit. If you + don't need them for your site, feel free to delete the + `pages/examples` directory in your codebase. +

      • diff --git a/starters/nextjs-starter/pages/examples/ssg-isr/index.jsx b/starters/nextjs-starter/pages/examples/ssg-isr/index.jsx index aeaeb4e4..7aa59726 100644 --- a/starters/nextjs-starter/pages/examples/ssg-isr/index.jsx +++ b/starters/nextjs-starter/pages/examples/ssg-isr/index.jsx @@ -31,7 +31,7 @@ export default function SSGISRExampleTemplate({ />
        -
        +

        By default, this starter kit is optimized for SSR and Edge Caching