@prezly/theme-kit-nextjs 1.6.2 → 1.6.4-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/README.md +30 -0
  2. package/build/adapter-nextjs/processRequest.js +3 -1
  3. package/build/adapter-nextjs/processRequest.js.map +1 -1
  4. package/build/components-nextjs/PageSeo/PageSeo.d.ts +12 -0
  5. package/build/components-nextjs/PageSeo/PageSeo.js +89 -0
  6. package/build/components-nextjs/PageSeo/PageSeo.js.map +1 -0
  7. package/build/components-nextjs/PageSeo/index.d.ts +2 -0
  8. package/build/components-nextjs/PageSeo/index.js +17 -0
  9. package/build/components-nextjs/PageSeo/index.js.map +1 -0
  10. package/build/components-nextjs/PageSeo/lib/getAbsoluteUrl.d.ts +1 -0
  11. package/build/components-nextjs/PageSeo/lib/getAbsoluteUrl.js +11 -0
  12. package/build/components-nextjs/PageSeo/lib/getAbsoluteUrl.js.map +1 -0
  13. package/build/components-nextjs/PageSeo/lib/types.d.ts +4 -0
  14. package/build/components-nextjs/PageSeo/lib/types.js +3 -0
  15. package/build/components-nextjs/PageSeo/lib/types.js.map +1 -0
  16. package/build/components-nextjs/Sitemap/SitemapBuilder.d.ts +11 -0
  17. package/build/components-nextjs/Sitemap/SitemapBuilder.js +51 -0
  18. package/build/components-nextjs/Sitemap/SitemapBuilder.js.map +1 -0
  19. package/build/components-nextjs/Sitemap/createPaths.d.ts +2 -0
  20. package/build/components-nextjs/Sitemap/createPaths.js +50 -0
  21. package/build/components-nextjs/Sitemap/createPaths.js.map +1 -0
  22. package/build/components-nextjs/Sitemap/getInitialProps.d.ts +2 -0
  23. package/build/components-nextjs/Sitemap/getInitialProps.js +78 -0
  24. package/build/components-nextjs/Sitemap/getInitialProps.js.map +1 -0
  25. package/build/components-nextjs/Sitemap/index.d.ts +4 -0
  26. package/build/components-nextjs/Sitemap/index.js +21 -0
  27. package/build/components-nextjs/Sitemap/index.js.map +1 -0
  28. package/build/components-nextjs/Sitemap/types.d.ts +5 -0
  29. package/build/components-nextjs/Sitemap/types.js +3 -0
  30. package/build/components-nextjs/Sitemap/types.js.map +1 -0
  31. package/build/components-nextjs/StorySeo/StorySeo.d.ts +11 -0
  32. package/build/components-nextjs/StorySeo/StorySeo.js +47 -0
  33. package/build/components-nextjs/StorySeo/StorySeo.js.map +1 -0
  34. package/build/components-nextjs/StorySeo/index.d.ts +1 -0
  35. package/build/components-nextjs/StorySeo/index.js +6 -0
  36. package/build/components-nextjs/StorySeo/index.js.map +1 -0
  37. package/build/components-nextjs/index.d.ts +3 -0
  38. package/build/components-nextjs/index.js +19 -0
  39. package/build/components-nextjs/index.js.map +1 -0
  40. package/build/data-fetching/lib/getEnvVariables.d.ts +1 -1
  41. package/build/data-fetching/lib/getEnvVariables.js.map +1 -1
  42. package/build/index.d.ts +2 -0
  43. package/build/index.js +2 -0
  44. package/build/index.js.map +1 -1
  45. package/build/infinite-loading/apiHandlers/fetchGalleries.d.ts +2 -0
  46. package/build/infinite-loading/apiHandlers/fetchGalleries.js +73 -0
  47. package/build/infinite-loading/apiHandlers/fetchGalleries.js.map +1 -0
  48. package/build/infinite-loading/apiHandlers/fetchStories.d.ts +2 -0
  49. package/build/infinite-loading/apiHandlers/fetchStories.js +75 -0
  50. package/build/infinite-loading/apiHandlers/fetchStories.js.map +1 -0
  51. package/build/infinite-loading/apiHandlers/index.d.ts +2 -0
  52. package/build/infinite-loading/apiHandlers/index.js +8 -0
  53. package/build/infinite-loading/apiHandlers/index.js.map +1 -0
  54. package/build/infinite-loading/index.d.ts +5 -0
  55. package/build/infinite-loading/index.js +22 -0
  56. package/build/infinite-loading/index.js.map +1 -0
  57. package/build/infinite-loading/types.d.ts +5 -0
  58. package/build/infinite-loading/types.js +3 -0
  59. package/build/infinite-loading/types.js.map +1 -0
  60. package/build/infinite-loading/useInfiniteGalleriesLoading.d.ts +13 -0
  61. package/build/infinite-loading/useInfiniteGalleriesLoading.js +98 -0
  62. package/build/infinite-loading/useInfiniteGalleriesLoading.js.map +1 -0
  63. package/build/infinite-loading/useInfiniteLoading.d.ts +16 -0
  64. package/build/infinite-loading/useInfiniteLoading.js +115 -0
  65. package/build/infinite-loading/useInfiniteLoading.js.map +1 -0
  66. package/build/infinite-loading/useInfiniteStoriesLoading.d.ts +13 -0
  67. package/build/infinite-loading/useInfiniteStoriesLoading.js +116 -0
  68. package/build/infinite-loading/useInfiniteStoriesLoading.js.map +1 -0
  69. package/build/intl/locale.js +4 -3
  70. package/build/intl/locale.js.map +1 -1
  71. package/package.json +6 -3
  72. package/src/adapter-nextjs/processRequest.ts +3 -1
  73. package/src/components-nextjs/PageSeo/PageSeo.tsx +123 -0
  74. package/src/components-nextjs/PageSeo/index.ts +2 -0
  75. package/src/components-nextjs/PageSeo/lib/getAbsoluteUrl.ts +7 -0
  76. package/src/components-nextjs/PageSeo/lib/types.ts +4 -0
  77. package/src/components-nextjs/Sitemap/SitemapBuilder.ts +56 -0
  78. package/src/components-nextjs/Sitemap/createPaths.ts +21 -0
  79. package/src/components-nextjs/Sitemap/getInitialProps.ts +37 -0
  80. package/src/components-nextjs/Sitemap/index.ts +5 -0
  81. package/src/components-nextjs/Sitemap/types.ts +5 -0
  82. package/src/components-nextjs/StorySeo/StorySeo.tsx +68 -0
  83. package/src/components-nextjs/StorySeo/index.ts +1 -0
  84. package/src/components-nextjs/index.ts +3 -0
  85. package/src/data-fetching/lib/getEnvVariables.ts +5 -3
  86. package/src/index.ts +2 -0
  87. package/src/infinite-loading/apiHandlers/fetchGalleries.ts +24 -0
  88. package/src/infinite-loading/apiHandlers/fetchStories.ts +26 -0
  89. package/src/infinite-loading/apiHandlers/index.ts +2 -0
  90. package/src/infinite-loading/index.ts +5 -0
  91. package/src/infinite-loading/types.ts +5 -0
  92. package/src/infinite-loading/useInfiniteGalleriesLoading.ts +53 -0
  93. package/src/infinite-loading/useInfiniteLoading.ts +66 -0
  94. package/src/infinite-loading/useInfiniteStoriesLoading.ts +81 -0
  95. package/src/intl/locale.ts +5 -4
@@ -0,0 +1,53 @@
1
+ import type { NewsroomGallery } from '@prezly/sdk';
2
+
3
+ import type { PaginationProps } from './types';
4
+ import { useInfiniteLoading } from './useInfiniteLoading';
5
+
6
+ async function fetchGalleries(
7
+ page: number,
8
+ pageSize: number,
9
+ ): Promise<{ galleries: NewsroomGallery[] }> {
10
+ const result = await fetch('/api/fetch-galleries', {
11
+ method: 'POST',
12
+ headers: {
13
+ 'Content-Type': 'application/json',
14
+ },
15
+ body: JSON.stringify({
16
+ page,
17
+ pageSize,
18
+ }),
19
+ });
20
+
21
+ if (!result.ok) {
22
+ const { message } = await result.json();
23
+ throw new Error(message);
24
+ }
25
+
26
+ return result.json();
27
+ }
28
+
29
+ /**
30
+ * NOTE: This hook depends on the presence of a Next API route (/api/fetch-galleries)!
31
+ * The handler for this route is exported from `apiHandlers/fetchGalleries.ts` file.
32
+ * See https://github.com/prezly/theme-nextjs-bea/blob/d381e9878187ca98815d240d3ffdf10a75993c14/pages/media/index.tsx#L23 for usage example
33
+ */
34
+ export function useInfiniteGalleriesLoading(
35
+ initialGalleries: NewsroomGallery[],
36
+ pagination: PaginationProps,
37
+ ) {
38
+ const { canLoadMore, data, isLoading, loadMore } = useInfiniteLoading<NewsroomGallery>({
39
+ fetchingFn: async (nextPage, pageSize) => {
40
+ const { galleries } = await fetchGalleries(nextPage, pageSize);
41
+ return galleries;
42
+ },
43
+ initialData: initialGalleries,
44
+ pagination,
45
+ });
46
+
47
+ return {
48
+ canLoadMore,
49
+ galleries: data,
50
+ isLoading,
51
+ loadMoreGalleries: loadMore,
52
+ };
53
+ }
@@ -0,0 +1,66 @@
1
+ import { useAsync } from '@react-hookz/web';
2
+ import { useCallback, useEffect, useState } from 'react';
3
+
4
+ import type { PaginationProps } from './types';
5
+
6
+ interface Parameters<T> {
7
+ fetchingFn: (page: number, pageSize: number) => Promise<T[]>;
8
+ initialData: T[];
9
+ pagination: PaginationProps;
10
+ }
11
+
12
+ interface State<T> {
13
+ canLoadMore: boolean;
14
+ currentPage: number;
15
+ data: T[];
16
+ isLoading: boolean;
17
+ loadMore: () => void;
18
+ resetData: () => void;
19
+ }
20
+
21
+ export function useInfiniteLoading<T>({
22
+ fetchingFn,
23
+ initialData,
24
+ pagination,
25
+ }: Parameters<T>): State<T> {
26
+ const [data, setData] = useState<T[]>(initialData);
27
+ const [currentPage, setCurrentPage] = useState(pagination.currentPage);
28
+
29
+ const { itemsTotal, pageSize } = pagination;
30
+ const pagesTotal = Math.ceil(itemsTotal / pageSize);
31
+ const canLoadMore = currentPage < pagesTotal;
32
+
33
+ const [{ error, status }, { execute: loadMoreFn }] = useAsync(async () => {
34
+ const nextPage = currentPage + 1;
35
+ const newData = await fetchingFn(nextPage, pageSize);
36
+ setCurrentPage(nextPage);
37
+ setData((currentData) => [...currentData, ...newData]);
38
+ });
39
+
40
+ const loadMore = useCallback(() => {
41
+ if (canLoadMore) {
42
+ loadMoreFn();
43
+ }
44
+ }, [canLoadMore, loadMoreFn]);
45
+
46
+ const resetData = useCallback(() => {
47
+ setData(initialData);
48
+ setCurrentPage(pagination.currentPage);
49
+ }, [pagination.currentPage, initialData]);
50
+
51
+ useEffect(() => {
52
+ if (error) {
53
+ // eslint-disable-next-line no-console
54
+ console.error(error);
55
+ }
56
+ }, [error]);
57
+
58
+ return {
59
+ canLoadMore,
60
+ currentPage,
61
+ data,
62
+ isLoading: status === 'loading',
63
+ loadMore,
64
+ resetData,
65
+ };
66
+ }
@@ -0,0 +1,81 @@
1
+ import type { Category, ExtraStoryFields, Story } from '@prezly/sdk';
2
+ import { useEffect } from 'react';
3
+
4
+ import type { LocaleObject } from '../intl';
5
+ import { useCurrentLocale } from '../newsroom-context';
6
+
7
+ import type { PaginationProps } from './types';
8
+ import { useInfiniteLoading } from './useInfiniteLoading';
9
+
10
+ async function fetchStories<T extends Story = Story>(
11
+ page: number,
12
+ pageSize: number,
13
+ category?: Category,
14
+ locale?: LocaleObject,
15
+ include?: (keyof ExtraStoryFields)[],
16
+ ): Promise<{ stories: T[] }> {
17
+ const result = await fetch('/api/fetch-stories', {
18
+ method: 'POST',
19
+ headers: {
20
+ 'Content-Type': 'application/json',
21
+ },
22
+ body: JSON.stringify({
23
+ page,
24
+ pageSize,
25
+ category,
26
+ include,
27
+ ...(locale && {
28
+ localeCode: locale.toUnderscoreCode(),
29
+ }),
30
+ }),
31
+ });
32
+
33
+ if (!result.ok) {
34
+ const { message } = await result.json();
35
+ throw new Error(message);
36
+ }
37
+
38
+ return result.json();
39
+ }
40
+
41
+ /**
42
+ * NOTE: This hook depends on the presence of a Next API route (/api/fetch-stories)!
43
+ * The handler for this route is exported from `apiHandlers/fetchStories.ts` file.
44
+ * See https://github.com/prezly/theme-nextjs-bea/blob/d381e9878187ca98815d240d3ffdf10a75993c14/pages/index.tsx#L24 for usage example
45
+ */
46
+ export function useInfiniteStoriesLoading<T extends Story = Story>(
47
+ initialStories: T[],
48
+ pagination: PaginationProps,
49
+ category?: Category,
50
+ include?: (keyof ExtraStoryFields)[],
51
+ ) {
52
+ const currentLocale = useCurrentLocale();
53
+
54
+ const { canLoadMore, data, isLoading, loadMore, resetData } = useInfiniteLoading<T>({
55
+ fetchingFn: async (nextPage, pageSize) => {
56
+ const { stories } = await fetchStories<T>(
57
+ nextPage,
58
+ pageSize,
59
+ category,
60
+ currentLocale,
61
+ include,
62
+ );
63
+ return stories;
64
+ },
65
+ initialData: initialStories,
66
+ pagination,
67
+ });
68
+
69
+ useEffect(() => {
70
+ if (category?.id) {
71
+ resetData();
72
+ }
73
+ }, [category?.id, resetData]);
74
+
75
+ return {
76
+ canLoadMore,
77
+ isLoading,
78
+ loadMoreStories: loadMore,
79
+ stories: data,
80
+ };
81
+ }
@@ -97,14 +97,15 @@ export function getRedirectToCanonicalLocale(
97
97
  redirectPath: string,
98
98
  query?: ParsedUrlQuery,
99
99
  ): Redirect | undefined {
100
+ // No need to redirect if no particular locale was requested by the application
101
+ if (!nextLocaleIsoCode || nextLocaleIsoCode === DUMMY_DEFAULT_LOCALE) {
102
+ return undefined;
103
+ }
104
+
100
105
  const shortestLocaleSlug = shortestLocaleCode
101
106
  ? LocaleObject.fromAnyCode(shortestLocaleCode).toUrlSlug()
102
107
  : shortestLocaleCode;
103
108
 
104
- if (nextLocaleIsoCode === DUMMY_DEFAULT_LOCALE) {
105
- return undefined;
106
- }
107
-
108
109
  if (shortestLocaleSlug !== nextLocaleIsoCode) {
109
110
  const prefixedPath =
110
111
  redirectPath && !redirectPath.startsWith('/') ? `/${redirectPath}` : redirectPath;