From db035ccc6fefa7e8b9a39075982e31a67731a01e Mon Sep 17 00:00:00 2001 From: Kevin Stubbs Date: Fri, 27 Dec 2024 20:27:22 +0200 Subject: [PATCH 1/3] Implement new author pages and author header on articles for the starter kits. --- pnpm-lock.yaml | 634 +++++++++++++++--- .../app/authors/[author]/page.tsx | 111 +++ .../components/article-list.tsx | 4 +- .../components/article-view.tsx | 169 +++-- .../nextjs-starter-approuter-ts/package.json | 1 + .../public/images/no-avatar.png | Bin 0 -> 25813 bytes .../components/article-view.tsx | 76 ++- .../nextjs-starter-ts/hooks/usePagination.ts | 24 +- starters/nextjs-starter-ts/next-env.d.ts | 2 +- starters/nextjs-starter-ts/package.json | 1 + .../pages/api/utils/paginate.ts | 5 + .../pages/authors/[author].tsx | 113 ++++ .../public/images/no-avatar.png | Bin 0 -> 25813 bytes .../components/article-view.jsx | 138 ++-- .../nextjs-starter/hooks/usePagination.js | 18 +- starters/nextjs-starter/next-env.d.ts | 2 +- starters/nextjs-starter/package.json | 1 + .../pages/api/utils/paginate.js | 5 + .../nextjs-starter/pages/authors/[author].jsx | 109 +++ .../public/images/no-avatar.png | Bin 0 -> 25813 bytes 20 files changed, 1170 insertions(+), 243 deletions(-) create mode 100644 starters/nextjs-starter-approuter-ts/app/authors/[author]/page.tsx create mode 100644 starters/nextjs-starter-approuter-ts/public/images/no-avatar.png create mode 100644 starters/nextjs-starter-ts/pages/authors/[author].tsx create mode 100644 starters/nextjs-starter-ts/public/images/no-avatar.png create mode 100644 starters/nextjs-starter/pages/authors/[author].jsx create mode 100644 starters/nextjs-starter/public/images/no-avatar.png diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index da9e8a05..e01f888d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -89,7 +89,7 @@ importers: version: link:../../packages/react-sample-library next: specifier: ^14.2.10 - version: 14.2.10(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) + version: 14.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) react: specifier: 18.3.1 version: 18.3.1 @@ -139,7 +139,7 @@ importers: version: link:../../configs/eslint tsup: specifier: ^8.2.4 - version: 8.2.4(@swc/core@1.4.2)(jiti@1.21.6)(postcss@8.4.47)(typescript@5.5.4)(yaml@2.6.0) + version: 8.2.4(@swc/core@1.4.2(@swc/helpers@0.5.5))(jiti@1.21.6)(postcss@8.4.47)(typescript@5.5.4)(yaml@2.6.0) typescript: specifier: ^5.5.4 version: 5.5.4 @@ -260,10 +260,10 @@ importers: version: 0.2.3 ts-jest: specifier: 29.1.0 - version: 29.1.0(@babel/core@7.25.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(esbuild@0.23.0)(jest@29.5.0(@types/node@20.16.1)(babel-plugin-macros@3.1.0))(typescript@5.5.4) + version: 29.1.0(@babel/core@7.25.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.5.0(@types/node@20.16.1)(babel-plugin-macros@3.1.0))(typescript@5.5.4) tsup: specifier: ^8.2.4 - version: 8.2.4(@swc/core@1.4.2)(jiti@1.21.6)(postcss@8.4.47)(typescript@5.5.4)(yaml@2.6.0) + version: 8.2.4(@swc/core@1.4.2(@swc/helpers@0.5.5))(jiti@1.21.6)(postcss@8.4.47)(typescript@5.5.4)(yaml@2.6.0) packages/core: dependencies: @@ -306,7 +306,7 @@ importers: version: link:../../configs/eslint tsup: specifier: ^8.2.4 - version: 8.2.4(@swc/core@1.4.2)(jiti@1.21.6)(postcss@8.4.47)(typescript@5.5.4)(yaml@2.6.0) + version: 8.2.4(@swc/core@1.4.2(@swc/helpers@0.5.5))(jiti@1.21.6)(postcss@8.4.47)(typescript@5.5.4)(yaml@2.6.0) vitest: specifier: ^1.3.1 version: 1.3.1(@types/node@20.11.21)(jsdom@22.1.0)(sass@1.71.1)(terser@5.28.1) @@ -328,7 +328,7 @@ importers: version: 8.1.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(encoding@0.1.13)(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(webpack-sources@3.2.3) '@storybook/addon-interactions': specifier: ^8.1.4 - version: 8.1.4(@jest/globals@29.7.0)(@types/jest@29.5.1)(jest@29.5.0(@types/node@20.11.21))(vitest@1.3.1(@types/node@20.11.21)(sass@1.71.1)) + version: 8.1.4(@jest/globals@29.7.0)(@types/jest@29.5.1)(jest@29.5.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0))(vitest@1.3.1(@types/node@20.11.21)(jsdom@22.1.0)(sass@1.71.1)(terser@5.28.1)) '@storybook/addon-links': specifier: ^8.1.4 version: 8.1.4(react@18.3.1) @@ -340,13 +340,13 @@ importers: version: 8.1.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(encoding@0.1.13)(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@storybook/nextjs': specifier: ^8.1.4 - version: 8.1.4(@jest/globals@29.7.0)(@swc/core@1.4.2)(@types/jest@29.5.1)(encoding@0.1.13)(esbuild@0.23.0)(jest@29.5.0(@types/node@20.11.21))(next@14.2.10(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1)(type-fest@3.13.1)(typescript@5.5.4)(vitest@1.3.1(@types/node@20.11.21)(sass@1.71.1))(webpack-hot-middleware@2.26.1)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)) + version: 8.1.4(@jest/globals@29.7.0)(@swc/core@1.4.2(@swc/helpers@0.5.5))(@types/jest@29.5.1)(babel-plugin-macros@3.1.0)(encoding@0.1.13)(esbuild@0.20.2)(jest@29.5.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0))(next@14.2.10(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1)(type-fest@3.13.1)(typescript@5.5.4)(vitest@1.3.1(@types/node@20.11.21)(jsdom@22.1.0)(sass@1.71.1)(terser@5.28.1))(webpack-hot-middleware@2.26.1)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) '@storybook/react': specifier: ^8.1.4 version: 8.1.4(encoding@0.1.13)(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@storybook/test': specifier: ^8.1.4 - version: 8.1.4(@jest/globals@29.7.0)(@types/jest@29.5.1)(jest@29.5.0(@types/node@20.11.21))(vitest@1.3.1(@types/node@20.11.21)(sass@1.71.1)) + version: 8.1.4(@jest/globals@29.7.0)(@types/jest@29.5.1)(jest@29.5.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0))(vitest@1.3.1(@types/node@20.11.21)(jsdom@22.1.0)(sass@1.71.1)(terser@5.28.1)) '@types/node': specifier: ^20.11.21 version: 20.11.21 @@ -382,7 +382,7 @@ importers: version: 8.1.4(@babel/preset-env@7.25.3(@babel/core@7.25.2))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) tsup: specifier: ^8.2.4 - version: 8.2.4(@swc/core@1.4.2)(jiti@1.21.6)(postcss@8.4.38)(typescript@5.5.4)(yaml@2.6.0) + version: 8.2.4(@swc/core@1.4.2(@swc/helpers@0.5.5))(jiti@1.21.6)(postcss@8.4.38)(typescript@5.5.4)(yaml@2.6.0) typescript: specifier: ^5.5.4 version: 5.5.4 @@ -443,7 +443,7 @@ importers: version: 18.0.0 babel-loader: specifier: 9.1.2 - version: 9.1.2(@babel/core@7.25.2)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)) + version: 9.1.2(@babel/core@7.25.2)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))) chalk: specifier: ^5.3.0 version: 5.3.0 @@ -482,10 +482,10 @@ importers: version: 18.3.1(react@18.3.1) ts-jest: specifier: 29.1.0 - version: 29.1.0(@babel/core@7.25.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(esbuild@0.23.0)(jest@29.5.0(@types/node@20.16.1)(babel-plugin-macros@3.1.0))(typescript@5.5.4) + version: 29.1.0(@babel/core@7.25.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.5.0(@types/node@20.16.1)(babel-plugin-macros@3.1.0))(typescript@5.5.4) tsup: specifier: ^8.2.4 - version: 8.2.4(@swc/core@1.4.2)(jiti@1.21.6)(postcss@8.4.47)(typescript@5.5.4)(yaml@2.6.0) + version: 8.2.4(@swc/core@1.4.2(@swc/helpers@0.5.5))(jiti@1.21.6)(postcss@8.4.47)(typescript@5.5.4)(yaml@2.6.0) typescript: specifier: ^5.5.4 version: 5.5.4 @@ -506,7 +506,7 @@ importers: version: 4.0.0-beta.12(@apollo/client@3.10.4(@types/react@18.3.3)(graphql-ws@5.15.0(graphql@16.8.1))(graphql@16.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@vue/composition-api@1.7.2(vue@3.4.27(typescript@5.5.4)))(graphql@16.8.1)(typescript@5.5.4)(vue@3.4.27(typescript@5.5.4)) floating-vue: specifier: ^5.2.2 - version: 5.2.2(@nuxt/kit@3.13.2)(vue@3.4.27(typescript@5.5.4)) + version: 5.2.2(@nuxt/kit@3.13.2(magicast@0.3.4)(rollup@4.20.0)(webpack-sources@3.2.3))(vue@3.4.27(typescript@5.5.4)) graphql: specifier: ^16.8.1 version: 16.8.1 @@ -564,7 +564,7 @@ importers: version: 1.71.1 tsup: specifier: ^8.2.4 - version: 8.2.4(@swc/core@1.4.2)(jiti@1.21.6)(postcss@8.4.47)(typescript@5.5.4)(yaml@2.6.0) + version: 8.2.4(@swc/core@1.4.2(@swc/helpers@0.5.5))(jiti@1.21.6)(postcss@8.4.47)(typescript@5.5.4)(yaml@2.6.0) typescript: specifier: ^5.5.4 version: 5.5.4 @@ -640,16 +640,16 @@ importers: version: 10.4.19(postcss@8.4.38) gatsby: specifier: 5.13.5 - version: 5.13.5(babel-eslint@10.1.0(eslint@7.32.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1) + version: 5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1) gatsby-plugin-mdx: specifier: 5.13.1 - version: 5.13.1(@mdx-js/react@2.3.0(react@18.3.1))(gatsby-source-filesystem@5.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@7.32.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1)))(gatsby@5.13.5(babel-eslint@10.1.0(eslint@7.32.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1))(graphql@16.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 5.13.1(@mdx-js/react@2.3.0(react@18.3.1))(gatsby-source-filesystem@5.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1)))(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1))(graphql@16.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) gatsby-plugin-postcss: specifier: 6.13.1 - version: 6.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@7.32.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1))(postcss@8.4.38)(typescript@5.5.4)(webpack@5.90.3) + version: 6.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1))(postcss@8.4.38)(typescript@5.5.4)(webpack@5.90.3) gatsby-source-filesystem: specifier: 5.13.1 - version: 5.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@7.32.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1)) + version: 5.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1)) postcss: specifier: ^8.4.35 version: 8.4.38 @@ -698,10 +698,10 @@ importers: version: 2.0.1 next: specifier: ^14.2.10 - version: 14.2.10(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) + version: 14.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) next-seo: specifier: ^5.15.0 - version: 5.15.0(next@14.2.10(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 5.15.0(next@14.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) query-string: specifier: ^8.2.0 version: 8.2.0 @@ -711,6 +711,9 @@ importers: react-dom: specifier: 18.3.1 version: 18.3.1(react@18.3.1) + react-icons: + specifier: ^5.4.0 + version: 5.4.0(react@18.3.1) react-loading-skeleton: specifier: ^3.4.0 version: 3.4.0(react@18.3.1) @@ -811,6 +814,9 @@ importers: react-dom: specifier: 18.3.1 version: 18.3.1(react@18.3.1) + react-icons: + specifier: ^5.4.0 + version: 5.4.0(react@18.3.1) react-loading-skeleton: specifier: ^3.4.0 version: 3.4.0(react@18.3.1) @@ -904,10 +910,10 @@ importers: version: 2.0.1 next: specifier: ^14.2.10 - version: 14.2.10(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) + version: 14.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) next-seo: specifier: ^5.15.0 - version: 5.15.0(next@14.2.10(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 5.15.0(next@14.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) query-string: specifier: ^8.2.0 version: 8.2.0 @@ -11735,6 +11741,11 @@ packages: react-error-overlay@6.0.11: resolution: {integrity: sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==} + react-icons@5.4.0: + resolution: {integrity: sha512-7eltJxgVt7X64oHh6wSWNwwbKTCtMfK35hcjvJS0yxEAhPM8oUKdS3+kqaW1vicIltw+kR2unHaa12S9pPALoQ==} + peerDependencies: + react: '*' + react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} @@ -12745,6 +12756,7 @@ packages: sudo-prompt@8.2.5: resolution: {integrity: sha512-rlBo3HU/1zAJUrkY6jNxDOC9eVYliG6nS4JA8u8KAshITd07tafMc/Br7xQwCSseXwJ2iCcHCE8SNWX3q8Z+kw==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. superjson@2.2.1: resolution: {integrity: sha512-8iGv75BYOa0xRJHK5vRLEjE2H/i4lulTjzpUXic3Eg8akftYjkmQDa8JARQ42rlczXyFR3IeRoeFCc7RxHsYZA==} @@ -18471,7 +18483,7 @@ snapshots: '@pkgr/core@0.1.1': {} - '@pmmmwh/react-refresh-webpack-plugin@0.5.11(react-refresh@0.14.0)(type-fest@3.13.1)(webpack-hot-middleware@2.26.1)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0))': + '@pmmmwh/react-refresh-webpack-plugin@0.5.11(react-refresh@0.14.0)(type-fest@3.13.1)(webpack-hot-middleware@2.26.1)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2))': dependencies: ansi-html-community: 0.0.8 common-path-prefix: 3.0.0 @@ -18483,7 +18495,7 @@ snapshots: react-refresh: 0.14.0 schema-utils: 3.3.0 source-map: 0.7.4 - webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.23.0) + webpack: 5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2) optionalDependencies: type-fest: 3.13.1 webpack-hot-middleware: 2.26.1 @@ -19106,11 +19118,11 @@ snapshots: dependencies: '@storybook/global': 5.0.0 - '@storybook/addon-interactions@8.1.4(@jest/globals@29.7.0)(@types/jest@29.5.1)(jest@29.5.0(@types/node@20.11.21))(vitest@1.3.1(@types/node@20.11.21)(sass@1.71.1))': + '@storybook/addon-interactions@8.1.4(@jest/globals@29.7.0)(@types/jest@29.5.1)(jest@29.5.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0))(vitest@1.3.1(@types/node@20.11.21)(jsdom@22.1.0)(sass@1.71.1)(terser@5.28.1))': dependencies: '@storybook/global': 5.0.0 '@storybook/instrumenter': 8.1.4 - '@storybook/test': 8.1.4(@jest/globals@29.7.0)(@types/jest@29.5.1)(jest@29.5.0(@types/node@20.11.21))(vitest@1.3.1(@types/node@20.11.21)(sass@1.71.1)) + '@storybook/test': 8.1.4(@jest/globals@29.7.0)(@types/jest@29.5.1)(jest@29.5.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0))(vitest@1.3.1(@types/node@20.11.21)(jsdom@22.1.0)(sass@1.71.1)(terser@5.28.1)) '@storybook/types': 8.1.4 polished: 4.3.1 ts-dedent: 2.2.0 @@ -19212,7 +19224,7 @@ snapshots: - prettier - supports-color - '@storybook/builder-webpack5@8.1.4(@swc/core@1.4.2)(encoding@0.1.13)(esbuild@0.23.0)(prettier@3.2.5)(typescript@5.5.4)': + '@storybook/builder-webpack5@8.1.4(@swc/core@1.4.2(@swc/helpers@0.5.5))(encoding@0.1.13)(esbuild@0.20.2)(prettier@3.2.5)(typescript@5.5.4)': dependencies: '@storybook/channels': 8.1.4 '@storybook/client-logger': 8.1.4 @@ -19228,24 +19240,24 @@ snapshots: case-sensitive-paths-webpack-plugin: 2.4.0 cjs-module-lexer: 1.2.3 constants-browserify: 1.0.0 - css-loader: 6.10.0(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)) + css-loader: 6.10.0(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) es-module-lexer: 1.5.3 express: 4.18.2 - fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.5.4)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)) + fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.5.4)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) fs-extra: 11.2.0 - html-webpack-plugin: 5.6.0(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)) + html-webpack-plugin: 5.6.0(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) magic-string: 0.30.12 path-browserify: 1.0.1 process: 0.11.10 semver: 7.6.3 - style-loader: 3.3.4(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)) - terser-webpack-plugin: 5.3.10(@swc/core@1.4.2)(esbuild@0.23.0)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)) + style-loader: 3.3.4(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) + terser-webpack-plugin: 5.3.10(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) ts-dedent: 2.2.0 url: 0.11.3 util: 0.12.5 util-deprecate: 1.0.2 - webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.23.0) - webpack-dev-middleware: 7.2.1(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)) + webpack: 5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2) + webpack-dev-middleware: 7.2.1(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) webpack-hot-middleware: 2.26.1 webpack-virtual-modules: 0.5.0 optionalDependencies: @@ -19619,7 +19631,7 @@ snapshots: '@storybook/manager@8.1.4': {} - '@storybook/nextjs@8.1.4(@jest/globals@29.7.0)(@swc/core@1.4.2)(@types/jest@29.5.1)(encoding@0.1.13)(esbuild@0.23.0)(jest@29.5.0(@types/node@20.11.21))(next@14.2.10(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1)(type-fest@3.13.1)(typescript@5.5.4)(vitest@1.3.1(@types/node@20.11.21)(sass@1.71.1))(webpack-hot-middleware@2.26.1)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0))': + '@storybook/nextjs@8.1.4(@jest/globals@29.7.0)(@swc/core@1.4.2(@swc/helpers@0.5.5))(@types/jest@29.5.1)(babel-plugin-macros@3.1.0)(encoding@0.1.13)(esbuild@0.20.2)(jest@29.5.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0))(next@14.2.10(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1)(type-fest@3.13.1)(typescript@5.5.4)(vitest@1.3.1(@types/node@20.11.21)(jsdom@22.1.0)(sass@1.71.1)(terser@5.28.1))(webpack-hot-middleware@2.26.1)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2))': dependencies: '@babel/core': 7.24.6 '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.24.6) @@ -19634,44 +19646,44 @@ snapshots: '@babel/preset-react': 7.24.6(@babel/core@7.24.6) '@babel/preset-typescript': 7.24.6(@babel/core@7.24.6) '@babel/runtime': 7.24.6 - '@pmmmwh/react-refresh-webpack-plugin': 0.5.11(react-refresh@0.14.0)(type-fest@3.13.1)(webpack-hot-middleware@2.26.1)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)) - '@storybook/builder-webpack5': 8.1.4(@swc/core@1.4.2)(encoding@0.1.13)(esbuild@0.23.0)(prettier@3.2.5)(typescript@5.5.4) + '@pmmmwh/react-refresh-webpack-plugin': 0.5.11(react-refresh@0.14.0)(type-fest@3.13.1)(webpack-hot-middleware@2.26.1)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) + '@storybook/builder-webpack5': 8.1.4(@swc/core@1.4.2(@swc/helpers@0.5.5))(encoding@0.1.13)(esbuild@0.20.2)(prettier@3.2.5)(typescript@5.5.4) '@storybook/core-common': 8.1.4(encoding@0.1.13)(prettier@3.2.5) '@storybook/core-events': 8.1.4 '@storybook/node-logger': 8.1.4 - '@storybook/preset-react-webpack': 8.1.4(@swc/core@1.4.2)(encoding@0.1.13)(esbuild@0.23.0)(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) + '@storybook/preset-react-webpack': 8.1.4(@swc/core@1.4.2(@swc/helpers@0.5.5))(encoding@0.1.13)(esbuild@0.20.2)(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) '@storybook/preview-api': 8.1.4 '@storybook/react': 8.1.4(encoding@0.1.13)(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) - '@storybook/test': 8.1.4(@jest/globals@29.7.0)(@types/jest@29.5.1)(jest@29.5.0(@types/node@20.11.21))(vitest@1.3.1(@types/node@20.11.21)(sass@1.71.1)) + '@storybook/test': 8.1.4(@jest/globals@29.7.0)(@types/jest@29.5.1)(jest@29.5.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0))(vitest@1.3.1(@types/node@20.11.21)(jsdom@22.1.0)(sass@1.71.1)(terser@5.28.1)) '@storybook/types': 8.1.4 '@types/node': 18.16.9 '@types/semver': 7.5.8 - babel-loader: 9.1.3(@babel/core@7.24.6)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)) - css-loader: 6.10.0(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)) + babel-loader: 9.1.3(@babel/core@7.24.6)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) + css-loader: 6.10.0(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) find-up: 5.0.0 fs-extra: 11.2.0 image-size: 1.1.1 loader-utils: 3.2.1 next: 14.2.10(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) - node-polyfill-webpack-plugin: 2.0.1(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)) + node-polyfill-webpack-plugin: 2.0.1(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) pnp-webpack-plugin: 1.7.0(typescript@5.5.4) postcss: 8.4.38 - postcss-loader: 8.1.1(postcss@8.4.38)(typescript@5.5.4)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)) + postcss-loader: 8.1.1(postcss@8.4.38)(typescript@5.5.4)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) react-refresh: 0.14.0 resolve-url-loader: 5.0.0 - sass-loader: 12.6.0(sass@1.71.1)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)) + sass-loader: 12.6.0(sass@1.71.1)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) semver: 7.6.0 - style-loader: 3.3.4(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)) - styled-jsx: 5.1.1(@babel/core@7.24.6)(react@18.3.1) + style-loader: 3.3.4(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) + styled-jsx: 5.1.1(@babel/core@7.24.6)(babel-plugin-macros@3.1.0)(react@18.3.1) ts-dedent: 2.2.0 tsconfig-paths: 4.2.0 tsconfig-paths-webpack-plugin: 4.1.0 optionalDependencies: sharp: 0.33.4 typescript: 5.5.4 - webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.23.0) + webpack: 5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2) transitivePeerDependencies: - '@jest/globals' - '@rspack/core' @@ -19702,13 +19714,13 @@ snapshots: '@storybook/node-logger@8.1.4': {} - '@storybook/preset-react-webpack@8.1.4(@swc/core@1.4.2)(encoding@0.1.13)(esbuild@0.23.0)(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4)': + '@storybook/preset-react-webpack@8.1.4(@swc/core@1.4.2(@swc/helpers@0.5.5))(encoding@0.1.13)(esbuild@0.20.2)(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4)': dependencies: '@storybook/core-webpack': 8.1.4(encoding@0.1.13)(prettier@3.2.5) '@storybook/docs-tools': 8.1.4(encoding@0.1.13)(prettier@3.2.5) '@storybook/node-logger': 8.1.4 '@storybook/react': 8.1.4(encoding@0.1.13)(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) - '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.5.4)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)) + '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.5.4)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) '@types/node': 18.16.9 '@types/semver': 7.5.8 find-up: 5.0.0 @@ -19720,7 +19732,7 @@ snapshots: resolve: 1.22.8 semver: 7.6.3 tsconfig-paths: 4.2.0 - webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.23.0) + webpack: 5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2) optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: @@ -19751,7 +19763,7 @@ snapshots: '@storybook/preview@8.1.4': {} - '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.5.4)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0))': + '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.5.4)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2))': dependencies: debug: 4.3.5 endent: 2.1.0 @@ -19761,7 +19773,7 @@ snapshots: react-docgen-typescript: 2.2.2(typescript@5.5.4) tslib: 2.6.2 typescript: 5.5.4 - webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.23.0) + webpack: 5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2) transitivePeerDependencies: - supports-color @@ -19837,14 +19849,14 @@ snapshots: - prettier - supports-color - '@storybook/test@8.1.4(@jest/globals@29.7.0)(@types/jest@29.5.1)(jest@29.5.0(@types/node@20.11.21))(vitest@1.3.1(@types/node@20.11.21)(sass@1.71.1))': + '@storybook/test@8.1.4(@jest/globals@29.7.0)(@types/jest@29.5.1)(jest@29.5.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0))(vitest@1.3.1(@types/node@20.11.21)(jsdom@22.1.0)(sass@1.71.1)(terser@5.28.1))': dependencies: '@storybook/client-logger': 8.1.4 '@storybook/core-events': 8.1.4 '@storybook/instrumenter': 8.1.4 '@storybook/preview-api': 8.1.4 '@testing-library/dom': 9.3.4 - '@testing-library/jest-dom': 6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.1)(jest@29.5.0(@types/node@20.11.21))(vitest@1.3.1(@types/node@20.11.21)(sass@1.71.1)) + '@testing-library/jest-dom': 6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.1)(jest@29.5.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0))(vitest@1.3.1(@types/node@20.11.21)(jsdom@22.1.0)(sass@1.71.1)(terser@5.28.1)) '@testing-library/user-event': 14.5.2(@testing-library/dom@9.3.4) '@vitest/expect': 1.3.1 '@vitest/spy': 1.3.1 @@ -19909,7 +19921,7 @@ snapshots: '@swc/core-win32-x64-msvc@1.4.2': optional: true - '@swc/core@1.4.2': + '@swc/core@1.4.2(@swc/helpers@0.5.5)': dependencies: '@swc/counter': 0.1.3 '@swc/types': 0.1.7 @@ -19924,6 +19936,7 @@ snapshots: '@swc/core-win32-arm64-msvc': 1.4.2 '@swc/core-win32-ia32-msvc': 1.4.2 '@swc/core-win32-x64-msvc': 1.4.2 + '@swc/helpers': 0.5.5 optional: true '@swc/counter@0.1.3': {} @@ -19985,7 +19998,7 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/jest-dom@6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.1)(jest@29.5.0(@types/node@20.11.21))(vitest@1.3.1(@types/node@20.11.21)(sass@1.71.1))': + '@testing-library/jest-dom@6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.1)(jest@29.5.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0))(vitest@1.3.1(@types/node@20.11.21)(jsdom@22.1.0)(sass@1.71.1)(terser@5.28.1))': dependencies: '@adobe/css-tools': 4.3.3 '@babel/runtime': 7.24.0 @@ -19998,7 +20011,7 @@ snapshots: optionalDependencies: '@jest/globals': 29.7.0 '@types/jest': 29.5.1 - jest: 29.5.0(@types/node@20.11.21) + jest: 29.5.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0) vitest: 1.3.1(@types/node@20.11.21)(jsdom@22.1.0)(sass@1.71.1)(terser@5.28.1) '@testing-library/react@13.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': @@ -21414,6 +21427,18 @@ snapshots: transitivePeerDependencies: - supports-color + babel-eslint@10.1.0(eslint@8.57.0): + dependencies: + '@babel/code-frame': 7.26.0 + '@babel/parser': 7.26.1 + '@babel/traverse': 7.25.9 + '@babel/types': 7.26.0 + eslint: 8.57.0 + eslint-visitor-keys: 1.3.0 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + babel-jest@29.7.0(@babel/core@7.25.2): dependencies: '@babel/core': 7.25.2 @@ -21438,19 +21463,19 @@ snapshots: schema-utils: 2.7.1 webpack: 5.90.3 - babel-loader@9.1.2(@babel/core@7.25.2)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)): + babel-loader@9.1.2(@babel/core@7.25.2)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))): dependencies: '@babel/core': 7.25.2 find-cache-dir: 3.3.2 schema-utils: 4.2.0 - webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.23.0) + webpack: 5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5)) - babel-loader@9.1.3(@babel/core@7.24.6)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)): + babel-loader@9.1.3(@babel/core@7.24.6)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)): dependencies: '@babel/core': 7.24.6 find-cache-dir: 4.0.0 schema-utils: 4.2.0 - webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.23.0) + webpack: 5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2) babel-plugin-add-module-exports@1.0.4: {} @@ -21537,6 +21562,14 @@ snapshots: gatsby: 5.13.5(babel-eslint@10.1.0(eslint@7.32.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1) gatsby-core-utils: 4.13.1 + babel-plugin-remove-graphql-queries@5.13.1(@babel/core@7.25.2)(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1)): + dependencies: + '@babel/core': 7.25.2 + '@babel/runtime': 7.24.6 + '@babel/types': 7.25.2 + gatsby: 5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1) + gatsby-core-utils: 4.13.1 + babel-plugin-syntax-trailing-function-commas@7.0.0-beta.0: {} babel-plugin-transform-react-remove-prop-types@0.4.24: {} @@ -22458,13 +22491,13 @@ snapshots: safe-buffer: 5.2.1 sha.js: 2.4.11 - create-jest@29.7.0(@types/node@20.11.21): + create-jest@29.7.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.11.21) + jest-config: 29.7.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -22553,7 +22586,7 @@ snapshots: semver: 7.6.3 webpack: 5.90.3 - css-loader@6.10.0(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)): + css-loader@6.10.0(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)): dependencies: icss-utils: 5.1.0(postcss@8.4.38) postcss: 8.4.38 @@ -22564,7 +22597,7 @@ snapshots: postcss-value-parser: 4.2.0 semver: 7.6.3 optionalDependencies: - webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.23.0) + webpack: 5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2) css-minimizer-webpack-plugin@2.0.0(webpack@5.90.3): dependencies: @@ -23471,7 +23504,7 @@ snapshots: '@typescript-eslint/parser': 5.59.5(eslint@8.57.0)(typescript@5.5.4) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) eslint-plugin-react: 7.33.2(eslint@8.57.0) @@ -23501,6 +23534,21 @@ snapshots: optionalDependencies: typescript: 5.5.4 + eslint-config-react-app@6.0.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@7.32.0)(typescript@5.5.4))(eslint@7.32.0)(typescript@5.5.4))(@typescript-eslint/parser@5.62.0(eslint@7.32.0)(typescript@5.5.4))(babel-eslint@10.1.0(eslint@8.57.0))(eslint-plugin-flowtype@5.10.0(eslint@7.32.0))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@5.62.0(eslint@7.32.0)(typescript@5.5.4))(eslint@7.32.0))(eslint-plugin-jsx-a11y@6.8.0(eslint@7.32.0))(eslint-plugin-react-hooks@4.6.0(eslint@7.32.0))(eslint-plugin-react@7.33.2(eslint@7.32.0))(eslint@7.32.0)(typescript@5.5.4): + dependencies: + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@7.32.0)(typescript@5.5.4))(eslint@7.32.0)(typescript@5.5.4) + '@typescript-eslint/parser': 5.62.0(eslint@7.32.0)(typescript@5.5.4) + babel-eslint: 10.1.0(eslint@8.57.0) + confusing-browser-globals: 1.0.11 + eslint: 7.32.0 + eslint-plugin-flowtype: 5.10.0(eslint@7.32.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.62.0(eslint@7.32.0)(typescript@5.5.4))(eslint@7.32.0) + eslint-plugin-jsx-a11y: 6.8.0(eslint@7.32.0) + eslint-plugin-react: 7.33.2(eslint@7.32.0) + eslint-plugin-react-hooks: 4.6.0(eslint@7.32.0) + optionalDependencies: + typescript: 5.5.4 + eslint-config-turbo@1.12.4(eslint@8.57.0): dependencies: eslint: 8.57.0 @@ -23514,12 +23562,12 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0): + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 4.3.5 enhanced-resolve: 5.15.1 eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.2 @@ -23531,14 +23579,14 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.8.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 5.59.5(eslint@8.57.0)(typescript@5.5.4) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) transitivePeerDependencies: - supports-color @@ -23568,7 +23616,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1)(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) hasown: 2.0.1 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -24200,7 +24248,7 @@ snapshots: flatted@3.3.1: {} - floating-vue@5.2.2(@nuxt/kit@3.13.2)(vue@3.4.27(typescript@5.5.4)): + floating-vue@5.2.2(@nuxt/kit@3.13.2(magicast@0.3.4)(rollup@4.20.0)(webpack-sources@3.2.3))(vue@3.4.27(typescript@5.5.4)): dependencies: '@floating-ui/dom': 1.1.1 vue: 3.4.27(typescript@5.5.4) @@ -24260,7 +24308,7 @@ snapshots: optionalDependencies: eslint: 7.32.0 - fork-ts-checker-webpack-plugin@8.0.0(typescript@5.5.4)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)): + fork-ts-checker-webpack-plugin@8.0.0(typescript@5.5.4)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)): dependencies: '@babel/code-frame': 7.24.7 chalk: 4.1.2 @@ -24275,7 +24323,7 @@ snapshots: semver: 7.6.3 tapable: 2.2.1 typescript: 5.5.4 - webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.23.0) + webpack: 5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2) form-data-encoder@2.1.4: {} @@ -24495,6 +24543,36 @@ snapshots: - graphql - supports-color + gatsby-plugin-mdx@5.13.1(@mdx-js/react@2.3.0(react@18.3.1))(gatsby-source-filesystem@5.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1)))(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1))(graphql@16.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + '@mdx-js/mdx': 2.3.0 + '@mdx-js/react': 2.3.0(react@18.3.1) + acorn: 8.11.3 + acorn-jsx: 5.3.2(acorn@8.11.3) + astring: 1.8.6 + deepmerge: 4.3.1 + estree-util-build-jsx: 2.2.2 + fs-extra: 11.2.0 + gatsby: 5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1) + gatsby-core-utils: 4.13.1 + gatsby-plugin-utils: 4.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1))(graphql@16.8.1) + gatsby-source-filesystem: 5.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1)) + gray-matter: 4.0.3 + mdast-util-mdx: 2.0.1 + mdast-util-to-hast: 10.2.0 + mdast-util-to-markdown: 1.5.0 + mdast-util-toc: 6.1.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + rehype-infer-description-meta: 1.1.0 + remark-unwrap-images: 3.0.1 + unified: 10.1.2 + unist-util-visit: 4.1.2 + vfile: 5.3.7 + transitivePeerDependencies: + - graphql + - supports-color + gatsby-plugin-page-creator@5.13.1(encoding@0.1.13)(gatsby@5.13.5(babel-eslint@10.1.0(eslint@7.32.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1))(graphql@16.8.1): dependencies: '@babel/runtime': 7.24.6 @@ -24515,6 +24593,26 @@ snapshots: - graphql - supports-color + gatsby-plugin-page-creator@5.13.1(encoding@0.1.13)(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1))(graphql@16.8.1): + dependencies: + '@babel/runtime': 7.24.6 + '@babel/traverse': 7.25.3 + '@sindresorhus/slugify': 1.1.2 + chokidar: 3.6.0 + fs-exists-cached: 1.0.0 + fs-extra: 11.2.0 + gatsby: 5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1) + gatsby-core-utils: 4.13.1 + gatsby-page-utils: 3.13.1 + gatsby-plugin-utils: 4.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1))(graphql@16.8.1) + gatsby-telemetry: 4.13.1(encoding@0.1.13) + globby: 11.1.0 + lodash: 4.17.21 + transitivePeerDependencies: + - encoding + - graphql + - supports-color + gatsby-plugin-postcss@6.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@7.32.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1))(postcss@8.4.38)(typescript@5.5.4)(webpack@5.90.3): dependencies: '@babel/runtime': 7.24.6 @@ -24525,6 +24623,16 @@ snapshots: - typescript - webpack + gatsby-plugin-postcss@6.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1))(postcss@8.4.38)(typescript@5.5.4)(webpack@5.90.3): + dependencies: + '@babel/runtime': 7.24.6 + gatsby: 5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1) + postcss: 8.4.38 + postcss-loader: 7.3.4(postcss@8.4.38)(typescript@5.5.4)(webpack@5.90.3) + transitivePeerDependencies: + - typescript + - webpack + gatsby-plugin-typescript@5.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@7.32.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1)): dependencies: '@babel/core': 7.25.2 @@ -24538,6 +24646,19 @@ snapshots: transitivePeerDependencies: - supports-color + gatsby-plugin-typescript@5.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1)): + dependencies: + '@babel/core': 7.25.2 + '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.25.2) + '@babel/plugin-proposal-numeric-separator': 7.18.6(@babel/core@7.25.2) + '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.25.2) + '@babel/preset-typescript': 7.24.7(@babel/core@7.25.2) + '@babel/runtime': 7.24.6 + babel-plugin-remove-graphql-queries: 5.13.1(@babel/core@7.25.2)(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1)) + gatsby: 5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1) + transitivePeerDependencies: + - supports-color + gatsby-plugin-utils@4.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@7.32.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1))(graphql@16.8.1): dependencies: '@babel/runtime': 7.24.6 @@ -24552,6 +24673,20 @@ snapshots: joi: 17.12.2 mime: 3.0.0 + gatsby-plugin-utils@4.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1))(graphql@16.8.1): + dependencies: + '@babel/runtime': 7.24.6 + fastq: 1.17.1 + fs-extra: 11.2.0 + gatsby: 5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1) + gatsby-core-utils: 4.13.1 + gatsby-sharp: 1.13.0 + graphql: 16.8.1 + graphql-compose: 9.0.10(graphql@16.8.1) + import-from: 4.0.0 + joi: 17.12.2 + mime: 3.0.0 + gatsby-react-router-scroll@6.13.1(@gatsbyjs/reach-router@2.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.24.6 @@ -24583,6 +24718,19 @@ snapshots: valid-url: 1.0.9 xstate: 4.38.3 + gatsby-source-filesystem@5.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1)): + dependencies: + '@babel/runtime': 7.24.6 + chokidar: 3.6.0 + file-type: 16.5.4 + fs-extra: 11.2.0 + gatsby: 5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1) + gatsby-core-utils: 4.13.1 + mime: 3.0.0 + pretty-bytes: 5.6.0 + valid-url: 1.0.9 + xstate: 4.38.3 + gatsby-telemetry@4.13.1(encoding@0.1.13): dependencies: '@babel/code-frame': 7.24.7 @@ -24807,6 +24955,204 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve + gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1): + dependencies: + '@babel/code-frame': 7.24.7 + '@babel/core': 7.25.2 + '@babel/eslint-parser': 7.23.10(@babel/core@7.25.2)(eslint@7.32.0) + '@babel/helper-plugin-utils': 7.24.8 + '@babel/parser': 7.25.3 + '@babel/runtime': 7.24.6 + '@babel/traverse': 7.25.3 + '@babel/types': 7.25.2 + '@builder.io/partytown': 0.7.6 + '@gatsbyjs/reach-router': 2.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@gatsbyjs/webpack-hot-middleware': 2.25.3 + '@graphql-codegen/add': 3.2.3(graphql@16.8.1) + '@graphql-codegen/core': 2.6.8(graphql@16.8.1) + '@graphql-codegen/plugin-helpers': 2.7.2(graphql@16.8.1) + '@graphql-codegen/typescript': 2.8.8(encoding@0.1.13)(graphql@16.8.1) + '@graphql-codegen/typescript-operations': 2.5.13(encoding@0.1.13)(graphql@16.8.1) + '@graphql-tools/code-file-loader': 7.3.23(@babel/core@7.25.2)(graphql@16.8.1) + '@graphql-tools/load': 7.8.14(graphql@16.8.1) + '@jridgewell/trace-mapping': 0.3.25 + '@nodelib/fs.walk': 1.2.8 + '@parcel/cache': 2.8.3(@parcel/core@2.8.3) + '@parcel/core': 2.8.3 + '@pmmmwh/react-refresh-webpack-plugin': 0.5.11(react-refresh@0.14.0)(type-fest@3.13.1)(webpack-hot-middleware@2.26.1)(webpack@5.90.3) + '@sigmacomputing/babel-plugin-lodash': 3.3.5 + '@types/http-proxy': 1.17.14 + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@7.32.0)(typescript@5.5.4))(eslint@7.32.0)(typescript@5.5.4) + '@typescript-eslint/parser': 5.62.0(eslint@7.32.0)(typescript@5.5.4) + '@vercel/webpack-asset-relocator-loader': 1.7.3 + acorn-loose: 8.4.0 + acorn-walk: 8.3.2 + address: 1.2.2 + anser: 2.1.1 + autoprefixer: 10.4.19(postcss@8.4.38) + axios: 0.21.4(debug@4.3.5) + babel-jsx-utils: 1.1.0 + babel-loader: 8.3.0(@babel/core@7.25.2)(webpack@5.90.3) + babel-plugin-add-module-exports: 1.0.4 + babel-plugin-dynamic-import-node: 2.3.3 + babel-plugin-remove-graphql-queries: 5.13.1(@babel/core@7.25.2)(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1)) + babel-preset-gatsby: 3.13.2(@babel/core@7.25.2)(core-js@3.36.0) + better-opn: 2.1.1 + bluebird: 3.7.2 + body-parser: 1.20.1 + browserslist: 4.23.3 + cache-manager: 2.11.1 + chalk: 4.1.2 + chokidar: 3.6.0 + common-tags: 1.8.2 + compression: 1.7.4 + cookie: 0.5.0 + core-js: 3.36.0 + cors: 2.8.5 + css-loader: 5.2.7(webpack@5.90.3) + css-minimizer-webpack-plugin: 2.0.0(webpack@5.90.3) + css.escape: 1.5.1 + date-fns: 2.30.0 + debug: 4.3.5 + deepmerge: 4.3.1 + detect-port: 1.5.1 + devcert: 1.2.2 + dotenv: 8.6.0 + enhanced-resolve: 5.15.1 + error-stack-parser: 2.1.4 + eslint: 7.32.0 + eslint-config-react-app: 6.0.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@7.32.0)(typescript@5.5.4))(eslint@7.32.0)(typescript@5.5.4))(@typescript-eslint/parser@5.62.0(eslint@7.32.0)(typescript@5.5.4))(babel-eslint@10.1.0(eslint@8.57.0))(eslint-plugin-flowtype@5.10.0(eslint@7.32.0))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@5.62.0(eslint@7.32.0)(typescript@5.5.4))(eslint@7.32.0))(eslint-plugin-jsx-a11y@6.8.0(eslint@7.32.0))(eslint-plugin-react-hooks@4.6.0(eslint@7.32.0))(eslint-plugin-react@7.33.2(eslint@7.32.0))(eslint@7.32.0)(typescript@5.5.4) + eslint-plugin-flowtype: 5.10.0(eslint@7.32.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.62.0(eslint@7.32.0)(typescript@5.5.4))(eslint@7.32.0) + eslint-plugin-jsx-a11y: 6.8.0(eslint@7.32.0) + eslint-plugin-react: 7.33.2(eslint@7.32.0) + eslint-plugin-react-hooks: 4.6.0(eslint@7.32.0) + eslint-webpack-plugin: 2.7.0(eslint@7.32.0)(webpack@5.90.3) + event-source-polyfill: 1.0.31 + execa: 5.1.1 + express: 4.18.2 + express-http-proxy: 1.6.3 + fastest-levenshtein: 1.0.16 + fastq: 1.17.1 + file-loader: 6.2.0(webpack@5.90.3) + find-cache-dir: 3.3.2 + fs-exists-cached: 1.0.0 + fs-extra: 11.2.0 + gatsby-cli: 5.13.3(encoding@0.1.13) + gatsby-core-utils: 4.13.1 + gatsby-graphiql-explorer: 3.13.1 + gatsby-legacy-polyfills: 3.13.1 + gatsby-link: 5.13.1(@gatsbyjs/reach-router@2.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + gatsby-page-utils: 3.13.1 + gatsby-parcel-config: 1.13.1(@parcel/core@2.8.3) + gatsby-plugin-page-creator: 5.13.1(encoding@0.1.13)(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1))(graphql@16.8.1) + gatsby-plugin-typescript: 5.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1)) + gatsby-plugin-utils: 4.13.1(gatsby@5.13.5(babel-eslint@10.1.0(eslint@8.57.0))(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(type-fest@3.13.1)(typescript@5.5.4)(webpack-hot-middleware@2.26.1))(graphql@16.8.1) + gatsby-react-router-scroll: 6.13.1(@gatsbyjs/reach-router@2.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + gatsby-script: 2.13.0(@gatsbyjs/reach-router@2.0.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + gatsby-telemetry: 4.13.1(encoding@0.1.13) + gatsby-worker: 2.13.1 + glob: 7.2.3 + globby: 11.1.0 + got: 11.8.6 + graphql: 16.8.1 + graphql-compose: 9.0.10(graphql@16.8.1) + graphql-http: 1.22.0(graphql@16.8.1) + graphql-tag: 2.12.6(graphql@16.8.1) + hasha: 5.2.2 + invariant: 2.2.4 + is-relative: 1.0.0 + is-relative-url: 3.0.0 + joi: 17.12.2 + json-loader: 0.5.7 + latest-version: 7.0.0 + linkfs: 2.1.0 + lmdb: 2.5.3 + lodash: 4.17.21 + meant: 1.0.3 + memoizee: 0.4.15 + micromatch: 4.0.5 + mime: 3.0.0 + mini-css-extract-plugin: 1.6.2(webpack@5.90.3) + mitt: 1.2.0 + moment: 2.30.1 + multer: 1.4.5-lts.1 + node-fetch: 2.7.0(encoding@0.1.13) + node-html-parser: 5.4.2 + normalize-path: 3.0.0 + null-loader: 4.0.1(webpack@5.90.3) + opentracing: 0.14.7 + p-defer: 3.0.0 + parseurl: 1.3.3 + path-to-regexp: 0.1.7 + physical-cpu-count: 2.0.0 + platform: 1.3.6 + postcss: 8.4.38 + postcss-flexbugs-fixes: 5.0.2(postcss@8.4.38) + postcss-loader: 5.3.0(postcss@8.4.38)(webpack@5.90.3) + prompts: 2.4.2 + prop-types: 15.8.1 + query-string: 6.14.1 + raw-loader: 4.0.2(webpack@5.90.3) + react: 18.3.1 + react-dev-utils: 12.0.1(eslint@7.32.0)(typescript@5.5.4)(webpack@5.90.3) + react-dom: 18.3.1(react@18.3.1) + react-refresh: 0.14.0 + react-server-dom-webpack: 0.0.0-experimental-c8b778b7f-20220825(react@18.3.1)(webpack@5.90.3) + redux: 4.2.1 + redux-thunk: 2.4.2(redux@4.2.1) + resolve-from: 5.0.0 + semver: 7.6.2 + shallow-compare: 1.2.2 + signal-exit: 3.0.7 + slugify: 1.6.6 + socket.io: 4.7.1 + socket.io-client: 4.7.1 + stack-trace: 0.0.10 + string-similarity: 1.2.2 + strip-ansi: 6.0.1 + style-loader: 2.0.0(webpack@5.90.3) + style-to-object: 0.4.4 + terser-webpack-plugin: 5.3.10(webpack@5.90.3) + tmp: 0.2.3 + true-case-path: 2.2.1 + type-of: 2.0.1 + url-loader: 4.1.1(file-loader@6.2.0(webpack@5.90.3))(webpack@5.90.3) + uuid: 8.3.2 + webpack: 5.90.3 + webpack-dev-middleware: 7.2.1(webpack@5.90.3) + webpack-merge: 5.10.0 + webpack-stats-plugin: 1.1.3 + webpack-virtual-modules: 0.5.0 + xstate: 4.38.3 + yaml-loader: 0.8.1 + optionalDependencies: + gatsby-sharp: 1.13.0 + transitivePeerDependencies: + - '@swc/core' + - '@types/webpack' + - babel-eslint + - bufferutil + - clean-css + - csso + - encoding + - esbuild + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - eslint-plugin-jest + - eslint-plugin-testing-library + - sockjs-client + - supports-color + - type-fest + - typescript + - uglify-js + - utf-8-validate + - vue-template-compiler + - webpack-cli + - webpack-dev-server + - webpack-hot-middleware + - webpack-plugin-serve + gauge@3.0.2: dependencies: aproba: 2.0.0 @@ -25406,7 +25752,7 @@ snapshots: html-void-elements@2.0.1: {} - html-webpack-plugin@5.6.0(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)): + html-webpack-plugin@5.6.0(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -25414,7 +25760,7 @@ snapshots: pretty-error: 4.0.0 tapable: 2.2.1 optionalDependencies: - webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.23.0) + webpack: 5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2) htmlparser2@6.1.0: dependencies: @@ -25993,16 +26339,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.11.21): + jest-cli@29.7.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0): dependencies: '@jest/core': 29.7.0(babel-plugin-macros@3.1.0) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.11.21) + create-jest: 29.7.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.11.21) + jest-config: 29.7.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -26032,7 +26378,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@20.11.21): + jest-config@29.7.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0): dependencies: '@babel/core': 7.25.2 '@jest/test-sequencer': 29.7.0 @@ -26320,12 +26666,12 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.5.0(@types/node@20.11.21): + jest@29.5.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0): dependencies: '@jest/core': 29.7.0(babel-plugin-macros@3.1.0) '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.11.21) + jest-cli: 29.7.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -27623,9 +27969,9 @@ snapshots: neo-async@2.6.2: {} - next-seo@5.15.0(next@14.2.10(@babel/core@7.25.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next-seo@5.15.0(next@14.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - next: 14.2.10(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) + next: 14.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) @@ -27657,6 +28003,32 @@ snapshots: - '@babel/core' - babel-plugin-macros + next@14.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1): + dependencies: + '@next/env': 14.2.10 + '@swc/helpers': 0.5.5 + busboy: 1.6.0 + caniuse-lite: 1.0.30001651 + graceful-fs: 4.2.11 + postcss: 8.4.31 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + styled-jsx: 5.1.1(@babel/core@7.24.6)(babel-plugin-macros@3.1.0)(react@18.3.1) + optionalDependencies: + '@next/swc-darwin-arm64': 14.2.10 + '@next/swc-darwin-x64': 14.2.10 + '@next/swc-linux-arm64-gnu': 14.2.10 + '@next/swc-linux-arm64-musl': 14.2.10 + '@next/swc-linux-x64-gnu': 14.2.10 + '@next/swc-linux-x64-musl': 14.2.10 + '@next/swc-win32-arm64-msvc': 14.2.10 + '@next/swc-win32-ia32-msvc': 14.2.10 + '@next/swc-win32-x64-msvc': 14.2.10 + sass: 1.71.1 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + nitropack@2.9.7(encoding@0.1.13)(magicast@0.3.4)(webpack-sources@3.2.3): dependencies: '@cloudflare/kv-asset-handler': 0.3.4 @@ -27796,7 +28168,7 @@ snapshots: node-object-hash@2.3.10: {} - node-polyfill-webpack-plugin@2.0.1(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)): + node-polyfill-webpack-plugin@2.0.1(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)): dependencies: assert: 2.1.0 browserify-zlib: 0.2.0 @@ -27823,7 +28195,7 @@ snapshots: url: 0.11.3 util: 0.12.5 vm-browserify: 1.1.2 - webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.23.0) + webpack: 5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2) node-releases@2.0.14: {} @@ -28596,14 +28968,14 @@ snapshots: transitivePeerDependencies: - typescript - postcss-loader@8.1.1(postcss@8.4.38)(typescript@5.5.4)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)): + postcss-loader@8.1.1(postcss@8.4.38)(typescript@5.5.4)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)): dependencies: cosmiconfig: 9.0.0(typescript@5.5.4) jiti: 1.21.6 postcss: 8.4.38 semver: 7.6.3 optionalDependencies: - webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.23.0) + webpack: 5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2) transitivePeerDependencies: - typescript @@ -29209,6 +29581,10 @@ snapshots: react-error-overlay@6.0.11: {} + react-icons@5.4.0(react@18.3.1): + dependencies: + react: 18.3.1 + react-is@16.13.1: {} react-is@17.0.2: {} @@ -29786,11 +30162,11 @@ snapshots: safer-buffer@2.1.2: {} - sass-loader@12.6.0(sass@1.71.1)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)): + sass-loader@12.6.0(sass@1.71.1)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)): dependencies: klona: 2.0.6 neo-async: 2.6.2 - webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.23.0) + webpack: 5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2) optionalDependencies: sass: 1.71.1 @@ -29798,7 +30174,7 @@ snapshots: dependencies: chokidar: 3.6.0 immutable: 4.3.5 - source-map-js: 1.2.0 + source-map-js: 1.2.1 saxes@6.0.0: dependencies: @@ -30371,9 +30747,9 @@ snapshots: schema-utils: 3.3.0 webpack: 5.90.3 - style-loader@3.3.4(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)): + style-loader@3.3.4(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)): dependencies: - webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.23.0) + webpack: 5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2) style-to-object@0.4.4: dependencies: @@ -30383,12 +30759,13 @@ snapshots: dependencies: inline-style-parser: 0.2.2 - styled-jsx@5.1.1(@babel/core@7.24.6)(react@18.3.1): + styled-jsx@5.1.1(@babel/core@7.24.6)(babel-plugin-macros@3.1.0)(react@18.3.1): dependencies: client-only: 0.0.1 react: 18.3.1 optionalDependencies: '@babel/core': 7.24.6 + babel-plugin-macros: 3.1.0 styled-jsx@5.1.1(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react@18.3.1): dependencies: @@ -30590,17 +30967,28 @@ snapshots: term-size@2.2.1: {} - terser-webpack-plugin@5.3.10(@swc/core@1.4.2)(esbuild@0.23.0)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)): + terser-webpack-plugin@5.3.10(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 3.3.0 serialize-javascript: 6.0.2 terser: 5.28.1 - webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.23.0) + webpack: 5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2) optionalDependencies: - '@swc/core': 1.4.2 - esbuild: 0.23.0 + '@swc/core': 1.4.2(@swc/helpers@0.5.5) + esbuild: 0.20.2 + + terser-webpack-plugin@5.3.10(@swc/core@1.4.2(@swc/helpers@0.5.5))(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))): + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.2 + terser: 5.28.1 + webpack: 5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5)) + optionalDependencies: + '@swc/core': 1.4.2(@swc/helpers@0.5.5) terser-webpack-plugin@5.3.10(webpack@5.90.3): dependencies: @@ -30738,7 +31126,7 @@ snapshots: dependencies: tslib: 2.6.2 - ts-jest@29.1.0(@babel/core@7.25.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(esbuild@0.23.0)(jest@29.5.0(@types/node@20.16.1)(babel-plugin-macros@3.1.0))(typescript@5.5.4): + ts-jest@29.1.0(@babel/core@7.25.2)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.25.2))(jest@29.5.0(@types/node@20.16.1)(babel-plugin-macros@3.1.0))(typescript@5.5.4): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 @@ -30754,7 +31142,6 @@ snapshots: '@babel/core': 7.25.2 '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.25.2) - esbuild: 0.23.0 ts-pnp@1.2.0(typescript@5.5.4): optionalDependencies: @@ -30785,7 +31172,7 @@ snapshots: tslib@2.6.2: {} - tsup@8.2.4(@swc/core@1.4.2)(jiti@1.21.6)(postcss@8.4.38)(typescript@5.5.4)(yaml@2.6.0): + tsup@8.2.4(@swc/core@1.4.2(@swc/helpers@0.5.5))(jiti@1.21.6)(postcss@8.4.38)(typescript@5.5.4)(yaml@2.6.0): dependencies: bundle-require: 5.0.0(esbuild@0.23.0) cac: 6.7.14 @@ -30804,7 +31191,7 @@ snapshots: sucrase: 3.35.0 tree-kill: 1.2.2 optionalDependencies: - '@swc/core': 1.4.2 + '@swc/core': 1.4.2(@swc/helpers@0.5.5) postcss: 8.4.38 typescript: 5.5.4 transitivePeerDependencies: @@ -30813,7 +31200,7 @@ snapshots: - tsx - yaml - tsup@8.2.4(@swc/core@1.4.2)(jiti@1.21.6)(postcss@8.4.47)(typescript@5.5.4)(yaml@2.6.0): + tsup@8.2.4(@swc/core@1.4.2(@swc/helpers@0.5.5))(jiti@1.21.6)(postcss@8.4.47)(typescript@5.5.4)(yaml@2.6.0): dependencies: bundle-require: 5.0.0(esbuild@0.23.0) cac: 6.7.14 @@ -30832,7 +31219,7 @@ snapshots: sucrase: 3.35.0 tree-kill: 1.2.2 optionalDependencies: - '@swc/core': 1.4.2 + '@swc/core': 1.4.2(@swc/helpers@0.5.5) postcss: 8.4.47 typescript: 5.5.4 transitivePeerDependencies: @@ -31754,7 +32141,7 @@ snapshots: webidl-conversions@7.0.0: {} - webpack-dev-middleware@7.2.1(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)): + webpack-dev-middleware@7.2.1(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)): dependencies: colorette: 2.0.20 memfs: 4.9.2 @@ -31763,7 +32150,7 @@ snapshots: range-parser: 1.2.1 schema-utils: 4.2.0 optionalDependencies: - webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.23.0) + webpack: 5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2) webpack-dev-middleware@7.2.1(webpack@5.90.3): dependencies: @@ -31834,7 +32221,38 @@ snapshots: - esbuild - uglify-js - webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0): + webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5)): + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.5 + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/wasm-edit': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + acorn: 8.14.0 + acorn-import-assertions: 1.9.0(acorn@8.14.0) + browserslist: 4.23.3 + chrome-trace-event: 1.0.3 + enhanced-resolve: 5.15.1 + es-module-lexer: 1.5.3 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.3.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.10(@swc/core@1.4.2(@swc/helpers@0.5.5))(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))) + watchpack: 2.4.0 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + + webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2): dependencies: '@types/eslint-scope': 3.7.7 '@types/estree': 1.0.5 @@ -31857,7 +32275,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.4.2)(esbuild@0.23.0)(webpack@5.90.3(@swc/core@1.4.2)(esbuild@0.23.0)) + terser-webpack-plugin: 5.3.10(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) watchpack: 2.4.0 webpack-sources: 3.2.3 transitivePeerDependencies: diff --git a/starters/nextjs-starter-approuter-ts/app/authors/[author]/page.tsx b/starters/nextjs-starter-approuter-ts/app/authors/[author]/page.tsx new file mode 100644 index 00000000..4eea0e3d --- /dev/null +++ b/starters/nextjs-starter-approuter-ts/app/authors/[author]/page.tsx @@ -0,0 +1,111 @@ +import { PCCConvenienceFunctions } from "@pantheon-systems/pcc-react-sdk/server"; +import Image from "next/image"; +import { + FaFacebookSquare, + FaInstagramSquare, + FaLinkedin, +} from "react-icons/fa"; +import { FaSquareXTwitter } from "react-icons/fa6"; +import { MdEmail } from "react-icons/md"; +import { PiMediumLogoFill } from "react-icons/pi"; +import ArticleList from "../../../components/article-list"; +import Layout from "../../../components/layout"; +import { PAGE_SIZE } from "../../../constants"; + +function fetchNextPages(author?: string) { + return async (cursor: string) => { + "use server"; + const { data, cursor: newCursor } = + await PCCConvenienceFunctions.getPaginatedArticles({ + pageSize: PAGE_SIZE, + metadataFilters: + author == null + ? undefined + : { + author, + }, + cursor, + }); + + return { + data, + newCursor, + }; + }; +} + +export default async function ArticlesListTemplate({ params }) { + const author = params.author ? decodeURIComponent(params.author) : undefined; + + const { + data: articles, + cursor, + totalCount, + } = await PCCConvenienceFunctions.getPaginatedArticles({ + pageSize: PAGE_SIZE, + metadataFilters: { + author, + }, + }); + + if (totalCount === 0) { + return ( + +
+
Could not find any articles by {author}
+
+
+ ); + } + + return ( + + +
+
+ {`Avatar +
+
+

{author}

+
A short line about the author
+
+
+
+ + + + + + +
+
+ {author} is a passionate content writer with a flair for turning + ideas into engaging stories. When she’s not writing, Jane enjoys + cozy afternoons with a good book, exploring new coffee spots, and + finding inspiration in everyday moments. +
+ + } + /> +
+ ); +} + +export function generateMetadata() { + return { + title: "Decoupled Next PCC Demo", + description: "Articles by Author", + }; +} diff --git a/starters/nextjs-starter-approuter-ts/components/article-list.tsx b/starters/nextjs-starter-approuter-ts/components/article-list.tsx index 412b895d..542dd2e3 100644 --- a/starters/nextjs-starter-approuter-ts/components/article-list.tsx +++ b/starters/nextjs-starter-approuter-ts/components/article-list.tsx @@ -12,7 +12,7 @@ import PageHeader from "./page-header"; import Pagination from "./pagination"; interface Props { - headerText: string; + headerText?: string | null | undefined; articles: PaginatedArticle[] | ArticleWithoutContent[]; totalCount: number; cursor: string; @@ -44,7 +44,7 @@ export default function ArticleList({ return (
- + {headerText ? : null} {additionalHeader}
diff --git a/starters/nextjs-starter-approuter-ts/components/article-view.tsx b/starters/nextjs-starter-approuter-ts/components/article-view.tsx index 1233fb47..ef5dff91 100644 --- a/starters/nextjs-starter-approuter-ts/components/article-view.tsx +++ b/starters/nextjs-starter-approuter-ts/components/article-view.tsx @@ -6,7 +6,11 @@ import { ArticleRenderer, useArticleTitle, } from "@pantheon-systems/pcc-react-sdk/components"; +import { Metadata } from "next"; +import Image from "next/image"; +import Link from "next/link"; import React from "react"; +import { getSeoMetadata } from "../lib/utils"; import { clientSmartComponentMap } from "./smart-components/client-components"; const ELEMENT_STYLES_TO_OVERRIDE = [ @@ -17,113 +21,108 @@ const ELEMENT_STYLES_TO_OVERRIDE = [ /lineHeight/, /height/, ]; + const overrideElementStyles = (tag: keyof HTMLElementTagNameMap) => { function resultFunc({ children, id, style, ...attrs }: any) { const newStyles = { ...style }; + ELEMENT_STYLES_TO_OVERRIDE.forEach((s) => { Object.keys(newStyles).forEach((key) => { if (s.test(key)) delete newStyles[key]; }); }); + return React.createElement( tag, { id, style: newStyles, ...attrs }, children, ); } + return resultFunc; }; +const componentOverrideMap = { + h1: overrideElementStyles("h1"), + h2: overrideElementStyles("h2"), + h3: overrideElementStyles("h3"), + h4: overrideElementStyles("h4"), + h5: overrideElementStyles("h5"), + h6: overrideElementStyles("h6"), + p: overrideElementStyles("p"), + span: overrideElementStyles("span"), +}; + type ArticleViewProps = { article: Article; onlyContent?: boolean; }; -export default function ArticleView({ +const ArticleHeader = ({ article, - onlyContent, -}: ArticleViewProps) { - const { data } = useArticle( - article.id, - { - publishingLevel: article.publishingLevel, - contentType: "TREE_PANTHEON_V2", - }, - { - skip: article.publishingLevel !== "REALTIME", - }, - ); - - const hydratedArticle = data?.article ?? article; - const title = useArticleTitle(hydratedArticle); - + articleTitle, + seoMetadata, +}: { + article: Article; + articleTitle: string; + seoMetadata: Metadata; +}) => { return ( - <> -
-

{title}

+
+
{articleTitle}
+
+ {seoMetadata.authors?.[0]?.name ? ( + <> +
+ +
+ {`Avatar +
+
+ {seoMetadata.authors?.[0]?.name} +
+ +
+
 
+ + ) : null} {article.updatedAt ? ( -

+ {new Date(article.updatedAt).toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric", })} -

+ ) : null}
- - +
); -} +}; export function StaticArticleView({ article, onlyContent }: ArticleViewProps) { const articleTitle = useArticleTitle(article); + const seoMetadata = getSeoMetadata(article); return ( <> -
-
{articleTitle}
- - {article.updatedAt ? ( -

- {new Date(article.updatedAt).toLocaleDateString("en-US", { - year: "numeric", - month: "long", - day: "numeric", - })} -

- ) : null} -
+ + +
+ {seoMetadata.keywords != null + ? (Array.isArray(seoMetadata.keywords) + ? seoMetadata.keywords + : [seoMetadata.keywords] + ).map((x, i) => ( +
+ {x} +
+ )) + : null} +
); } + +export default function ArticleView({ + article, + onlyContent, +}: ArticleViewProps) { + const { data } = useArticle( + article.id, + { + publishingLevel: article.publishingLevel, + contentType: "TREE_PANTHEON_V2", + }, + { + skip: article.publishingLevel !== "REALTIME", + }, + ); + + const hydratedArticle = data?.article ?? article; + + return ( + + ); +} diff --git a/starters/nextjs-starter-approuter-ts/package.json b/starters/nextjs-starter-approuter-ts/package.json index 9938e16a..13a4b53e 100644 --- a/starters/nextjs-starter-approuter-ts/package.json +++ b/starters/nextjs-starter-approuter-ts/package.json @@ -39,6 +39,7 @@ "query-string": "^8.2.0", "react": "18.3.1", "react-dom": "18.3.1", + "react-icons": "^5.4.0", "react-loading-skeleton": "^3.4.0", "react-markdown": "^8.0.7", "react-remove-scroll": "^2.5.10", diff --git a/starters/nextjs-starter-approuter-ts/public/images/no-avatar.png b/starters/nextjs-starter-approuter-ts/public/images/no-avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..ef404ce2a228ca1aaca185f8f8c4bba33edcf320 GIT binary patch literal 25813 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 { + return ( +
+
{articleTitle}
+
+ {seoMetadata.openGraph.article.authors?.[0] ? ( + <> + +
+ {`Avatar +
+
+ {seoMetadata.openGraph.article.authors?.[0]} +
+ +
 
+ + ) : null} + {article.updatedAt ? ( + + {new Date(article.updatedAt).toLocaleDateString("en-US", { + year: "numeric", + month: "long", + day: "numeric", + })} + + ) : null} +
+
+ ); +}; + export default function ArticleView({ article, onlyContent, @@ -64,22 +108,15 @@ export default function ArticleView({ export function StaticArticleView({ article, onlyContent }: ArticleViewProps) { const articleTitle = useArticleTitle(article); + const seoMetadata = getSeoMetadata(article); return ( <> -
-
{articleTitle}
- - {article.updatedAt ? ( -

- {new Date(article.updatedAt).toLocaleDateString("en-US", { - year: "numeric", - month: "long", - day: "numeric", - })} -

- ) : null} -
+ + +
+ {seoMetadata.openGraph.article.tags?.length > 0 + ? seoMetadata.openGraph.article.tags.map((x, i) => ( +
+ {x} +
+ )) + : null} +
); } diff --git a/starters/nextjs-starter-ts/hooks/usePagination.ts b/starters/nextjs-starter-ts/hooks/usePagination.ts index d619a36d..02397bfc 100644 --- a/starters/nextjs-starter-ts/hooks/usePagination.ts +++ b/starters/nextjs-starter-ts/hooks/usePagination.ts @@ -2,6 +2,7 @@ import { ArticleWithoutContent, PaginatedArticle, } from "@pantheon-systems/pcc-react-sdk"; +import queryString from "query-string"; import { useCallback, useEffect, useState } from "react"; import useSWR from "swr"; @@ -9,9 +10,15 @@ interface Props { cursor?: string; pageSize: number; initialArticles?: PaginatedArticle[] | ArticleWithoutContent[]; + author?: string; } -export function usePagination({ cursor, initialArticles, pageSize }: Props) { +export function usePagination({ + cursor, + initialArticles, + pageSize, + author, +}: Props) { const [articlePages, setArticlePages] = useState( initialArticles ? [initialArticles] : [], ); @@ -23,12 +30,19 @@ export function usePagination({ cursor, initialArticles, pageSize }: Props) { const pageNumber = Number(key); if (articlePages[pageNumber]) return null; - const response = await fetch( - `/api/utils/paginate?pageSize=${pageSize}&cursor=${currentCursor}`, - ); + const url = queryString.stringifyUrl({ + url: "/api/utils/paginate", + query: { + pageSize, + cursor: currentCursor, + author, + }, + }); + + const response = await fetch(url); return await response.json(); }, - [currentCursor, pageSize, articlePages], + [currentCursor, pageSize, articlePages, author], ); const { data: newResponse, isLoading } = useSWR( diff --git a/starters/nextjs-starter-ts/next-env.d.ts b/starters/nextjs-starter-ts/next-env.d.ts index 4f11a03d..a4a7b3f5 100644 --- a/starters/nextjs-starter-ts/next-env.d.ts +++ b/starters/nextjs-starter-ts/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. diff --git a/starters/nextjs-starter-ts/package.json b/starters/nextjs-starter-ts/package.json index 5ee37377..ccf5e2ca 100644 --- a/starters/nextjs-starter-ts/package.json +++ b/starters/nextjs-starter-ts/package.json @@ -34,6 +34,7 @@ "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "dotenv": "^16.4.5", + "react-icons": "^5.4.0", "markdown-to-txt": "^2.0.1", "next": "^14.2.10", "next-seo": "^5.15.0", diff --git a/starters/nextjs-starter-ts/pages/api/utils/paginate.ts b/starters/nextjs-starter-ts/pages/api/utils/paginate.ts index a3b06b99..0993d310 100644 --- a/starters/nextjs-starter-ts/pages/api/utils/paginate.ts +++ b/starters/nextjs-starter-ts/pages/api/utils/paginate.ts @@ -16,6 +16,10 @@ export default async function handler( return res.status(400).json("Invalid pageSize"); } + let author: string; + if (Array.isArray(req.query.author)) author = req.query.author[0]; + else author = req.query.author; + if (!pageSize || !cursor) return res.status(400).json("Invalid pageSize or cursor"); @@ -23,6 +27,7 @@ export default async function handler( await PCCConvenienceFunctions.getPaginatedArticles({ pageSize, ...(cursor && { cursor }), + ...(author && { metadataFilters: { author } }), }); return res.status(200).json({ data, newCursor }); diff --git a/starters/nextjs-starter-ts/pages/authors/[author].tsx b/starters/nextjs-starter-ts/pages/authors/[author].tsx new file mode 100644 index 00000000..4a470c4b --- /dev/null +++ b/starters/nextjs-starter-ts/pages/authors/[author].tsx @@ -0,0 +1,113 @@ +import { + ArticleWithoutContent, + PCCConvenienceFunctions, +} from "@pantheon-systems/pcc-react-sdk"; +import { NextSeo } from "next-seo"; +import Image from "next/image"; +import { + FaFacebookSquare, + FaInstagramSquare, + FaLinkedin, +} from "react-icons/fa"; +import { FaSquareXTwitter } from "react-icons/fa6"; +import { MdEmail } from "react-icons/md"; +import { PiMediumLogoFill } from "react-icons/pi"; +import { ArticleGrid } from "../../components/grid"; +import Layout from "../../components/layout"; +import Pagination from "../../components/pagination"; +import { usePagination } from "../../hooks/usePagination"; + +const PAGE_SIZE = 20; + +export default function ArticlesListTemplate({ + articles, + totalCount, + cursor, + author, +}) { + const { + data: currentArticles, + onPageChange, + fetching, + currentPage, + } = usePagination({ + cursor, + initialArticles: articles, + pageSize: PAGE_SIZE, + author, + }); + + return ( + + + +
+
+
+
+ {`Avatar +
+
+

{author}

+
A short line about the author
+
+
+
+ + + + + + +
+
+ {author} is a passionate content writer with a flair for turning + ideas into engaging stories. When she’s not writing, Jane enjoys + cozy afternoons with a good book, exploring new coffee spots, and + finding inspiration in everyday moments. +
+
+ + + +
+ +
+
+
+ ); +} + +export async function getServerSideProps({ query: { author } }) { + const { + data: articles, + totalCount, + cursor, + } = await PCCConvenienceFunctions.getPaginatedArticles({ + pageSize: PAGE_SIZE, + metadataFilters: { + author, + }, + }); + + return { + props: { + articles, + cursor, + totalCount, + author, + }, + }; +} diff --git a/starters/nextjs-starter-ts/public/images/no-avatar.png b/starters/nextjs-starter-ts/public/images/no-avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..ef404ce2a228ca1aaca185f8f8c4bba33edcf320 GIT binary patch literal 25813 zcmV)PK()V#P){}yC7-Zj*2oY_@%wQ~oF@s8*q{4|L2_)So1bXIuQHE|sl$gLezRIE%k z{NrD8zn2`Bm&QT2^F(=lH2QIr+fk-RhX#9~d>;S;CH6ZOe#hJ-E*Aiz1YN%?c0QLB zC(TV1C-G6vl5!G{orZD|%KFg>DI%25O5?(>>u*R|#N(iOq#=|k>0%zbCrR3uof#tO zdb0HVbWVy;$~h?8apKtM8uA5{7ksUMUfOBW2Ksq<*jn1#+A^(}mW=2`HYb6R#$hK) zcl}>WdRJdb{|ErGXl>1RIAUS?*BC}RVF3xq0y1TPJVb?PkSe4N89-)`6~uy^Aunht6bwZ`QBW)-fW%N1v>nQailK6-8mfbShR#D* zpqo%H^avV;CZNBdk1zsLU^=V`8^Q}=7VHN5!=dmRI2KNYH^4dY9=HsyfltEC@D=zr z`~a4~FX3qfAY?=d(LtC93-Le#kw_#45h9zBJfsw;v#VIxQ)01+#y^Ot{vBl8^KNE@px6d8QuvWh-c$P_+0!! z{7L*}d>?)k|DHf5XcMdm-h@bkfRIfnCDaox5&8&Ygju2-(SYbc3?y=i>xqTLT4EdV z4snz?OOhuUk(@}Oqd{bd5AbdP63Yb;!+D)lM#y$nspT*gm^E3-wWLZ(@!Pv(^@ zQPx1#O?Iv92H8^CGqQJNC*_E8hH@TqY`M*H6>{h02IQvYY4Voxf$~Z61@iUsH|56_ z@Ct?sUJ6`=9EGC_R~1HR2u+XXLF3T2(`sqgXrpu--H7f-kEiF;f1>x$rxXH5s9;kd& zWvF_oCaCUJZBc!qhEX$BTdtO&c3AD2+N3&N-BF#Ro~M3V{jmnDVX6_Vu~FlwMz_Ya zrk19UW{T!P&8wP|T1r~3TJc&XT9>pYv}xMT+I;O2?aSIP7>W!xMk1q((aD(7(a`bL z5$jaz^ytj$8tJak&DL$weWFLwW9h}{mFRWoP3ddv2k2+%H|Re$AR4d?;tUQLbQ#PT z8X1Ng?lf#M95+%i@-y0C)L=AZOf_~fPBpGEzHfpvVVNYD95T6U3Y*%P#+g=_-Z6vC zY|Z#)hs=5xU>Ddg5G<%!Fu zi&~38O9jg%mf4nVmVa59T5+r@tnOP=t-YK@gM+Pu$lq&1jl;E@x?}q zd5dcok2vW%v7M@&B+d-yDCZ;25*Hm8wo8r6Ggm!VuIn+^F*g&pc(;>ouiP!%h3@Cv zXFMD{HhHvrBAz~;d7eF93SKL`%DtX?>w3p}H+WC^*!XPpY4^qY`upzn9q`liO1UuxUovJD!=OE5&n^f)jrkDHHI~%M{!5fk3O#r ztL^%c^<&*JwPX3mJ|7nxmz)Sb(OG9#S68o5U)TUQh#MwOu0DD9C(oZ+8<~yOO-fDq zr@$%ksTV&-{oH@r|8&P0)|tk$24^eJ(az;HL(S`(r&{7#B&`vxz2}#l?`U&uJNJwE zFUK$FT&TFHc(L#j=~B+6xyu_aPq(MEPhN?=GSacGWAN(AtM@yXclKQKzjoug_w}n? zZe5peINi8#)8Xd%TdZ3xw{34XciVKI`_<;xb3L{_&3EkXwBEJ9+t$0d_fnrr-<5lw z_paafyMOz^vIo8WEBYS}tR9d&( zTgk;?&*AQ8Al;T?jQ1h zRK7BPb@or!Kf9+^PK~}6zMlK5;En2=<8K$e?U)Xle)=xy-Rw->d)4+8&{$GaXlIG^V^Csq~En$4~C7!$(wm4D5kQx?`%8I0HE^tTMSju*T+|{HZKVLyWsEg4x^(M9Xr3pl4}59O#^@wrSW6u zV;;ewjPLru4Cck~gggOy)G$6TgD;3h&oAKeMf_v|gD+tGqfP()$^WTub$;{AB3`Cw zzRu*7^+JAZoQUBk5b=ZpwzML4;{5Fhr8TA{3q^c!(gKE+g@ru;X))GT^IJg_)H`E; zo11%M2mrnWfX{_0Dy!5 z0Qvv`0D$NK0Cg|`0P0`>06Lfe02gqax=}m;000JJOGiWi{{a60|De66lK=n!32;bR za{vGp-~a#>-~o+PEI0rF00(qQO+^Rj3>y*^FnZ;$b^ria>`6pHRCwBr{nxLgS&}D+ znKC?tg^zqA0fJmC zmINQj;S76sx_eqwcj>H385tRIBd&1qiKEQ;@VWc-dn2+z&qPFA_v`N8XUC3-pV|2t z-utiqR|tRzj0gY#V381!01$x?5l{gD6aYlwrS}5hwl9GKAOHYPt!a$)l3xv;5DDO@ za0qze{r#!}fNSp=(Gmp_0Z`SXGQOPvCf14SI>w|5pbD5&0YE_!kN_35VV+uRhzS8f z0e4pnfQYJk@WibL-uZj`P#tgJ=4ajiA^}?F&%r4Mn4aq0ag#M&5x^n4hW zIT-|1Fo-2V5XcGu>WB&=LpWZ)8D)h#5gQ^)Gzt-LD@0KpZ=+8ssTxFsWC#gRK(ner zs@O2$+NY%I5CBjWqDmA|P*osAL)%+L-LDX+0uuq~kTW4zL`G7DUb5&;I=3ZqD6>(- zZt%mp(5_?!WxF{Us)vMPX%-=9PfKok*l zTv*gwVv8b41Q1jqs3;uV@~wZ}Qp-a{-mCLo^tTsat2N`_I?8>!;&Ax(aSs6i-AEc$ zWqe5$Mo|EufTo+TPz2QN$KCo~RX_l<|8PTC88%Fe$ar%FfJlHDG>ddOTf%~sdZ4CRln4|-R29ZQQ4|$q{2bZo48no_ z90=%8+~dDTDUa_Mby*Mhfr7rt&gdu=00dyf@$Gx*jh~r8#~q&)M(qaGTN<#{<=xsL zjLQauXo(tQOT*ijcY40F!%B!mt^H$2LqNu8?;Jch15+NEQLK4+1N`!_;R5mFoKvo!+ngFtDja0J{)zXk5 zX2h(D03|?H0RW!`02r}L$r5H21O){`%%GqkqgT2u)BO*7RT!nbQ_{VKM+6*YcgJvV z#l81U`%l}i2OtsNF)FGms;YprHHmuzIEs5~qY>zqTL1(!Gz$OL*1Pc{swk>4=gSbr zm0&~$RMpXG7$idUIS)BA5(6lx>>|P;=OO3HFac%}Ae7zRMo~*-5CH)J9g!g#wMJDH zAV^-P1bSeX@0bxi(9oT8+gfDUdbGV&*~|A}o9e+5f$sb^>_P>CTRJ!1a^9I^1V}2o z=xMY|q@(3fz?~7)gQ#Pt=X*PYu)9des;Y7s{2;=BG`fhJRZ&7@#6G2joAUwy5t2ww+wUF)>T^m8sxZdvK1D`kr15?UkpTsCRQX+01~=M@I|H~?%$-Rd zeUaXBn0pU-<0tVZygrOTc9wIiwl~IC6%lpZ%wxTWTzuzw4|eI zfQ&yv+OLEj>h5?m2V3tT@>PKC_3ia^EAD-W_S&C&p{wfNIqidMyroYtidbPAc#h$C z+I`n{+u^A7h}%m&@Yn!mA0*sKkrYr=MdiYWtfTFg@!R#_cNtL>yktWJDUXTJnBCzv zqEb+}3Vxju0FF`~!?mrS1jq;B5${aFCU{I#HpqEHI{tcgbJvF47@kpBTWM{BHc$n~D&wzbT}{kXfa zG5N;3myWNY7l`}ZYa5^7KaiK-dH%+9;MR-cO$>5lbZ)|RP|~l`0PO-Jz}sOz?05BT!QIIh^lm;42NB!r0pcC2vJ(St(X`vnckc{GZOEWmZ^w2A zzT_Y*+Fl{)Ud?uHT~!fu9pY7t2wOjUM?Gj4mf-FRc27duso*Y-z4@Q_iwU@mpLW+s zfCj;A?IZAQ{0I+%JG{|y*k{&zgK)?D!Pnq(eYE&jQaw2nJkFG7%Q*mBFi95|VqJ5?M5vaNv+B6+*fP!WC374s(NC^F_m zdSm6cp%sA=AR`cH-tG*&>;K+x9g5qe7fD9o$0$3-rNL8s-T2~ z09iy16+&U}84+LGd59*70zy*BqK3wA(oIag2yTIk@%mJDMn-qre~b|JZj=CU1b}wB zDGH9Tms}7(Da%3fGQ?5SMIi$cLIBOX{YZfO)uNrxxdjZ|hHef*w$VTux>o2zh+gco8K;g&;zb$HlmgQ2=Of zWp;6@-hd=GVbCr*)X}bGkxoXm8!V!#7Hmr9(y$d`z#->BL_rM#Bifw{J50t#Q6<$w zDB>oS!0qSb{=EoW5hF$=RoFw(s(_#dw~D+&l~E5f%B_@dghNRCUAv3xw@~T0Dsh{C z?{Gl8g~_~DVo*bfs*qIsl!lxcM*}1VF{_N$^Csm2kR4n&rWoVZ7{sLNbo6N&6=+my z003k}$2?wS$;J>>BWQ3Fk>i-%3aA|THv$!fTY%c`HAX-r-MgTzokmr9+xQ<$hfeH| zHk3piidTA(O+;WOh68cmL|P~~W@_Wcy1C~Y8$HGdJ2*S5BD{_W+>Va6HVPHg%#0y~ zG500J5&Ao^E{J%MK_rYzcaTTyRX}CyALwvnBl4Im;dc8YfXLQ}Dkvc^k^+c|sAk!2 zIKl&jaYWkTmV%5?JR>4;Mlzr?l#08lJx#Hh44Ckl#V%ClF`F}{K=xTxD4VhfN0>Mh70XzQVOrUMV`_BK((5gi@x z6B&sSEP#Sq(NblinpE4IdlA`s-WyGj?Mg#ZwY#8mTzT5rN!*qyb~YDa+_Z84>TLJE zARukQegrq=H3c#vo+b7}qZnokQ;I9C*gFlR65Y*`=@v#~|x zhX9{`{_5rR>Dig@*Ds%aas0%dmc>7R82@lKyz22)v?)bQ!?RHQ%vV=n1yuk6z}}Rq zZ?^B&?E?^E6v?;hIOAe$0hU|H*A~4+lSL6>EF_KL<1RB*#4!dyCa_A4F`E>#sHlQ$ zp(0g{lJ{<(c0$KpiDVC6j&gT~4DAt<8*i=vSu~2aDRn6$A}V;%K@vQ+y1UACkMqi3bw|&Lf}WbR)!?#%-(sOgo=OP_bD{9O2U>!bAWNMGkG~O-KS@Xe^!R&X*}8TH4z1 zu~3i&7?l8sw1iAXL)vP15I8gX*yInY{=`Jb0$7NuAvCCn;EdT`8K^M^lr$$Lg9>EK z2fzNku8%+ckN>gldM5Mv#~&5V^!Vr~_UpbMa`ZW6u9`jx#PunzNmNz739!N0m+|D4 z%vW4^BrlMF1L&Y=01$PI2=;ZaF(cpR+I7I7xjn;NjvHUb4@ zM1z=A7*SL$g6zDO9>%tZRz)F;0&kOH!z{=EWKkXBF{QVxpHnO`ljI48+OlEFS%Hd- zhEVg+W%XH8O1X5VD2tPOC(Oo{g|S7>Q57VolyhNi&RL{qwn&DZ`Q~@N^X&7_fBw_I zucwQ4a~*&5qu=@M-;sXPFE0^6a?0(xsOKT&K4t+4G58@`vwX-e9#NT#iP%{*Wozg; zn8#IKiroNTMZ1HS{ZKltF+byo!qVI@GFyR=kXHY|w zb(?PJJ^;K0CIBKV3TK#>J~m*c#BaO&R_Tu&AKPHVbp>8PV+a{kfl*nLB3fh6%}z7$ zu+Hie_lta*UB|<=BLnQGu9}z&iGfy^Tv(TuiI_MDja`t}4ZpE10}2 z@xLeiiw*~d;#Nfh4if*J=Nj=|{>|_2tmrmO&Z?p#Xrd!3KSsE)EmJ8WCJ{oa4f~we zX`AL0#6fis8KEUctPKO8V`CH^LHehs_8*_(Zw3#10 ze)ofqe)`j^iz{YqH=BE>_fi-nhL{o%7WD)Ga!PD$h}nmTpjidj2pJz^674gjEGi!l4{m{ZD?yNvT7WkS2#qu zvO;4G6Ad}HDUH%8iIQr+6Li5;v3hnQ1XzhsQnbmGdw87GpX?+G*vo9qWkso$&s z#5$K_+D1Mi%$#$~S>`7v4<0}H=%*jGn{MzeAg>Jh>|L6jp)I7}U}`0`Xb6>5q#rh_ zIR(GEzHZm6zFiOPx?OjxtIIHS{dzTYT?&Il&&Ggi3i0gzgZcdECqMeJf;b1$`Ekyv zU;?BpDT4yrYBEVFU0<(MNdQG4rCir_Q4}JQq96RG4C_c*d`OCiTy&t+w7luCN zxs4YS08<}IGP?E9Y=wj0ss&jL}QCeRj1Qw?}JYXR1rZ`VvJQ; z5;G#D1SzEuhTeA}4j>v+oZ;|@@+ZMv0#%3xkq){x_J|eV``v%E)$|?8We`iIsWDSy zYc`fh5rb-0u!xpu>f8twu48CZ+DFPYGa&RiA@Cp5=707+-J6%|s~2h5Jb(7(a=n=? zj{4Ply}AY}XMxRgMustt(wQH_efoo^mzGMI%g*l60%?;#t4BLgo>FHO{D{ zp>4^!dU20T*)3OH*Sp!Nt7qkO5qwZ8XNyx%jZubfm7{l)*^_U)|M{n%fBD51W$l`J z5@X6K0RS;EbIz&?v*~2D>4p%jbxa0;5LG0FnA%~8DS5w1DaM>qPN=Z%`+GM2_T2t5 zHEV@x>=3;H0(WWpD#SL#J|>?fi|7_Hfuul)wc!(2JgLgJtNKA%oR;ORa9j9Fq)q7% zR2hT64)}5I|73DuD6Fn7ug;&ZudiQTu9lm=U9Y>%I(RRVs%m0g5jx+lHsc1D9FPvitI-|MX>`)9>8- z@DJt>Kk$8j{>d+lT)#BO*RHJF~_zF#;N6h{zbH zqA7-$LX1&WC2P*injmFrRp#TX9f&U0D|3&qDZgJgi`t|1W`DZ>PE{~tQ|KZTCeb+J@5k(@lCTRwt zvYxWBL)S@4?3{=QDCHklOXDA(5y#d+QtL=a+x~qaS_o z?A3a?Jik~XQC0B!-}vBrzxAEB-+gOx@_6;?>6f4U@|}0y`rh}y{}+GxAFHZ){P2EI zMNKJ2;|d}J3@N0^q&_`4zPz|L##mzjA?IYRDa&%`Hc=_WWQ{|Bwrv|%%_e5GX)9?g z7PoQ6n<^!r{Lb%>8k$v;Y7hxo`kdR8vuF}YGL}%bvR43~QlE0nl2i~zqyj%{i3`4LQ(?26auIsQP;NDubx-a#o1f$8&`bw^77Ar`0*!StzNA1(+xe} z$oVS$;`1+m_LINsm#-c?e%lfb?X@kcx8Hg4H-G)(>+AN>lQUZu-KIq#5hWrbQV}33 ztD^6Qm;w`v2oYt;l9NdGLmyHSk*1pVy5Ct^7ZxA`T5J0 zcO~)At`)Rw>iNk@S(K<+RMmXGD67&qCN|AtE>svpXc&Q%4Jr~bm5pJ8s+u9hK}0l* zE$no0EGp&fxSr0J7w4~Dt)6%A#o7}WLzEP0?ORaXh&%tcKV&=m)Bp4bO3RB^=ci}) z{@FkOPyf&Vr~mrdv-5Y~drZdUoLyO_7)Nv`#^lQ4{)4m6K6{#TE}WGtsG=fS1lbzN zS+b~B)%4j{FS0!U=7-;X=`riJBk4{92>=?|fw5!z$=KvMHb8i|!S<7CC%~ihZvae< zzy;`^()n-0v*mE@oSRK*L=M9+g#7a5%gbxY%*^VnacquGPG*aF7GcJsDC(vztAZGq z2{B_HAbLV%8mn6b0M=Rn5zR?bN}^e^5lh6bSUh;Ao}a9)FM97^T&^TW4(?VJDT4}SNDfBV;`r?bW4Xt}%| z8%R|Jh^;Z3O*fm(=8L22tE;LmbBqd56vYsus1P9_`PdU$KxAt!F3-=W_q;-dFdlI@ zY^#)Aoo{??S3ub}E~x@2?J5q8V|&h6E>i~eK=&a1PwBJYr>_!ZGR1sxWSsMT?}uTv zUIK!TfX2)xwKH^bcHA^|78rUTvT#ujeJ430fJ(@|Pu;Z)SGnJ$ehqOTi69A)kN|<5 zD;bduv$aLt)U(rSex_vVX0}>)&#$_&tVE?cKBao{?)QH1%|HClzw!J3hO>pQrb%kTa6nEnaud++|Cz7yRwx%Ft?m-b)!U!3Z7 zBm$ALtU%TGZM(is0)6B#w97V@)A}2aPtHz`in6-CynOlUl>ietKqg~BM6zdue!cd6 zr-)q6feS(+BqfFzHeY_!U4A7Xh-jUunyD!&MT5*frfx`o`FEfE_~Y{-$nw=I0BpT- zQBIvY@$0MSMPZ)2^+e1hXZg+tZ-FFhi>h?%P5bQ2uO2)+6A=}Ol9{Ne>XbxOQ%Yq~ zu(4g&BLWf;fMwGSZAwA1T33~>C`+4C%Gn=HkA8`>ta<~S?##3Rm?*kKo`Gj+YIsI>Y^^|2ag`aS2ZJ{|?b|HBrG{&UfTUQj-WHMb) zQ4TRC)wT_veD>8(e))w@5JJ3s`P`V7T`;k|e(&s0r-iMX2^)(VzkG4wjQ$I*D<1lO zBiX(8?%N-K^wHoWS!&lkBDQ^tY}ghef=Dr?rmB_(VoD6+W3Q@<+0m7xF0}y4)`5h# z-aebw)0{V_3{N9C+?rO{f%^!^5A`t_t#RE&%Ro{yc%-3XtPoQ%bI! zD6xpPo3?LbIlJeYIhm5I10)T-U%nWYFBx#UI4R27I#<*ayLjY%T3%g$^s7&wJ-=jY z*-d)y3DFr<@0TyW`te`=S=VmLdYV$6FDCaV?!knciu&~`rg(I;`1q4A0N}y>)3)sZ zbS!?00I@|t=Nu7<GzTtB5g{h(ZiG zddnun7={)=5eQMn76dl--h+Gd`O)8Y#jB)d-y4nl&S5p?puV?te~N;->qyZN9YKHr z%sbls55mtE*j^^_eK6Ka_Wdv@Ky8^2Q%FfLXQ@mjc{!O4qvvp&NiW#RRJ$iIj%}zi6_>0Ei z;^DE1uDWI6N-f~4pZ)C%g6X7~74E&``cHoE*N*11%k!swH_RusbC%f6CyU8+F@$7{ z3BHffTXuylkyu69+7u%Z88+6~EXg?|>Qc^-fypv51JzAMrpP%}baQO*Ry#I=F@(EL zmTkpacimFs`KkzbhUxqA@;Aa4LHhvgeV3DRVKqofY3TcDxnS!;3V}gGfB(Pz_kaEQZ+_VJiH^^PiY4^&*3n~I zPTAH#Cg!A~8dDafa?+eW!Q7*G;|jKxY;p4N;rilLZRy+J{g!04i{tsUT&-8@_4?(- z6_5kavy*wv@L*9*n>wXXO{S0EdR!N#YHC$<&fLHMfS9vL&cbK_AxTywP>rdVY^^P< zv)F?n9Qp{V%t&Y?rlKfRW$5~5HqDevL%M6AMm#)k35Jojy^Uil-~MRP78<2L<;(Bs zGn>}yVNsa_^$_~4t@ zPk(iFb*;#hWitCtJ(~+a%2_qYY0Oyw(feWb#m8k?S54DQt8RVy_?>Ts zn9HW>3+x!1rbN(ovtdRQnLT)`m`wBL3L#Hs)6j2HiYbY6I-5&eAy0=q9+nXm{hJ0 zqNox&<4n7`diJZIxCbX9IJ_JfZ@%a|D?hR|L;AJ(r7 zf-MUbT`w4T#7=WmRf$7vm#(a{ zh)ADvo=hgjau|e|Rn;2Tg<))*$Py*TVd#u0vPg;n#~6^gt{Wt@*5;HXX8_Eio#5BC zU>i#e`-67-Q#1&*z#rLHAVbU&QtpS?58kk0N5BNk1PF*kV6E96cP7p`v9&4yIr)&h zM}<7HEQqnw8FoW7hWaiLQN^~sys8`%*^{GrQC8LQshUDSb4m)FbL_p(AzBEjT|(}e zs46E+3Zw#puDpKr${IX5J30UAi)OYUYjg0;Y+)D2X(-rLfJDswH+I4{dpPWukD?OeSM~ms%y$92>T+ENj)m&7APkqc@ zGzx^ITu#xHDW&Dr%BO56(-2d8y&UZnAuca2e29y)v(?Kl9YfVLIYn!jkxbP9fWLaF z*)tIvO1|s6P0G@4Hq6E~4Q;dQU5BfRs>Toik(r4Y5mjRho{*8)*+LcSW>PnkqAbg* znjM`w%NcnsMDRL-0jj!lhHz8#h$8c^Fa_DauJ2hIZYRRhd=TnDy22;rs6ooAv7D^Tqv#Zhjp4 zE+=mhUESo(C0N6jopH&xoSguaRf9;7B?B63V+=%wiJ8rKEZcXjEh-&55tw1e6vGBd z3;>j6g^1QVB`Tb`mSUavC(jNr(h-U}==s>5G*86u%Tg%Nfc03*w`2|7p`^| z1*|c~+0ne`oY5e&iGBc;lvCE^3R_p!k~$3Ec-TC>id38V(ZqMrFW1NK-2d={_l~BG z0%9KG;7w7JD+EA;Zr%^Pk#CHm#DKMiKRTPe`_{eE07#t7W;tjI-quY~Pkgt&`10d+v+9PBGb}g$&Rx&6qJ}XXXZMy%aQ<9whhoXhqe%a=fC~CStP57j_gN3po1w? z`M7^+%Tfha%k@YAlwu@iLuO=iVkT9^G4dpnHA&8ZBsnPxv0bh<_s>q8Wh6)`lPwBk z8HGuWGleT0V^x(Za`M)Plhb>D`xpP+pa0d5KL7H?%a_+LE;cV;uBWqVGHHsUD$6RX z^qoIBJyxLeSL-jneE$Bs_n$m^kb_4g>x${(Wb8w6Rbz|+%+A${NCsS45uz(9AolGt zh6rSsEh1iCoIiW|%odeKFIkXDRbz}IDw+|2+2ovxqGZE{*%+&$s=~&^m;j-y8iVva zRe!O{`;(bC$p^TasbWI z56&4$fmDrAMXL%q1wk5*d=nc))GSw*FMZ#4-q({kITMFrvtAQ%-Aq=?t1ah;0wSf9 z%DT)Vc^Hba@FDbVXPiZ{#6}gq@)8w_Z2|iBp+f-E7@I_rN|0?r$Vdj!u>QPy=dAM% zU#UV$YAqRK#=J*BEwPIDFfcPP#S~S6$bc#$<(yT-T2jeXU7^l=iaC3qdgjtqjf5e` zftdh#djFmEru`3p{#WbOYQ8uY#WV~>GkN~}ikOPBu4YrW;lS~Q9{}9DKDn0Z`?di8hxnf{%cZbB=M<_ZyX*vyd$) z4GM!X763xu)y-t+hm;Z$F;a>#r`*(yW=%16!{7)1;NfFH-n8q|%|7qY67nv38;?`& zkNlWL;l_5aESgn<$arqRr$9(*UFxDD<}B7C2nazp^dq@g7<$bq=d1upva?P^R4oyv zm{S-~#aL^c&BJCfKb}tVvK`i~kD-r#;PH?^(M-;s{Pbr(`{d)#rjuzu^hjLRb=}nW z@1ONu-w$0gKXQfLtS{lEGB9 z<_rKiOAM=_T@OQtY>Z{!_kG{?eH)Xk*6Z3*Q_oWh#3XBF=ZwiQ_>|NYWmVM(q)C`f zR*|g6*uM9R7FC^m zw^k{QH8J>@qAdzl$T=Be$q5WG(bx!&q@tpzS-e3YWB|%Jrqp?#nr2$ov-20v0M(VH zD;yV2LC;@YsA|me#aGYEvbcA8nlf5zJ@=Br`ue3@T>RaSf4W{?KR!Et=biVCPEW1l zZs=F*b}_4)0+1+YA$IlY!}W_VHTz~#rO=aruoXZ+NICWGy6alD4t)qA48s7Z)>U2G z*@h5J&M653LQVk`H4}_!3xVW}L_YbpAA%o>s>-5mKO~=jtWA$nF^vRZqB^8J(I`l*VK!C6A1tnJgk8GOMZ~BQl=C=bREC z^xn^AjkQfosh-Sz)S@u&f8!hHFJ1)SPpWd{sCf4D%ZrQ4DkKH!eSUR$F%ESwbrE2 zinUxeh*opecAcoANErGUV;DT5#*~<>amCOL!{FJlF%A&tXGef9{4k6sc(bG!LXw0c zRatgj@2Z&}hG%kg;U?nyt1JpIo~yJ(1s4LEvLux~GumM*(>B&d)wO9h>tG7wj0H)8 zq=r!eR8WzWfE;rnI~pfY6wO4GQkD#e5JONE!yJOB;_PVNwHu`3-FM%9`svR{rVvbd z(=KE3HCtf$G`cNuZK*F% z0e~d6le1^fW0wDj>2w;;E>vFvHM^XwDK-h+)tT z8*2+^iLfq;l*NajnoC<~24*{*6vn)|TCQV?^<-Mt&GPEiae|_%$F%mk??3wLMTf+u zX6s64+fDCmQO=Gz_r7a^0N9#(BEyxj1xiK$A|kdS4!-XJNi>8Ih-eu46oa#_>-!Lr zbq-Y9^@?2)Q|kLR25)$zCxx742;O^7Y>h1^v)TZBj*T$Z*div%39rks#W&I#F;NB8Ud?<+7HYs*R{OZ0Kr zbj!;a<7Tt*KIAMs;-c08g7-nGP=T28c%INY7h~9R6(EI}LKu7qqGX&i&LVQm^eHZO z^d&c>j*L_pyQqq@raGz0iL+*hCYZMDw|q!+^nwp zp$CAN(rVMPHJfhGub!RWyZ`%t{3qwHF4mh(1HJg`N@~g}1(vXT4RfR}^*!7*WmWd@N zBw|~nl;%e#M1(*F_2bmMFca3C_oQrx93Tn^=nNN3Bs)e)Jz)A6Px7lGh$LHFHIG8q z2_#VA@kAV1WFjt*7?D5~N46~$VnzUktdda$fj;~4Qo$hG3^e%EbzL`fF-K&|l9|Z& zT~QXxP5h9)6x*gD7w3ERy^RYlYo6Qftv5F!9NXD4+L`hL@SBx8)T zwit$~}T;rgyLOc2ee(?K$0Jo`H4*7f$RG9;s z)AeUfRY(d1N=U?PT*aoyITEvqh)T{G6^SV2A;lhmh!_CAe7P}%g*B3O=(@IDhLA0r zoIRVmoE;a~+$z@rLEw23#MDf-6%P&6p7$pqrm9u=bm={Gk zpHC-~Y1a;m#ZlSJo7pilfMx|Pnps*eL9(r?976QN^QWK35L1rUx?va$8|Q3@`TSyO zjGNAy>+6*Q6;+*M?7Izt#u!wzC@KZ$hk?ie5<4i>S=KRil7$eMpl&AX zRxDiIA$E=_yr)N2KXo?(Dj9v+|N=(UB zr2;T>P7xH#dg5H^2H#@|!I6%2OWMT`e(wi3o|7dsM9ef|Oa!!3a0N1u!qN3F$AY4@j+m{p z%xrAohdyTo%sG2RO4&<_Y^_Q*hC%UKCYL84%$83IQ3?rq^8WvX%zE!^btTd{U0Sywb zyLC#bX{M9eVs`q-D@H-@<77H>HdFs3a^S2~TI#8A!8Qb>7d*Q-?sKBW|5FveQrin2h|F~nB1j2e`l!5j(t z+1YaTcukY*$URL~IDG|^Ps_J|HFI`VC{GEciogl+9LbztyWdA1-{%>90+`0FjV3)xfP0ws1hAscBrR} z2Vj2=;d(lsH+3TQb9X87CudIxyk_!jq|ztkETs1`1P#6P@6ee{FoT%~L$F1qaLBab zQc$&Av3UK5w!umtS@_Ia&Pd4fJWtz3Y7aoGd{V&3XW!GvnR>jt zK9~0RbDryZ7c{ps8uIPUd=0A$Eh^mAbErppSmi3@C3vaDpx*?LNT=%L!iXhxlVFpq zW~&7b-Cxlr-5K@5BpEucrlXUCaM{NQmLX3=lf0vql~#o2d;heG~YQLq$ z$edd#+>;985@1m2p5i31VU1N7Z2bO)kF-i;!`1(V&XcxGSAU{~S1Jn!xf~4AoL^7# z9)GegKy4|-bNcP@G)#RD7jpMIR&eY13VOR(fbMhmkEnbmY55_EA$$fx!k6 znY^`imsfKqWB(@lGJghHazDE4@k`%NU5z^m|N1S*dk*^|t`2GwJWD%+aWB71Pw!70 z&@()mbTh#xn#xNH-p;cfaNCm#>_=B3le#><(Wmip6md2T0fwoRJ4fA zN>T=EI8w^~8VOx)g}0Kv)PXg2V3xhF16^xV|0-NF{T=1|%*oyU_ZbB&uwo#O%2|uw ze2S4TG7r257vwF_)k@Zl{t^GK*fTEVbykc4!=KEbabr`1S~huYThix7%fG2er>d%| zjx6(q2fnjySet+y$B-iFMrUp@}Vp(iON#E1#V?46>=L z=Xz0bEHFzw4$<}O1YdFBsiWJO?(_xs1p}8j`Ydy>Fl2fMHYrWZN>wav~LzB@B7^_zE%F_*JdckV$(60eDotrq#* z&*6gam#LsQy3G0kU)ZttLqUEXW@@nZCpbBgMT{{5g|E|&Sj4ehVmlINj6Z=C5-Rej zFqn7JnRzN#o$3DHFHdpZ7rQRkhhRv~^eo{UoD81k%xVex;6@<%x+Vwk zYt}gQYfl83@$NU7zQ^-uf|1qYXW<<`eQ0>n*tc86`t!Y?lJP`se;;Ll@Dc*}ljYk$ zJTE2DJV}JS#7ng~1rROi4WosrZd&6uLVnHhc7Weh{X@go6{5Q%`AsDcriQR=FxbJ>8q)6OYGcC=KIJ2mJSV;CNHtz#=!9=~*O~x~aOKu^Vuh&*Kl1F9 zuES2g_uT$f6j#2OJBTK=tgP5sy4`=wZ_pzy%I*xMfa6No4TmJCG;rDj0{35WEo`p0 zZ`|=o_8M>haJv)v!__lFiR0S$voMu=kRz(2_RQ1pBnYEP5TFn|#G<5;o6pdC0<(yL8+)Nh9k_tpKdXk|jce>KW5sO?G|UyRz}3nnJ_f`SicH z7ab~^0FuYyzPH^z@B%IW%?&}91>_q#?dMWY=B2YwLZ)cLM|^8}T@@voYr_`aPONDB z&O4dqbkumQVR82jr`UWCE!^C#sv{MxJTixV*eT3jU4*%5zSs{IzquqQa*m?{Q4I(T zvUagxvf4gin~#KJcx;(zA997~`_FQf@C?gGyXO7)a1FhnGY?3@H%4;qp1t{LW7~ig zw;Vaz7#XpwJ;mjpFw#G??coQ@#CSsW_OjAd5m}t_a^F^OER+h=_YoD&r zppfrn5ool8uAcmP1^gf}&_hP%qVJwdDr~xjHO_utgWF65NkShMr=+L%$GARJ7nr3X4-;uCw%MV4iJl^@*V{W)QeIQf#|lmWOtf4(uoDZvm9>menQ3>g0WYL5k_wX$ z)fXjJD^-hDB0W`J9d^2lu76xR(cXUNza#!s&_y?FKKQLzk+TJJHk~@CO(P`_)G=ZY zKlwNRRAA^-Ts$v)f3&^u2fRZDZCI0BDFh`$LmWmOB}*SNbBCRFE}f6zEb^#d!-&tO zPm7(~CEjfGo_P?mHI}JyZHGi9@KBKzXrbE2gzJQOT3bN6!u=hhrJ=}9b1%lB*S0>1 zL>=ZYTF2p^r#|} z8Y?k4rch+3baUNUWJYnhB~az;s5^j0B_)6d84ZVDwRIJV{>^PqDDt0CmU}E8zLV&| zOp9A$hyD!IFv;_*C;ZhJ@l?|+Z_YC>3fFmalP#FO_{x-3U#OZ5UOc@~Y-tDG4xO;% zzI|6X4TfYO0bot4;+i_yV(>6qB3(7Y-TCh&*N?k~9b8)iujf^KS&sG~r?j6$X&D2@ zH|4loXG)*+`o-P*Rd^cv4iV-0-Pfe_Y7K*fuS_j*Hk3&vi#_yZLSz7XF(t36e* zw$!f5p_LMpCI%$)oBs+d)|F~Vu$b9smTX&Tb60RVN&h<*ma#G%1upxswkqWOaWT*d zBBJxSuq*5aELDnKpBzbcEKyXDMruG`6YLrwQ7dLQ=p=CMqSO zFd|QE+=8u()RV!U)BPMnHLp3fE4nW%2$xx5MjB>U;SQn<`#m~1JoSFqO`B!p+@(=QaZSr;yQCBN3AZUW<~Lkl6U!t|$ur0Z zWhPiH)mc+5^+|pD>0HCdMY!`54N5V-%Zk6vXS`{=j*GgOwsIwJy`SI;_(p|F)C=4GJRjH+*_;8Iw@ETdh28JvA2KlIgx zru)ij&*^i%P=V<5I`86@x@IUB7fn^L5dmG7a7bu5`iNP6WJi!Ph)I9s1tderX`$XK z3gye8@l+EYIz_A27Ps2DgB&Rl(o$eRq=}M=>0{*;z*YI_jPB7Xlyh!C zT1tM0RSkqX)CZFkbG-14BsF~{l~OAkh3@}j7(682L!a|~AtTnNIs4VX`xmmCe&yZV zo{gE8oYHHX)So3h8y|6wZ%}E*h%kh)M*&|L-E5!Zk4#W@nO38jr%iA{-ODi;*Zi?>0gcQ>|W0qq;#M-cKmjs_wuMM8`J%CBlZ$q-J0^7BGkHs%I0>n^px>i(~N<2 z4lD_7BJaW3>Y#37@0|OqqhalhBa`=!bMNOb<#I@lPZlB)RQ6)MyhT3Rsc@XaLjC11 zrnqLErI*W!n-#-X;g1Sk60ywgskHqe8b#`6Ok;uT27fvYO;B!whKY5(t@Y>%ng>f> zcu~!qrQKDl$Oy{a8r*x-*VMvAy=UsbYq8U4v&KmG=fb@k(tw&WO>_C`(1!3!hV=Fr zf%*~(1UFGMni-Hs9$4Wzy?@~v_H9DU<+*obi(k^vEGMylyVDbNxJ?~;r6!J2%V_F1 z{Uam$t#pDW&+Rg)P*#S}p}M0Ua)B(r+SZPU%@Q>1N5`?okvVO(a+`x($gd?H7sgju zenucHE%P09w4!h$2w`ijl~H+Lc^5*EkWDAL#FqJ_B5iXgE>Q9Qmh<|ziuz#Fo{CjE zqHkhreJa&oK5i5*w#RS`LI9Iu_oAi;i^R04QYz&5%c;KH%-^#r~E{Bk$LwTC@(C;FxP4X z`e*Z?$U%il!!FMdYx2m-lFe#R$YzG^J5OlxIdXX-`7lL#J5{iknq)!wN02t{GA8cE&VKx*k>i<(|HVD@Id@Ucn0IcM8~5Wh}rzVoj*&hIInyOd5O4 z({DXn>Fzv9oPe#(hANZBj?5AHis;gRE?tzuGJ>@dMvzle7qKnUrPAO(NtMQt(q|>m z2?O8;BfP^l4=hzUcJ(cl?@r1C{!rfbxV-!gn(q?wn1p&OLd1k>uY88_N2z-Ujc188`Nbnof!_wIUD zOprnI4`Rq~-ou#scY>J95z7r;$wGr+#JvZ?yim5nca7^4=A^KraPNevT#;g>_O)c0ow`3353lKV{3L_I>jYS5@t*Yv{_?$!M z6$fKnG;NFT+cxZMW!adu37dn<&=9Wsw#+9Ku-BQY*FKGw2s@v1v1Hj8I@;==%&w}M zJLq<>VwQK2L4&DzvmQ+|6;B7Z(08lB?R6DA(KGuh~gZ_#q#u0?Rb$ZRH4OS zw+3ph#kTiUj3Vh6eT+-9_*+`GYD>^U7KqM)}{-uQYNl_06Yi6Q42h;#&W(n&zKu8=v z=5aGBo=Qq!@?*WoIE)rdPvoasI6QO;JrSY04pdO94&Q8Wa41Eff8T$SSrRo)0b~dp zk9otYZcMm_+4o^$+}>_h?Yd_H}`fAJMK&6*F!3-3Nc)>$*_3df~u zSv687oIpwK5>9Ti57=I}4KK^4gtdPn_V~Rg-=g>(YTQj3)Pr$eRwf==i1fTxusZti zX*tOC&jJV*oF8&pq~8#U`of0O3Y2LG7?$5CfpUbI{d%CU7RP~Iv|w4^PiTBd_AbN@1LIC42@PbIC0DiIE1su z$)HO#6R9OD-iaVqQEq6GF2?$wEqzp$t(b4D zBd4tmT}(UoR`y+O1H?9Spe!ncC={vsyR+GtGoZ(>6Xfbd)XB#5f+8!>iDyva{H|Om$+z+zodf9{G0)58nC+f8KnW-}m}%aIxzR4a38yX109fUS=GG(=P6k33%!{hCIH0?s+@|U=H6kSeM}w91A~?9k zJ(=Q~z!?@6jZXI>fem9zEhFJ`(OFVD_YVL1~E*` zB+1V7HxMRrHU~&{c~t>Nv%+?`P0n5@TvwY348IAMIluYmC)-c8PvX*3^?~$O&U1dj z(C62|FL*3JK1o8Se7cYTd-6h7X)SRG)7NGj4$jsBY*zLs+B>~rHkK|csl=L?R;&D z!9cfB7lfu`Vk^Kr5At@T(5^1Y;tp|HfcjAZP1a=BL!v+c(4w?5cUtMvhF1cL)8eE? z=-jw!%OVn=Yi;DRu;*QO@)lcq_i1G=_9lg@KDC(V##C2km~vbwpN0SWX^;~D{p!@0 zyi%1tncZ4sz^q+^Xn;*(R+q1w{_PzcnAljxP25{a(K6Q50|ghub}u)hU1ee)%PYP* z+sr)GkSb-FVoZRhWJyIb6jm0ou4n>@x#J#g>?VDGUJRwuc&c+38S&eK(om8i?~fr} zYpHs;RNR3;)FoT_E?EH0NR8rmcCV9g(@G?|x&&V{KwX>l3IxRjs@6@3AW$nW8$y&(crHIL< zin&w?y!KL*kV?b4X*xR*Zv<2=g#5x};A!&*Q7QT$k^KG-;@j;iJJt6^Z(mRk z70lifcoGjH(%M&E4RcDdCz4rrTy$0Vgp#{GYzqv0?at5g2w*a?@2@I+Kb=Gd zqNk^e`As==b){fia~ST*F;)*M01Jz8Z+mcpGpeYmv=)5t<;%1?sVi?W!$<*3N z^4RgJ$>Y*m){Prbx%ywpnkwR+v%NG2Zk>U$fP*MsV^AL^V~OjlMli z^NHfm4Dt07xGCxvFGQIL7Sh(%H$?G7frKQfq~-gAcOP4u>e3AHCra>S!SK zCWgD-{ik&Zr|RfOEXs*<4IRq-&6-v;UF3rUK9gbZ5v26-0aF;&K`j`~oVFxKF_Qs@3XIFk+$goP-B}`*EW3XluFT zf+2!%&DDB)ybyH;hTadfXs$psz7>_G9*8r}e8+DQ+qh?jXLMOI_;}YuvrJ7argISL z^)ZeG4Sx`2Ioa|&JganZIShnyR#H|tSx{Pxt106{-J7uvE}x!=sgh51RvnLTSl3Ac zy1+qdv$S13u$4db-nH5^Gl4a>0?A@@jh`vEL z0}=q)lO<+knlDn=NYZy;kf#LXiLxU|R&|?PnvuTvsj0z0Wu{DbnOw$bAF~7}a2CO6 zHN;|s3CMyqtj+Le#>6!Xv71Rd{n_4nU(de6!5bUSm!;K8C^=V9nNZE@Z{%!kGKE0n z!dH6guD=B>rRJAc>-KW8N3iGiTd9(Hhx&k-m=2l^TzhEr7A;@UY8Pl?hbnFwAu49N|6A6MU^WfMCZ=eB?S zt+-N1EwdC!9k{1Zt@>4@#q*w44#&_ZdUUg6{WikYdCJiumx)KnIE7x*GzC;s@;XtH z9ElN5m2PrzIUPn>RCht#7a0f5UvsY_eLf(2Gx^jr`zJ^pDuXB=O+|n7+I3m_Npgf{ zJ?AFWd%}j}RhN^KMTG1~5B2c#=uG~b@;w*Lc`7;|-mF>}k+Wk%OEV>{F=yYYSZ@=GrFx~|@rKTL%1NAJ=Q z3w`+;`Md91qK!zE?8T>I>M+XruIzcCU+zZTy0WJbMc%IIj$lAx8gYNgmq;R*l-dB@ zr9G==j$vT{#bUGw1K%B?RaP^D>Abe8ww%@nBmN4y5Lx6-fdZ!QlcXTIa!9#4qgt9| zrHOHlw`3u!)klQ70ABBs#YtY;!d$3X$x}bfkT{Ium&OnC?K%7TD_Bt3mNm`!wG|)$ zpuv=Y{D}DmM$ET70k?cYk-mc1beqj6p_TODF#ZLe*zQoki{O`=HORx}aS}TF>HsAJ z)uoJYIdgn1wB0RvU*$Xy2riFDP7sN^47H-y-^48Qi^otq7bhWRGN~Z%aDR*3+yE@= z144$!cMaC1{9}v03=z2wJA2#MHxSD}FuC{~XQh7kz8GdCNp*);_}x-{d?P78y&=Rb z>m-Ej>URmdOO;K1XZh`FY>T%aZqZX&kbgr?p5qx15pYVtP*e zwZwCd4U)cM(AEy8>Gp$0gX!!Z0Nx!vPZ{!mjrh zE*(8h0ix|a!_o*pxynDn5q2tDSl9le?0?&Y%L8zcD6o1v8x zxzJriyRgj7^T>AU{clcbk%m%4s-R4{q86K*rtA26 zS7)*^$jJ{J8<#y$f6t6YS2ByXr5*uTM?LMm+Fi!81d~ez3%C6$@Y5^zw>_jlhe9%k z1YiPisWD`+6!)oxvstRTW4o>6xlc;ZblCx|>e;-DuN}orh_$&kE#S>dpX>KQzh1e| z|J!yC@JG4IvO}{2SW!XW4e<6BE?}*oSYf)s=gbrK`(871M2$j?jd{a)DGoaYUh7a- zS-yBfjxhVL67h@y6bYLMlpVFkOe+XJ&jfa(+E_KCGMtlZXIF829n?+3Q))M4_ju=F zo?ZAv@7u%D+ig2rd_(X!Itu7UaYxm;f4Ycgedt5iB&L>t9Ee-)@=A&iA(c}wXdf$O zS)6SOJoTD~Hvi4cXwuLot~2P*j3`sB_al$yj-z`o`k=o)0sE<>FV`uLXjoXEtmh%6 z39x4C>gA>b^Aau3**Ak)$5cWhT%8D%DlMtUgSyyo=BWUz(~Y`?c2Rz3`}zI1IdesH zP@5UDD1a7N7aM(Aj1_Of+XoySMcht~9qlw0s0^RpoZnuYHX8L{kYE>IO=kYLKwi(n zXPKh|eK@i2g5n$%DWZ1G;#RmfWwLqHW9-dW^RdV#eaGJd{>s1IzuY0?kiPr$%IU2z zk8CQB2)N(5H0>!f=$~+6LLRKY?-(wa5s)xY{}n_=XlHHBRm#!XI$NJV4e6(-1l3d< z&#uCcqfbH9-^W=faaAIYb5JR*Il2mN)a+2@d-x2Sfb((q$Hn6v@GV}t*?Tk6bkpzR ziv0^dweC7qIhXCddwbBK!Z~0;lWqFP8cXiq)zcM(UFRqSKKS*(RO{gvn&)w1W%05u zmWwYKHq+L*@+@fQNf%%Ab(AJ|sHR^R9+s|EuKd%YL00!cJPdiVP=-0i=~vU)x(@Yj zHDivFY_xYPOtJFh^*^T-vPAhu;Y-e?N=rp;;oJp3g&g`*fK z%Gp7G$tx+5SWgSQeP5T^!|PZW6A9dN*M0BW+3stkN%!7EcEGWLucqK+?g-g?G2bhH zE9AK!yt+B%n|XL_cQqa%dz-FuHIacViF$-anGU`FE>g+%h>t^cmU50FvKE;`?K-*87#XBLR~8{0+`OVH9#@=7cRZ%kFZwf!(e~ zmdWEtJ{LBO(Q=KL$7rR%ea(B&sHvYrL;(4X>=nLu4UQnCzE+-{k3z+*Kr^M=Lwzv) z0RMAlVjhSkUWzs_8w9tfPta7;Bq>+9Si_HE<=-9*ii>-kmcxJ6e;X|i!`a>JL=4;x z%0~Rsk|8niV+{l6LGC)AXw<$+c|66ok)+O4aG>@U#pYtY)dM2=*BajN%5R4XN5bVh z>2QrEDUn^_xs*@1j1G>O{P?gS6#7O;1O{o4g|8hCPP8RIO|t>nbVt}HBSgj8G!oFw zqy||a-T5GZ>Zo#U0WYYH2jDwa={4V0b&otfE&ZXb4b@&z0fz#wnUTKn{mQLsXLS{- z>A4b(&aLtBriiOk6{|A4hre*QN~dMRxUi#+n=#rv+^8K%q2e9ofA8E=nG%8W$ON)G zA49e$nWR8fpmxz=?c94mqSd%b+2Jl~wCS#dzi(-uN`3Xt-@8YSw?e)jsP!z+(LT^g z!NK1N{{l!#NJ@)=B*i3U%|UVsk{|_X*#{C53K9|!M_-r!2jJ!7=;r+D{|^w7|2mHc zDE+qs{)!I;2Or;8{%$U=fdGyFeF1g71D*W6?E~F>yzM=K8a|#r{`jYNfRBHm8_Y`- zC@CQ!zalK6hL7{`e{me00v!C^eE-7$0!+2lfx226G9Y;w88JyQ5D@BV@8AIpaIp7u za=Zak>En^I|3l*c*vS)sUk?1g>ouL6?O~pQ!2bgMw?E7uXy$A0-~^>i+ { function resultFunc({ children, id, style, ...attrs }) { const newStyles = { ...style }; + ELEMENT_STYLES_TO_OVERRIDE.forEach((s) => { Object.keys(newStyles).forEach((key) => { if (s.test(key)) delete newStyles[key]; }); }); + return React.createElement( tag, { id, style: newStyles, ...attrs }, children, ); } + return resultFunc; }; -export default function ArticleView({ article, onlyContent }) { - const { data } = useArticle( - article.id, - { - publishingLevel: article.publishingLevel, - contentType: "TREE_PANTHEON_V2", - }, - { - skip: article.publishingLevel !== "REALTIME", - }, - ); - - const hydratedArticle = useMemo( - () => data?.article ?? article, - [data, article], - ); - - return ( - - ); -} - -export function StaticArticleView({ article, onlyContent }) { - const articleTitle = useArticleTitle(article); +const componentOverrideMap = { + h1: overrideElementStyles("h1"), + h2: overrideElementStyles("h2"), + h3: overrideElementStyles("h3"), + h4: overrideElementStyles("h4"), + h5: overrideElementStyles("h5"), + h6: overrideElementStyles("h6"), + p: overrideElementStyles("p"), + span: overrideElementStyles("span"), +}; +const ArticleHeader = ({ article, articleTitle, seoMetadata }) => { return ( - <> -
-
{articleTitle}
- +
+
{articleTitle}
+
+ {seoMetadata.openGraph.article.authors?.[0] ? ( + <> + +
+ {`Avatar +
+
+ {seoMetadata.openGraph.article.authors?.[0]} +
+ +
 
+ + ) : null} {article.updatedAt ? ( -

+ {new Date(article.updatedAt).toLocaleDateString("en-US", { year: "numeric", month: "long", day: "numeric", })} -

+ ) : null}
+
+ ); +}; + +export function StaticArticleView({ article, onlyContent }) { + const articleTitle = useArticleTitle(article); + const seoMetadata = getSeoMetadata(article); + + return ( + <> + + +
+ {seoMetadata.openGraph.article.tags?.length > 0 + ? seoMetadata.openGraph.article.tags.map((x, i) => ( +
+ {x} +
+ )) + : null} +
); } + +export default function ArticleView({ article, onlyContent }) { + const { data } = useArticle( + article.id, + { + publishingLevel: article.publishingLevel, + contentType: "TREE_PANTHEON_V2", + }, + { + skip: article.publishingLevel !== "REALTIME", + }, + ); + + const hydratedArticle = data?.article ?? article; + + return ( + + ); +} diff --git a/starters/nextjs-starter/hooks/usePagination.js b/starters/nextjs-starter/hooks/usePagination.js index 814e7ff6..22a3efb5 100644 --- a/starters/nextjs-starter/hooks/usePagination.js +++ b/starters/nextjs-starter/hooks/usePagination.js @@ -1,7 +1,8 @@ +import queryString from "query-string"; import { useCallback, useEffect, useState } from "react"; import useSWR from "swr"; -export function usePagination({ cursor, initialArticles, pageSize }) { +export function usePagination({ cursor, initialArticles, pageSize, author }) { const [articlePages, setArticlePages] = useState( initialArticles ? [initialArticles] : [], ); @@ -13,12 +14,19 @@ export function usePagination({ cursor, initialArticles, pageSize }) { const pageNumber = Number(key); if (articlePages[pageNumber]) return null; - const response = await fetch( - `/api/utils/paginate?pageSize=${pageSize}&cursor=${currentCursor}`, - ); + const url = queryString.stringifyUrl({ + url: "/api/utils/paginate", + query: { + pageSize, + cursor: currentCursor, + author, + }, + }); + + const response = await fetch(url); return await response.json(); }, - [currentCursor, pageSize, articlePages], + [currentCursor, pageSize, articlePages, author], ); const { data: newResponse, isLoading } = useSWR( diff --git a/starters/nextjs-starter/next-env.d.ts b/starters/nextjs-starter/next-env.d.ts index 4f11a03d..a4a7b3f5 100644 --- a/starters/nextjs-starter/next-env.d.ts +++ b/starters/nextjs-starter/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information. diff --git a/starters/nextjs-starter/package.json b/starters/nextjs-starter/package.json index 4eb7a9af..eef1ff07 100644 --- a/starters/nextjs-starter/package.json +++ b/starters/nextjs-starter/package.json @@ -40,6 +40,7 @@ "query-string": "^8.2.0", "react": "18.3.1", "react-dom": "18.3.1", + "react-icons": "^5.4.0", "react-loading-skeleton": "^3.4.0", "react-markdown": "^8.0.7", "react-remove-scroll": "^2.5.10", diff --git a/starters/nextjs-starter/pages/api/utils/paginate.js b/starters/nextjs-starter/pages/api/utils/paginate.js index 6f497384..442c0500 100644 --- a/starters/nextjs-starter/pages/api/utils/paginate.js +++ b/starters/nextjs-starter/pages/api/utils/paginate.js @@ -12,6 +12,10 @@ export default async function handler(req, res) { return res.status(400).json("Invalid pageSize"); } + let author; + if (Array.isArray(req.query.author)) author = req.query.author[0]; + else author = req.query.author; + if (!pageSize || !cursor) return res.status(400).json("Invalid pageSize or cursor"); @@ -19,6 +23,7 @@ export default async function handler(req, res) { await PCCConvenienceFunctions.getPaginatedArticles({ pageSize, ...(cursor && { cursor }), + ...(author && { metadataFilters: { author } }), }); return res.status(200).json({ data, newCursor }); diff --git a/starters/nextjs-starter/pages/authors/[author].jsx b/starters/nextjs-starter/pages/authors/[author].jsx new file mode 100644 index 00000000..c734afe7 --- /dev/null +++ b/starters/nextjs-starter/pages/authors/[author].jsx @@ -0,0 +1,109 @@ +import { PCCConvenienceFunctions } from "@pantheon-systems/pcc-react-sdk"; +import { NextSeo } from "next-seo"; +import Image from "next/image"; +import { + FaFacebookSquare, + FaInstagramSquare, + FaLinkedin, +} from "react-icons/fa"; +import { FaSquareXTwitter } from "react-icons/fa6"; +import { MdEmail } from "react-icons/md"; +import { PiMediumLogoFill } from "react-icons/pi"; +import { ArticleGrid } from "../../components/grid"; +import Layout from "../../components/layout"; +import Pagination from "../../components/pagination"; +import { usePagination } from "../../hooks/usePagination"; + +const PAGE_SIZE = 20; + +export default function ArticlesListTemplate({ + articles, + totalCount, + cursor, + author, +}) { + const { + data: currentArticles, + onPageChange, + fetching, + currentPage, + } = usePagination({ + cursor, + initialArticles: articles, + pageSize: PAGE_SIZE, + author, + }); + + return ( + + + +
+
+
+
+ {`Avatar +
+
+

{author}

+
A short line about the author
+
+
+
+ + + + + + +
+
+ {author} is a passionate content writer with a flair for turning + ideas into engaging stories. When she’s not writing, Jane enjoys + cozy afternoons with a good book, exploring new coffee spots, and + finding inspiration in everyday moments. +
+
+ + +
+ +
+
+
+ ); +} + +export async function getServerSideProps({ query: { author } }) { + const { + data: articles, + totalCount, + cursor, + } = await PCCConvenienceFunctions.getPaginatedArticles({ + pageSize: PAGE_SIZE, + metadataFilters: { + author, + }, + }); + + return { + props: { + articles, + cursor, + totalCount, + author, + }, + }; +} diff --git a/starters/nextjs-starter/public/images/no-avatar.png b/starters/nextjs-starter/public/images/no-avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..ef404ce2a228ca1aaca185f8f8c4bba33edcf320 GIT binary patch literal 25813 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 Date: Sat, 28 Dec 2024 15:05:54 +0200 Subject: [PATCH 2/3] Add playwright tests for starter kits to check author pages load. --- pnpm-lock.yaml | 99 ++++++++++++++----- .../nextjs-starter-approuter-ts/.gitignore | 6 ++ .../app/authors/[author]/page.tsx | 2 +- .../components/article-view.tsx | 1 + .../nextjs-starter-approuter-ts/next-env.d.ts | 2 +- .../nextjs-starter-approuter-ts/package.json | 4 +- .../playwright.config.ts | 79 +++++++++++++++ .../tests/basic-pages.spec.ts | 17 ++++ starters/nextjs-starter-ts/.gitignore | 6 ++ .../components/article-view.tsx | 1 + starters/nextjs-starter-ts/package.json | 2 + .../pages/authors/[author].tsx | 5 +- .../nextjs-starter-ts/playwright.config.ts | 79 +++++++++++++++ .../tests/basic-pages.spec.ts | 17 ++++ starters/nextjs-starter/.gitignore | 6 ++ .../components/article-view.jsx | 1 + starters/nextjs-starter/package.json | 2 + .../nextjs-starter/pages/authors/[author].jsx | 5 +- starters/nextjs-starter/playwright.config.js | 79 +++++++++++++++ .../nextjs-starter/tests/basic-pages.spec.js | 17 ++++ 20 files changed, 403 insertions(+), 27 deletions(-) create mode 100644 starters/nextjs-starter-approuter-ts/playwright.config.ts create mode 100644 starters/nextjs-starter-approuter-ts/tests/basic-pages.spec.ts create mode 100644 starters/nextjs-starter-ts/playwright.config.ts create mode 100644 starters/nextjs-starter-ts/tests/basic-pages.spec.ts create mode 100644 starters/nextjs-starter/playwright.config.js create mode 100644 starters/nextjs-starter/tests/basic-pages.spec.js diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e01f888d..398e52e2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -89,7 +89,7 @@ importers: version: link:../../packages/react-sample-library next: specifier: ^14.2.10 - version: 14.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) + version: 14.2.10(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) react: specifier: 18.3.1 version: 18.3.1 @@ -340,7 +340,7 @@ importers: version: 8.1.4(@types/react-dom@18.3.0)(@types/react@18.3.3)(encoding@0.1.13)(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@storybook/nextjs': specifier: ^8.1.4 - version: 8.1.4(@jest/globals@29.7.0)(@swc/core@1.4.2(@swc/helpers@0.5.5))(@types/jest@29.5.1)(babel-plugin-macros@3.1.0)(encoding@0.1.13)(esbuild@0.20.2)(jest@29.5.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0))(next@14.2.10(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1)(type-fest@3.13.1)(typescript@5.5.4)(vitest@1.3.1(@types/node@20.11.21)(jsdom@22.1.0)(sass@1.71.1)(terser@5.28.1))(webpack-hot-middleware@2.26.1)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) + version: 8.1.4(@jest/globals@29.7.0)(@swc/core@1.4.2(@swc/helpers@0.5.5))(@types/jest@29.5.1)(babel-plugin-macros@3.1.0)(encoding@0.1.13)(esbuild@0.20.2)(jest@29.5.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0))(next@14.2.10(@babel/core@7.25.2)(@playwright/test@1.49.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1)(type-fest@3.13.1)(typescript@5.5.4)(vitest@1.3.1(@types/node@20.11.21)(jsdom@22.1.0)(sass@1.71.1)(terser@5.28.1))(webpack-hot-middleware@2.26.1)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) '@storybook/react': specifier: ^8.1.4 version: 8.1.4(encoding@0.1.13)(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.4) @@ -464,7 +464,7 @@ importers: version: 29.5.0(@types/node@20.16.1)(babel-plugin-macros@3.1.0) next: specifier: ^14.2.10 - version: 14.2.10(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) + version: 14.2.10(@babel/core@7.25.2)(@playwright/test@1.49.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) octokit: specifier: ^3.2.1 version: 3.2.1 @@ -506,7 +506,7 @@ importers: version: 4.0.0-beta.12(@apollo/client@3.10.4(@types/react@18.3.3)(graphql-ws@5.15.0(graphql@16.8.1))(graphql@16.8.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@vue/composition-api@1.7.2(vue@3.4.27(typescript@5.5.4)))(graphql@16.8.1)(typescript@5.5.4)(vue@3.4.27(typescript@5.5.4)) floating-vue: specifier: ^5.2.2 - version: 5.2.2(@nuxt/kit@3.13.2(magicast@0.3.4)(rollup@4.20.0)(webpack-sources@3.2.3))(vue@3.4.27(typescript@5.5.4)) + version: 5.2.2(@nuxt/kit@3.13.2(magicast@0.3.4))(vue@3.4.27(typescript@5.5.4)) graphql: specifier: ^16.8.1 version: 16.8.1 @@ -698,10 +698,10 @@ importers: version: 2.0.1 next: specifier: ^14.2.10 - version: 14.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) + version: 14.2.10(@babel/core@7.25.2)(@playwright/test@1.49.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) next-seo: specifier: ^5.15.0 - version: 5.15.0(next@14.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 5.15.0(next@14.2.10(@babel/core@7.25.2)(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) query-string: specifier: ^8.2.0 version: 8.2.0 @@ -730,6 +730,9 @@ importers: specifier: ^2.5.2 version: 2.5.2 devDependencies: + '@playwright/test': + specifier: ^1.49.1 + version: 1.49.1 '@testing-library/react': specifier: 13.4.0 version: 13.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -804,7 +807,7 @@ importers: version: 2.0.1 next: specifier: ^14.2.10 - version: 14.2.10(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) + version: 14.2.10(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) query-string: specifier: ^8.2.0 version: 8.2.0 @@ -833,6 +836,9 @@ importers: specifier: ^2.5.2 version: 2.5.2 devDependencies: + '@playwright/test': + specifier: ^1.49.1 + version: 1.49.1 '@testing-library/react': specifier: 13.4.0 version: 13.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -884,6 +890,9 @@ importers: '@pantheon-systems/pcc-react-sdk': specifier: workspace:* version: link:../../packages/react-sdk + '@playwright/test': + specifier: ^1.49.1 + version: 1.49.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) @@ -910,10 +919,10 @@ importers: version: 2.0.1 next: specifier: ^14.2.10 - version: 14.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) + version: 14.2.10(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) next-seo: specifier: ^5.15.0 - version: 5.15.0(next@14.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 5.15.0(next@14.2.10(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) query-string: specifier: ^8.2.0 version: 8.2.0 @@ -923,6 +932,9 @@ importers: react-dom: specifier: 18.3.1 version: 18.3.1(react@18.3.1) + react-icons: + specifier: ^5.4.0 + version: 5.4.0(react@18.3.1) react-loading-skeleton: specifier: ^3.4.0 version: 3.4.0(react@18.3.1) @@ -3926,6 +3938,11 @@ packages: resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@playwright/test@1.49.1': + resolution: {integrity: sha512-Ky+BVzPz8pL6PQxHqNRW1k3mIyv933LML7HktS8uik0bUXNCdPhoS/kLihiO1tMf/egaJb4IutXd7UywvXEW+g==} + engines: {node: '>=18'} + hasBin: true + '@pmmmwh/react-refresh-webpack-plugin@0.5.11': resolution: {integrity: sha512-7j/6vdTym0+qZ6u4XbSAxrWBGYSdCfTzySkj7WAFgDLmSyWlOrWvpyzxlFh5jtw9dn0oL/jtW+06XfFiisN3JQ==} engines: {node: '>= 10.13'} @@ -8207,6 +8224,11 @@ packages: fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -10966,6 +10988,16 @@ packages: platform@1.3.6: resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==} + playwright-core@1.49.1: + resolution: {integrity: sha512-BzmpVcs4kE2CH15rWfzpjzVGhWERJfmnXmniSyKeRZUs9Ws65m+RGIi7mjJK/euCegfn3i7jvqWeWyHe9y3Vgg==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.49.1: + resolution: {integrity: sha512-VYL8zLoNTBxVOrJBbDuRgDWa3i+mfQgDTrL8Ah9QXZ7ax4Dsj0MSq5bYgytRnDVVe+njoKnfsYkH3HzqVj5UZA==} + engines: {node: '>=18'} + hasBin: true + pnp-webpack-plugin@1.7.0: resolution: {integrity: sha512-2Rb3vm+EXble/sMXNSu6eoBx8e79gKqhNq9F5ZWW6ERNCTE/Q0wQNne5541tE5vKjfM8hpNCYL+LGc1YTfI0dg==} engines: {node: '>=6'} @@ -18483,6 +18515,10 @@ snapshots: '@pkgr/core@0.1.1': {} + '@playwright/test@1.49.1': + dependencies: + playwright: 1.49.1 + '@pmmmwh/react-refresh-webpack-plugin@0.5.11(react-refresh@0.14.0)(type-fest@3.13.1)(webpack-hot-middleware@2.26.1)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2))': dependencies: ansi-html-community: 0.0.8 @@ -19631,7 +19667,7 @@ snapshots: '@storybook/manager@8.1.4': {} - '@storybook/nextjs@8.1.4(@jest/globals@29.7.0)(@swc/core@1.4.2(@swc/helpers@0.5.5))(@types/jest@29.5.1)(babel-plugin-macros@3.1.0)(encoding@0.1.13)(esbuild@0.20.2)(jest@29.5.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0))(next@14.2.10(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1)(type-fest@3.13.1)(typescript@5.5.4)(vitest@1.3.1(@types/node@20.11.21)(jsdom@22.1.0)(sass@1.71.1)(terser@5.28.1))(webpack-hot-middleware@2.26.1)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2))': + '@storybook/nextjs@8.1.4(@jest/globals@29.7.0)(@swc/core@1.4.2(@swc/helpers@0.5.5))(@types/jest@29.5.1)(babel-plugin-macros@3.1.0)(encoding@0.1.13)(esbuild@0.20.2)(jest@29.5.0(@types/node@20.11.21)(babel-plugin-macros@3.1.0))(next@14.2.10(@babel/core@7.25.2)(@playwright/test@1.49.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(prettier@3.2.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1)(type-fest@3.13.1)(typescript@5.5.4)(vitest@1.3.1(@types/node@20.11.21)(jsdom@22.1.0)(sass@1.71.1)(terser@5.28.1))(webpack-hot-middleware@2.26.1)(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2))': dependencies: '@babel/core': 7.24.6 '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.24.6) @@ -19664,7 +19700,7 @@ snapshots: fs-extra: 11.2.0 image-size: 1.1.1 loader-utils: 3.2.1 - next: 14.2.10(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) + next: 14.2.10(@babel/core@7.25.2)(@playwright/test@1.49.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) node-polyfill-webpack-plugin: 2.0.1(webpack@5.90.3(@swc/core@1.4.2(@swc/helpers@0.5.5))(esbuild@0.20.2)) pnp-webpack-plugin: 1.7.0(typescript@5.5.4) postcss: 8.4.38 @@ -23505,7 +23541,7 @@ snapshots: eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.8.0(eslint@8.57.0) eslint-plugin-react: 7.33.2(eslint@8.57.0) eslint-plugin-react-hooks: 4.6.0(eslint@8.57.0) @@ -23567,8 +23603,8 @@ snapshots: debug: 4.3.5 enhanced-resolve: 5.15.1 eslint: 8.57.0 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) fast-glob: 3.3.2 get-tsconfig: 4.7.2 is-core-module: 2.13.1 @@ -23579,7 +23615,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): + eslint-module-utils@2.8.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: @@ -23606,7 +23642,7 @@ snapshots: lodash: 4.17.21 string-natural-compare: 3.0.1 - eslint-plugin-import@2.29.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): dependencies: array-includes: 3.1.7 array.prototype.findlastindex: 1.2.4 @@ -23616,7 +23652,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@5.59.5(eslint@8.57.0)(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-plugin-import@2.29.1(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) hasown: 2.0.1 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -24248,7 +24284,7 @@ snapshots: flatted@3.3.1: {} - floating-vue@5.2.2(@nuxt/kit@3.13.2(magicast@0.3.4)(rollup@4.20.0)(webpack-sources@3.2.3))(vue@3.4.27(typescript@5.5.4)): + floating-vue@5.2.2(@nuxt/kit@3.13.2(magicast@0.3.4))(vue@3.4.27(typescript@5.5.4)): dependencies: '@floating-ui/dom': 1.1.1 vue: 3.4.27(typescript@5.5.4) @@ -24388,6 +24424,9 @@ snapshots: fs.realpath@1.0.0: {} + fsevents@2.3.2: + optional: true + fsevents@2.3.3: optional: true @@ -27969,15 +28008,21 @@ snapshots: neo-async@2.6.2: {} - next-seo@5.15.0(next@14.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + next-seo@5.15.0(next@14.2.10(@babel/core@7.25.2)(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - next: 14.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) + next: 14.2.10(@babel/core@7.25.2)(@playwright/test@1.49.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + next-seo@5.15.0(next@14.2.10(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + dependencies: + next: 14.2.10(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) next-tick@1.1.0: {} - next@14.2.10(@babel/core@7.25.2)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1): + next@14.2.10(@babel/core@7.25.2)(@playwright/test@1.49.1)(babel-plugin-macros@3.1.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1): dependencies: '@next/env': 14.2.10 '@swc/helpers': 0.5.5 @@ -27998,12 +28043,13 @@ snapshots: '@next/swc-win32-arm64-msvc': 14.2.10 '@next/swc-win32-ia32-msvc': 14.2.10 '@next/swc-win32-x64-msvc': 14.2.10 + '@playwright/test': 1.49.1 sass: 1.71.1 transitivePeerDependencies: - '@babel/core' - babel-plugin-macros - next@14.2.10(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1): + next@14.2.10(@playwright/test@1.49.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.71.1): dependencies: '@next/env': 14.2.10 '@swc/helpers': 0.5.5 @@ -28024,6 +28070,7 @@ snapshots: '@next/swc-win32-arm64-msvc': 14.2.10 '@next/swc-win32-ia32-msvc': 14.2.10 '@next/swc-win32-x64-msvc': 14.2.10 + '@playwright/test': 1.49.1 sass: 1.71.1 transitivePeerDependencies: - '@babel/core' @@ -28826,6 +28873,14 @@ snapshots: platform@1.3.6: {} + playwright-core@1.49.1: {} + + playwright@1.49.1: + dependencies: + playwright-core: 1.49.1 + optionalDependencies: + fsevents: 2.3.2 + pnp-webpack-plugin@1.7.0(typescript@5.5.4): dependencies: ts-pnp: 1.2.0(typescript@5.5.4) diff --git a/starters/nextjs-starter-approuter-ts/.gitignore b/starters/nextjs-starter-approuter-ts/.gitignore index 4c39b439..f6334b8e 100644 --- a/starters/nextjs-starter-approuter-ts/.gitignore +++ b/starters/nextjs-starter-approuter-ts/.gitignore @@ -49,3 +49,9 @@ out .yarn/build-state.yml .yarn/install-state.gz .pnp.* + +# playwright tests +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/starters/nextjs-starter-approuter-ts/app/authors/[author]/page.tsx b/starters/nextjs-starter-approuter-ts/app/authors/[author]/page.tsx index 4eea0e3d..d8d2ae83 100644 --- a/starters/nextjs-starter-approuter-ts/app/authors/[author]/page.tsx +++ b/starters/nextjs-starter-approuter-ts/app/authors/[author]/page.tsx @@ -66,7 +66,7 @@ export default async function ArticlesListTemplate({ params }) { totalCount={totalCount} fetcher={fetchNextPages(author)} additionalHeader={ -
+
diff --git a/starters/nextjs-starter-approuter-ts/next-env.d.ts b/starters/nextjs-starter-approuter-ts/next-env.d.ts index 4f11a03d..40c3d680 100644 --- a/starters/nextjs-starter-approuter-ts/next-env.d.ts +++ b/starters/nextjs-starter-approuter-ts/next-env.d.ts @@ -2,4 +2,4 @@ /// // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. diff --git a/starters/nextjs-starter-approuter-ts/package.json b/starters/nextjs-starter-approuter-ts/package.json index 13a4b53e..0f78d8db 100644 --- a/starters/nextjs-starter-approuter-ts/package.json +++ b/starters/nextjs-starter-approuter-ts/package.json @@ -9,7 +9,7 @@ "bugs": "https://github.com/pantheon-systems/pantheon-content-cloud-sdk/issues", "author": "@pantheon-systems", "scripts": { - "dev": "next dev -p 3001", + "dev": "next dev -p 3002", "build": "next build && cp -r .next/static .next/standalone/.next && cp -r public .next/standalone", "start": "node .next/standalone/server.js", "build:mono": "next build", @@ -19,6 +19,7 @@ "prettier:fix": "prettier \"**/*.{js,jsx,,md}\" --write --ignore-path .prettierignore", "test": "vitest run", "test:watch": "vitest", + "test:playwright": "pnpm exec playwright test", "update-snapshots": "vitest run --update --silent", "coverage": "vitest run --coverage" }, @@ -47,6 +48,7 @@ "tailwind-merge": "^2.5.2" }, "devDependencies": { + "@playwright/test": "^1.49.1", "@testing-library/react": "13.4.0", "@vitejs/plugin-react": "^4.2.1", "autoprefixer": "^10.4.17", diff --git a/starters/nextjs-starter-approuter-ts/playwright.config.ts b/starters/nextjs-starter-approuter-ts/playwright.config.ts new file mode 100644 index 00000000..a05d8b5a --- /dev/null +++ b/starters/nextjs-starter-approuter-ts/playwright.config.ts @@ -0,0 +1,79 @@ +import { defineConfig, devices } from '@playwright/test'; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// import dotenv from 'dotenv'; +// import path from 'path'; +// dotenv.config({ path: path.resolve(__dirname, '.env') }); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './tests', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + // baseURL: 'http://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { ...devices['Desktop Chrome'] }, + }, + + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // url: 'http://127.0.0.1:3000', + // reuseExistingServer: !process.env.CI, + // }, +}); diff --git a/starters/nextjs-starter-approuter-ts/tests/basic-pages.spec.ts b/starters/nextjs-starter-approuter-ts/tests/basic-pages.spec.ts new file mode 100644 index 00000000..0ce60223 --- /dev/null +++ b/starters/nextjs-starter-approuter-ts/tests/basic-pages.spec.ts @@ -0,0 +1,17 @@ +import { expect, test } from "@playwright/test"; + +// This assumes that the first article to appear in the list will have an author. +test("basic navigation", async ({ page }) => { + await page.goto("http://localhost:3002"); + + (await page.$("section .group button")).click(); + await page.waitForURL("**/articles/**", { + waitUntil: "networkidle", + }); + await page.getByTestId("author").click(); + await page.waitForURL("**/authors/**", { + waitUntil: "networkidle", + }); + + await expect(await page.getByTestId("author-header")).toBeInViewport(); +}); diff --git a/starters/nextjs-starter-ts/.gitignore b/starters/nextjs-starter-ts/.gitignore index 4c39b439..f6334b8e 100644 --- a/starters/nextjs-starter-ts/.gitignore +++ b/starters/nextjs-starter-ts/.gitignore @@ -49,3 +49,9 @@ out .yarn/build-state.yml .yarn/install-state.gz .pnp.* + +# playwright tests +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/starters/nextjs-starter-ts/components/article-view.tsx b/starters/nextjs-starter-ts/components/article-view.tsx index f8cc4f96..4ad3d86f 100644 --- a/starters/nextjs-starter-ts/components/article-view.tsx +++ b/starters/nextjs-starter-ts/components/article-view.tsx @@ -48,6 +48,7 @@ const ArticleHeader = ({ article, articleTitle, seoMetadata }) => { {seoMetadata.openGraph.article.authors?.[0] ? ( <> diff --git a/starters/nextjs-starter-ts/package.json b/starters/nextjs-starter-ts/package.json index ccf5e2ca..4eb5c161 100644 --- a/starters/nextjs-starter-ts/package.json +++ b/starters/nextjs-starter-ts/package.json @@ -19,6 +19,7 @@ "prettier:fix": "prettier \"**/*.{js,jsx,,md}\" --write --ignore-path .prettierignore", "test": "vitest run", "test:watch": "vitest", + "test:playwright": "pnpm exec playwright test", "update-snapshots": "vitest run --update --silent", "coverage": "vitest run --coverage" }, @@ -26,6 +27,7 @@ "node": ">=18.0.0" }, "dependencies": { + "@playwright/test": "^1.49.1", "@pantheon-systems/pcc-react-sdk": "~3.9.0", "@radix-ui/react-popover": "^1.1.1", "@radix-ui/react-slot": "^1.1.0", diff --git a/starters/nextjs-starter-ts/pages/authors/[author].tsx b/starters/nextjs-starter-ts/pages/authors/[author].tsx index 4a470c4b..b08a50e6 100644 --- a/starters/nextjs-starter-ts/pages/authors/[author].tsx +++ b/starters/nextjs-starter-ts/pages/authors/[author].tsx @@ -42,7 +42,10 @@ export default function ArticlesListTemplate({
-
+
{ + await page.goto("http://localhost:3001"); + + (await page.$("section .group button")).click(); + await page.waitForURL("**/articles/**", { + waitUntil: "networkidle", + }); + await page.getByTestId("author").click(); + await page.waitForURL("**/authors/**", { + waitUntil: "networkidle", + }); + + await expect(await page.getByTestId("author-header")).toBeInViewport(); +}); diff --git a/starters/nextjs-starter/.gitignore b/starters/nextjs-starter/.gitignore index 4c39b439..f6334b8e 100644 --- a/starters/nextjs-starter/.gitignore +++ b/starters/nextjs-starter/.gitignore @@ -49,3 +49,9 @@ out .yarn/build-state.yml .yarn/install-state.gz .pnp.* + +# playwright tests +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/starters/nextjs-starter/components/article-view.jsx b/starters/nextjs-starter/components/article-view.jsx index 36f83662..540b96c7 100644 --- a/starters/nextjs-starter/components/article-view.jsx +++ b/starters/nextjs-starter/components/article-view.jsx @@ -57,6 +57,7 @@ const ArticleHeader = ({ article, articleTitle, seoMetadata }) => { {seoMetadata.openGraph.article.authors?.[0] ? ( <> diff --git a/starters/nextjs-starter/package.json b/starters/nextjs-starter/package.json index eef1ff07..964f74b6 100644 --- a/starters/nextjs-starter/package.json +++ b/starters/nextjs-starter/package.json @@ -19,6 +19,7 @@ "prettier:fix": "prettier \"**/*.{js,jsx,,md}\" --write --ignore-path .prettierignore", "test": "vitest run", "test:watch": "vitest", + "test:playwright": "pnpm exec playwright test", "update-snapshots": "vitest run --update --silent", "coverage": "vitest run --coverage" }, @@ -48,6 +49,7 @@ "tailwind-merge": "^2.5.2" }, "devDependencies": { + "@playwright/test": "^1.49.1", "@testing-library/react": "13.4.0", "@vitejs/plugin-react": "^4.2.1", "autoprefixer": "^10.4.17", diff --git a/starters/nextjs-starter/pages/authors/[author].jsx b/starters/nextjs-starter/pages/authors/[author].jsx index c734afe7..6094751a 100644 --- a/starters/nextjs-starter/pages/authors/[author].jsx +++ b/starters/nextjs-starter/pages/authors/[author].jsx @@ -39,7 +39,10 @@ export default function ArticlesListTemplate({
-
+
{ + await page.goto("http://localhost:3000"); + + (await page.$("section .group button")).click(); + await page.waitForURL("**/articles/**", { + waitUntil: "networkidle", + }); + await page.getByTestId("author").click(); + await page.waitForURL("**/authors/**", { + waitUntil: "networkidle", + }); + + await expect(await page.getByTestId("author-header")).toBeInViewport(); +}); From a861dbd7e834b797697c7333b42af171221f11ad Mon Sep 17 00:00:00 2001 From: Kevin Stubbs Date: Mon, 30 Dec 2024 20:54:27 +0200 Subject: [PATCH 3/3] Skip playwright tests for starter kits when only running command. --- .../{tests => playwright-tests}/basic-pages.spec.ts | 0 starters/nextjs-starter-approuter-ts/playwright.config.ts | 2 +- starters/nextjs-starter-approuter-ts/vite.config.js | 3 ++- .../{tests => playwright-tests}/basic-pages.spec.ts | 0 starters/nextjs-starter-ts/playwright.config.ts | 2 +- starters/nextjs-starter-ts/vite.config.js | 3 ++- .../{tests => playwright-tests}/basic-pages.spec.js | 0 starters/nextjs-starter/playwright.config.js | 2 +- starters/nextjs-starter/vite.config.js | 3 ++- 9 files changed, 9 insertions(+), 6 deletions(-) rename starters/nextjs-starter-approuter-ts/{tests => playwright-tests}/basic-pages.spec.ts (100%) rename starters/nextjs-starter-ts/{tests => playwright-tests}/basic-pages.spec.ts (100%) rename starters/nextjs-starter/{tests => playwright-tests}/basic-pages.spec.js (100%) diff --git a/starters/nextjs-starter-approuter-ts/tests/basic-pages.spec.ts b/starters/nextjs-starter-approuter-ts/playwright-tests/basic-pages.spec.ts similarity index 100% rename from starters/nextjs-starter-approuter-ts/tests/basic-pages.spec.ts rename to starters/nextjs-starter-approuter-ts/playwright-tests/basic-pages.spec.ts diff --git a/starters/nextjs-starter-approuter-ts/playwright.config.ts b/starters/nextjs-starter-approuter-ts/playwright.config.ts index a05d8b5a..56218cda 100644 --- a/starters/nextjs-starter-approuter-ts/playwright.config.ts +++ b/starters/nextjs-starter-approuter-ts/playwright.config.ts @@ -12,7 +12,7 @@ import { defineConfig, devices } from '@playwright/test'; * See https://playwright.dev/docs/test-configuration. */ export default defineConfig({ - testDir: './tests', + testDir: './playwright-tests', /* Run tests in files in parallel */ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ diff --git a/starters/nextjs-starter-approuter-ts/vite.config.js b/starters/nextjs-starter-approuter-ts/vite.config.js index 1de88e54..761ffe98 100644 --- a/starters/nextjs-starter-approuter-ts/vite.config.js +++ b/starters/nextjs-starter-approuter-ts/vite.config.js @@ -1,5 +1,5 @@ -import { defineConfig } from "vitest/config"; import react from "@vitejs/plugin-react"; +import { configDefaults, defineConfig } from "vitest/config"; export default defineConfig(({ mode }) => { return { @@ -9,6 +9,7 @@ export default defineConfig(({ mode }) => { reportsDirectory: `./coverage`, }, setupFiles: ["./setupVitest.js"], + exclude: [...configDefaults.exclude, "./playwright-tests/*"], }, plugins: [react()], }; diff --git a/starters/nextjs-starter-ts/tests/basic-pages.spec.ts b/starters/nextjs-starter-ts/playwright-tests/basic-pages.spec.ts similarity index 100% rename from starters/nextjs-starter-ts/tests/basic-pages.spec.ts rename to starters/nextjs-starter-ts/playwright-tests/basic-pages.spec.ts diff --git a/starters/nextjs-starter-ts/playwright.config.ts b/starters/nextjs-starter-ts/playwright.config.ts index a05d8b5a..56218cda 100644 --- a/starters/nextjs-starter-ts/playwright.config.ts +++ b/starters/nextjs-starter-ts/playwright.config.ts @@ -12,7 +12,7 @@ import { defineConfig, devices } from '@playwright/test'; * See https://playwright.dev/docs/test-configuration. */ export default defineConfig({ - testDir: './tests', + testDir: './playwright-tests', /* Run tests in files in parallel */ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ diff --git a/starters/nextjs-starter-ts/vite.config.js b/starters/nextjs-starter-ts/vite.config.js index 1de88e54..761ffe98 100644 --- a/starters/nextjs-starter-ts/vite.config.js +++ b/starters/nextjs-starter-ts/vite.config.js @@ -1,5 +1,5 @@ -import { defineConfig } from "vitest/config"; import react from "@vitejs/plugin-react"; +import { configDefaults, defineConfig } from "vitest/config"; export default defineConfig(({ mode }) => { return { @@ -9,6 +9,7 @@ export default defineConfig(({ mode }) => { reportsDirectory: `./coverage`, }, setupFiles: ["./setupVitest.js"], + exclude: [...configDefaults.exclude, "./playwright-tests/*"], }, plugins: [react()], }; diff --git a/starters/nextjs-starter/tests/basic-pages.spec.js b/starters/nextjs-starter/playwright-tests/basic-pages.spec.js similarity index 100% rename from starters/nextjs-starter/tests/basic-pages.spec.js rename to starters/nextjs-starter/playwright-tests/basic-pages.spec.js diff --git a/starters/nextjs-starter/playwright.config.js b/starters/nextjs-starter/playwright.config.js index 1615efb5..26605466 100644 --- a/starters/nextjs-starter/playwright.config.js +++ b/starters/nextjs-starter/playwright.config.js @@ -12,7 +12,7 @@ import { defineConfig, devices } from "@playwright/test"; * See https://playwright.dev/docs/test-configuration. */ export default defineConfig({ - testDir: "./tests", + testDir: "./playwright-tests", /* Run tests in files in parallel */ fullyParallel: true, /* Fail the build on CI if you accidentally left test.only in the source code. */ diff --git a/starters/nextjs-starter/vite.config.js b/starters/nextjs-starter/vite.config.js index 1de88e54..761ffe98 100644 --- a/starters/nextjs-starter/vite.config.js +++ b/starters/nextjs-starter/vite.config.js @@ -1,5 +1,5 @@ -import { defineConfig } from "vitest/config"; import react from "@vitejs/plugin-react"; +import { configDefaults, defineConfig } from "vitest/config"; export default defineConfig(({ mode }) => { return { @@ -9,6 +9,7 @@ export default defineConfig(({ mode }) => { reportsDirectory: `./coverage`, }, setupFiles: ["./setupVitest.js"], + exclude: [...configDefaults.exclude, "./playwright-tests/*"], }, plugins: [react()], };