@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.
- package/README.md +30 -0
- package/build/adapter-nextjs/processRequest.js +3 -1
- package/build/adapter-nextjs/processRequest.js.map +1 -1
- package/build/components-nextjs/PageSeo/PageSeo.d.ts +12 -0
- package/build/components-nextjs/PageSeo/PageSeo.js +89 -0
- package/build/components-nextjs/PageSeo/PageSeo.js.map +1 -0
- package/build/components-nextjs/PageSeo/index.d.ts +2 -0
- package/build/components-nextjs/PageSeo/index.js +17 -0
- package/build/components-nextjs/PageSeo/index.js.map +1 -0
- package/build/components-nextjs/PageSeo/lib/getAbsoluteUrl.d.ts +1 -0
- package/build/components-nextjs/PageSeo/lib/getAbsoluteUrl.js +11 -0
- package/build/components-nextjs/PageSeo/lib/getAbsoluteUrl.js.map +1 -0
- package/build/components-nextjs/PageSeo/lib/types.d.ts +4 -0
- package/build/components-nextjs/PageSeo/lib/types.js +3 -0
- package/build/components-nextjs/PageSeo/lib/types.js.map +1 -0
- package/build/components-nextjs/Sitemap/SitemapBuilder.d.ts +11 -0
- package/build/components-nextjs/Sitemap/SitemapBuilder.js +51 -0
- package/build/components-nextjs/Sitemap/SitemapBuilder.js.map +1 -0
- package/build/components-nextjs/Sitemap/createPaths.d.ts +2 -0
- package/build/components-nextjs/Sitemap/createPaths.js +50 -0
- package/build/components-nextjs/Sitemap/createPaths.js.map +1 -0
- package/build/components-nextjs/Sitemap/getInitialProps.d.ts +2 -0
- package/build/components-nextjs/Sitemap/getInitialProps.js +78 -0
- package/build/components-nextjs/Sitemap/getInitialProps.js.map +1 -0
- package/build/components-nextjs/Sitemap/index.d.ts +4 -0
- package/build/components-nextjs/Sitemap/index.js +21 -0
- package/build/components-nextjs/Sitemap/index.js.map +1 -0
- package/build/components-nextjs/Sitemap/types.d.ts +5 -0
- package/build/components-nextjs/Sitemap/types.js +3 -0
- package/build/components-nextjs/Sitemap/types.js.map +1 -0
- package/build/components-nextjs/StorySeo/StorySeo.d.ts +11 -0
- package/build/components-nextjs/StorySeo/StorySeo.js +47 -0
- package/build/components-nextjs/StorySeo/StorySeo.js.map +1 -0
- package/build/components-nextjs/StorySeo/index.d.ts +1 -0
- package/build/components-nextjs/StorySeo/index.js +6 -0
- package/build/components-nextjs/StorySeo/index.js.map +1 -0
- package/build/components-nextjs/index.d.ts +3 -0
- package/build/components-nextjs/index.js +19 -0
- package/build/components-nextjs/index.js.map +1 -0
- package/build/data-fetching/lib/getEnvVariables.d.ts +1 -1
- package/build/data-fetching/lib/getEnvVariables.js.map +1 -1
- package/build/index.d.ts +2 -0
- package/build/index.js +2 -0
- package/build/index.js.map +1 -1
- package/build/infinite-loading/apiHandlers/fetchGalleries.d.ts +2 -0
- package/build/infinite-loading/apiHandlers/fetchGalleries.js +73 -0
- package/build/infinite-loading/apiHandlers/fetchGalleries.js.map +1 -0
- package/build/infinite-loading/apiHandlers/fetchStories.d.ts +2 -0
- package/build/infinite-loading/apiHandlers/fetchStories.js +75 -0
- package/build/infinite-loading/apiHandlers/fetchStories.js.map +1 -0
- package/build/infinite-loading/apiHandlers/index.d.ts +2 -0
- package/build/infinite-loading/apiHandlers/index.js +8 -0
- package/build/infinite-loading/apiHandlers/index.js.map +1 -0
- package/build/infinite-loading/index.d.ts +5 -0
- package/build/infinite-loading/index.js +22 -0
- package/build/infinite-loading/index.js.map +1 -0
- package/build/infinite-loading/types.d.ts +5 -0
- package/build/infinite-loading/types.js +3 -0
- package/build/infinite-loading/types.js.map +1 -0
- package/build/infinite-loading/useInfiniteGalleriesLoading.d.ts +13 -0
- package/build/infinite-loading/useInfiniteGalleriesLoading.js +98 -0
- package/build/infinite-loading/useInfiniteGalleriesLoading.js.map +1 -0
- package/build/infinite-loading/useInfiniteLoading.d.ts +16 -0
- package/build/infinite-loading/useInfiniteLoading.js +115 -0
- package/build/infinite-loading/useInfiniteLoading.js.map +1 -0
- package/build/infinite-loading/useInfiniteStoriesLoading.d.ts +13 -0
- package/build/infinite-loading/useInfiniteStoriesLoading.js +116 -0
- package/build/infinite-loading/useInfiniteStoriesLoading.js.map +1 -0
- package/build/intl/locale.js +4 -3
- package/build/intl/locale.js.map +1 -1
- package/package.json +6 -3
- package/src/adapter-nextjs/processRequest.ts +3 -1
- package/src/components-nextjs/PageSeo/PageSeo.tsx +123 -0
- package/src/components-nextjs/PageSeo/index.ts +2 -0
- package/src/components-nextjs/PageSeo/lib/getAbsoluteUrl.ts +7 -0
- package/src/components-nextjs/PageSeo/lib/types.ts +4 -0
- package/src/components-nextjs/Sitemap/SitemapBuilder.ts +56 -0
- package/src/components-nextjs/Sitemap/createPaths.ts +21 -0
- package/src/components-nextjs/Sitemap/getInitialProps.ts +37 -0
- package/src/components-nextjs/Sitemap/index.ts +5 -0
- package/src/components-nextjs/Sitemap/types.ts +5 -0
- package/src/components-nextjs/StorySeo/StorySeo.tsx +68 -0
- package/src/components-nextjs/StorySeo/index.ts +1 -0
- package/src/components-nextjs/index.ts +3 -0
- package/src/data-fetching/lib/getEnvVariables.ts +5 -3
- package/src/index.ts +2 -0
- package/src/infinite-loading/apiHandlers/fetchGalleries.ts +24 -0
- package/src/infinite-loading/apiHandlers/fetchStories.ts +26 -0
- package/src/infinite-loading/apiHandlers/index.ts +2 -0
- package/src/infinite-loading/index.ts +5 -0
- package/src/infinite-loading/types.ts +5 -0
- package/src/infinite-loading/useInfiniteGalleriesLoading.ts +53 -0
- package/src/infinite-loading/useInfiniteLoading.ts +66 -0
- package/src/infinite-loading/useInfiniteStoriesLoading.ts +81 -0
- 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
|
+
}
|
package/src/intl/locale.ts
CHANGED
|
@@ -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;
|