@elementor/editor-site-navigation 0.19.9 → 0.19.10

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 (37) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/index.js +286 -165
  3. package/dist/index.mjs +276 -156
  4. package/package.json +3 -3
  5. package/src/api/recent-posts.ts +15 -0
  6. package/src/components/panel/actions-menu/action-menu-item.tsx +10 -13
  7. package/src/components/panel/actions-menu/actions/__tests__/delete.test.tsx +2 -2
  8. package/src/components/panel/actions-menu/actions/__tests__/set-home.test.tsx +4 -4
  9. package/src/components/panel/actions-menu/actions/__tests__/view.test.tsx +1 -1
  10. package/src/components/panel/actions-menu/actions/delete.tsx +8 -2
  11. package/src/components/panel/actions-menu/actions/duplicate.tsx +1 -1
  12. package/src/components/panel/actions-menu/actions/rename.tsx +1 -1
  13. package/src/components/panel/actions-menu/actions/set-home.tsx +12 -4
  14. package/src/components/panel/actions-menu/actions/view.tsx +1 -1
  15. package/src/components/panel/add-new-button.tsx +3 -1
  16. package/src/components/panel/error-snackbar.tsx +33 -0
  17. package/src/components/panel/posts-list/__tests__/post-list-item.test.tsx +2 -2
  18. package/src/components/panel/posts-list/__tests__/posts-collapsible-list.test.tsx +3 -3
  19. package/src/components/panel/posts-list/collapsible-list.tsx +22 -10
  20. package/src/components/panel/posts-list/error-state.tsx +37 -0
  21. package/src/components/panel/posts-list/list-items/edit-mode-template.tsx +48 -31
  22. package/src/components/panel/posts-list/list-items/list-item-create.tsx +13 -10
  23. package/src/components/panel/posts-list/list-items/list-item-duplicate.tsx +13 -10
  24. package/src/components/panel/posts-list/list-items/list-item-rename.tsx +12 -9
  25. package/src/components/panel/posts-list/list-items/list-item-view.tsx +5 -12
  26. package/src/components/panel/posts-list/posts-collapsible-list.tsx +31 -3
  27. package/src/components/panel/shell.tsx +5 -1
  28. package/src/components/shared/page-title-and-status.tsx +2 -0
  29. package/src/components/top-bar/__tests__/add-new-page.test.tsx +6 -5
  30. package/src/components/top-bar/__tests__/recently-edited.test.tsx +22 -10
  31. package/src/components/top-bar/post-list-item.tsx +2 -2
  32. package/src/components/top-bar/recently-edited.tsx +21 -2
  33. package/src/contexts/post-list-context.tsx +5 -0
  34. package/src/hooks/__tests__/use-recent-posts.test.ts +8 -9
  35. package/src/hooks/use-posts-actions.ts +2 -1
  36. package/src/hooks/use-recent-posts.ts +8 -47
  37. package/src/types.ts +12 -0
@@ -3,12 +3,11 @@ import {
3
3
  bindMenu,
4
4
  bindTrigger,
5
5
  Divider,
6
+ IconButton,
6
7
  ListItem,
7
8
  ListItemButton,
8
- ListItemIcon,
9
9
  ListItemText,
10
10
  Menu,
11
- ToggleButton,
12
11
  usePopupState,
13
12
  } from '@elementor/ui';
14
13
  import { DotsVerticalIcon, HomeIcon } from '@elementor/icons';
@@ -39,15 +38,13 @@ export default function ListItemView( { post }: { post: Post } ) {
39
38
  <ListItem
40
39
  disablePadding
41
40
  secondaryAction={
42
- <ToggleButton
41
+ <IconButton
43
42
  value
44
- color="secondary"
45
43
  size="small"
46
- selected={ popupState.isOpen }
47
44
  { ...bindTrigger( popupState ) }
48
45
  >
49
46
  <DotsVerticalIcon fontSize="small" />
50
- </ToggleButton>
47
+ </IconButton>
51
48
  }
52
49
  >
53
50
  <ListItemButton
@@ -58,18 +55,14 @@ export default function ListItemView( { post }: { post: Post } ) {
58
55
  }
59
56
  } }
60
57
  dense
61
- disableGutters
62
58
  >
63
- <ListItemIcon />
64
59
  <ListItemText
65
60
  disableTypography={ true }
66
61
  >
67
62
  <PageTitleAndStatus page={ post } />
68
63
  </ListItemText>
69
64
  { post.isHome &&
70
- <ListItemIcon>
71
- <HomeIcon titleAccess={ __( 'Homepage', 'elementor' ) } color="disabled" />
72
- </ListItemIcon>
65
+ <HomeIcon titleAccess={ __( 'Homepage', 'elementor' ) } color="disabled" />
73
66
  }
74
67
  </ListItemButton>
75
68
  </ListItem>
@@ -83,7 +76,7 @@ export default function ListItemView( { post }: { post: Post } ) {
83
76
  <Delete post={ post } />
84
77
  <View post={ post } />
85
78
  <Divider />
86
- <SetHome post={ post } />
79
+ <SetHome post={ post } closeMenu={ () => popupState.close() } />
87
80
  </Menu>
88
81
  </>
89
82
  );
@@ -8,6 +8,7 @@ import CollapsibleList from './collapsible-list';
8
8
  import PostListItem from './post-list-item';
9
9
  import { useHomepage } from '../../../hooks/use-homepage';
10
10
  import AddNewButton from '../add-new-button';
11
+ import ErrorState from './error-state';
11
12
 
12
13
  type Props = {
13
14
  isOpenByDefault?: boolean,
@@ -15,9 +16,13 @@ type Props = {
15
16
 
16
17
  export default function PostsCollapsibleList( { isOpenByDefault = false }: Props ) {
17
18
  const { type, editMode } = usePostListContext();
18
- const { data: posts, isLoading: postsLoading } = usePosts( type );
19
+ const { data: posts, isLoading: postsLoading, isError: postsError } = usePosts( type );
19
20
  const { data: homepageSettings } = useHomepage();
20
21
 
22
+ if ( postsError ) {
23
+ return <ErrorState />;
24
+ }
25
+
21
26
  if ( ! posts || postsLoading ) {
22
27
  return (
23
28
  <Box sx={ { px: 5 } }>
@@ -43,12 +48,36 @@ export default function PostsCollapsibleList( { isOpenByDefault = false }: Props
43
48
  const isHomepageSet = homepageSettings?.show_on_front === 'page' && !! homepageSettings?.page_on_front;
44
49
  const homepageId = isHomepageSet ? homepageSettings.page_on_front : null;
45
50
 
51
+ const mappedPosts = posts.map( ( post ) => {
52
+ if ( post.id === homepageId ) {
53
+ return { ...post, isHome: true };
54
+ }
55
+
56
+ return post;
57
+ } );
58
+
59
+ const sortedPosts = mappedPosts.sort( ( a, b ) => {
60
+ if ( a.id === homepageId ) {
61
+ return -1;
62
+ }
63
+
64
+ if ( b.id === homepageId ) {
65
+ return 1;
66
+ }
67
+
68
+ return 0;
69
+ } );
70
+
46
71
  return (
47
72
  <>
48
73
  <Box
49
74
  display="flex"
50
75
  justifyContent="flex-end"
51
76
  alignItems="center"
77
+ sx={ {
78
+ py: 1,
79
+ px: 2,
80
+ } }
52
81
  >
53
82
  <AddNewButton />
54
83
  </Box>
@@ -58,8 +87,7 @@ export default function PostsCollapsibleList( { isOpenByDefault = false }: Props
58
87
  Icon={ PageTypeIcon }
59
88
  isOpenByDefault={ isOpenByDefault || false }
60
89
  >
61
- { posts.map( ( post ) => {
62
- post = { ...post, isHome: post.id === homepageId };
90
+ { sortedPosts.map( ( post ) => {
63
91
  return <PostListItem key={ post.id } post={ post } />;
64
92
  } ) }
65
93
  {
@@ -3,17 +3,21 @@ import { Panel, PanelBody, PanelHeader, PanelHeaderTitle } from '@elementor/edit
3
3
  import { __ } from '@wordpress/i18n';
4
4
  import PostsCollapsibleList from './posts-list/posts-collapsible-list';
5
5
  import { PostListContextProvider } from '../../contexts/post-list-context';
6
+ import ErrorSnackbar from './error-snackbar';
6
7
 
7
8
  const Shell = () => {
9
+ const [ isErrorSnackbarOpen, setIsErrorSnackbarOpen ] = React.useState( false );
10
+
8
11
  return (
9
12
  <Panel>
10
13
  <PanelHeader>
11
14
  <PanelHeaderTitle>{ __( 'Pages', 'elementor' ) }</PanelHeaderTitle>
12
15
  </PanelHeader>
13
16
  <PanelBody>
14
- <PostListContextProvider type={ 'page' }>
17
+ <PostListContextProvider type={ 'page' } setError={ () => setIsErrorSnackbarOpen( true ) }>
15
18
  <PostsCollapsibleList isOpenByDefault={ true } />
16
19
  </PostListContextProvider>
20
+ <ErrorSnackbar open={ isErrorSnackbarOpen } onClose={ () => setIsErrorSnackbarOpen( false ) } />
17
21
  </PanelBody>
18
22
  </Panel>
19
23
  );
@@ -12,6 +12,7 @@ const PageStatus = ( { status }: { status: string } ) => {
12
12
  <Typography
13
13
  component="span"
14
14
  variant="body2"
15
+ color="text.secondary"
15
16
  sx={ {
16
17
  textTransform: 'capitalize',
17
18
  fontStyle: 'italic',
@@ -31,6 +32,7 @@ const PageTitle = ( { title }: { title: string } ) => {
31
32
  <Typography
32
33
  component="span"
33
34
  variant="body2"
35
+ color="text.secondary"
34
36
  noWrap
35
37
  sx={ {
36
38
  flexBasis: 'auto',
@@ -3,8 +3,9 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react';
3
3
  import { __useActiveDocument as useActiveDocument, __useNavigateToDocument as useNavigateToDocument } from '@elementor/editor-documents';
4
4
  import RecentlyEdited from '../recently-edited';
5
5
  import { createMockDocument } from 'test-utils';
6
- import useRecentPosts, { Post } from '../../../hooks/use-recent-posts';
6
+ import useRecentPosts from '../../../hooks/use-recent-posts';
7
7
  import useCreatePage from '../../../hooks/use-create-page';
8
+ import { RecentPost } from '../../../types';
8
9
 
9
10
  jest.mock( '@elementor/editor-documents', () => ( {
10
11
  __useActiveDocument: jest.fn(),
@@ -30,9 +31,9 @@ describe( '@elementor/recently-edited - Top bar add new page', () => {
30
31
  it( 'should render add new page button', () => {
31
32
  // Arrange.
32
33
  const isLoading = false;
33
- const recentPosts: Post[] = [];
34
+ const recentPosts: RecentPost[] = [];
34
35
 
35
- jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, recentPosts } );
36
+ jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, data: recentPosts } as ReturnType<typeof useRecentPosts> );
36
37
 
37
38
  render( <RecentlyEdited /> );
38
39
 
@@ -48,11 +49,11 @@ describe( '@elementor/recently-edited - Top bar add new page', () => {
48
49
  it( 'should trigger create page hook on click', async () => {
49
50
  // Arrange.
50
51
  const isLoading = false;
51
- const recentPosts: Post[] = [];
52
+ const recentPosts: RecentPost[] = [];
52
53
  const create = jest.fn().mockReturnValue( Promise.resolve( { id: 123 } ) );
53
54
  const navigateToDocument = jest.fn();
54
55
 
55
- jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, recentPosts } );
56
+ jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, data: recentPosts } as ReturnType<typeof useRecentPosts> );
56
57
  jest.mocked( useCreatePage ).mockReturnValue( { isLoading, create } );
57
58
  jest.mocked( useNavigateToDocument ).mockReturnValue( navigateToDocument );
58
59
 
@@ -3,7 +3,8 @@ import { fireEvent, render, screen } from '@testing-library/react';
3
3
  import { __useHostDocument as useHostDocument, __useActiveDocument as useActiveDocument, __useNavigateToDocument as useNavigateToDocument } from '@elementor/editor-documents';
4
4
  import RecentlyEdited from '../recently-edited';
5
5
  import { createMockDocument } from 'test-utils';
6
- import useRecentPosts, { Post } from '../../../hooks/use-recent-posts';
6
+ import useRecentPosts from '../../../hooks/use-recent-posts';
7
+ import { RecentPost } from '../../../types';
7
8
 
8
9
  jest.mock( '@elementor/editor-documents', () => ( {
9
10
  __useActiveDocument: jest.fn(),
@@ -13,7 +14,7 @@ jest.mock( '@elementor/editor-documents', () => ( {
13
14
 
14
15
  jest.mock( '../../../hooks/use-recent-posts', () => (
15
16
  {
16
- default: jest.fn( () => ( { isLoading: false, recentPosts: [] } ) ),
17
+ default: jest.fn( () => ( { isLoading: false, data: [] } ) ),
17
18
  __esModule: true,
18
19
  }
19
20
  ) );
@@ -117,9 +118,9 @@ describe( '@elementor/recently-edited - Top bar Recently Edited', () => {
117
118
  } ) );
118
119
 
119
120
  const isLoading = false;
120
- const recentPosts: Post[] = [];
121
+ const recentPosts: RecentPost[] = [];
121
122
 
122
- jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, recentPosts } );
123
+ jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, data: recentPosts } as ReturnType<typeof useRecentPosts> );
123
124
 
124
125
  render( <RecentlyEdited /> );
125
126
 
@@ -144,7 +145,7 @@ describe( '@elementor/recently-edited - Top bar Recently Edited', () => {
144
145
  } ) );
145
146
 
146
147
  const isLoading = false;
147
- const recentPosts: Post[] = [ {
148
+ const recentPosts: RecentPost[] = [ {
148
149
  id: 1,
149
150
  title: 'Test post',
150
151
  edit_url: 'some_url',
@@ -156,7 +157,7 @@ describe( '@elementor/recently-edited - Top bar Recently Edited', () => {
156
157
  date_modified: 123,
157
158
  } ];
158
159
 
159
- jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, recentPosts } );
160
+ jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, data: recentPosts } as ReturnType<typeof useRecentPosts> );
160
161
 
161
162
  render( <RecentlyEdited /> );
162
163
 
@@ -186,9 +187,20 @@ describe( '@elementor/recently-edited - Top bar Recently Edited', () => {
186
187
  } ) );
187
188
 
188
189
  const isLoading = false;
189
- const recentPosts: Post[] = [
190
+ const recentPosts: RecentPost[] = [
190
191
  {
191
192
  id: 1,
193
+ title: 'Header title with special char &#165;',
194
+ edit_url: 'some_url',
195
+ type: {
196
+ post_type: 'post',
197
+ doc_type: 'wp-post',
198
+ label: 'Post',
199
+ },
200
+ date_modified: 123,
201
+ },
202
+ {
203
+ id: 3,
192
204
  title: 'Post title with <h1>HTML</h1>',
193
205
  edit_url: 'some_url',
194
206
  type: {
@@ -211,7 +223,7 @@ describe( '@elementor/recently-edited - Top bar Recently Edited', () => {
211
223
  },
212
224
  ];
213
225
 
214
- jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, recentPosts } );
226
+ jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, data: recentPosts } as ReturnType<typeof useRecentPosts> );
215
227
 
216
228
  // Act.
217
229
  render( <RecentlyEdited /> );
@@ -235,7 +247,7 @@ describe( '@elementor/recently-edited - Top bar Recently Edited', () => {
235
247
 
236
248
  jest.mocked( useRecentPosts ).mockReturnValue( {
237
249
  isLoading: false,
238
- recentPosts: [ {
250
+ data: [ {
239
251
  id: 123,
240
252
  title: 'Test post',
241
253
  edit_url: 'some_url',
@@ -246,7 +258,7 @@ describe( '@elementor/recently-edited - Top bar Recently Edited', () => {
246
258
  },
247
259
  date_modified: 123,
248
260
  } ],
249
- } );
261
+ } as ReturnType<typeof useRecentPosts> );
250
262
 
251
263
  render( <RecentlyEdited /> );
252
264
 
@@ -1,12 +1,12 @@
1
1
  import DocTypeChip from './chip-doc-type';
2
2
  import { MenuItem, MenuItemProps, ListItemText } from '@elementor/ui';
3
3
  import * as React from 'react';
4
- import { Post } from '../../hooks/use-recent-posts';
5
4
  import { __useNavigateToDocument as useNavigateToDocument } from '@elementor/editor-documents';
6
5
  import { useReverseHtmlEntities } from '../../hooks/use-reverse-html-entities';
6
+ import { RecentPost } from '../../types';
7
7
 
8
8
  type Props = MenuItemProps & {
9
- post: Post;
9
+ post: RecentPost;
10
10
  closePopup: () => void;
11
11
  }
12
12
 
@@ -18,6 +18,7 @@ import { __ } from '@wordpress/i18n';
18
18
  import { PostListItem } from './post-list-item';
19
19
  import { CreatePostListItem } from './create-post-list-item';
20
20
  import { useReverseHtmlEntities } from '../../hooks/use-reverse-html-entities';
21
+ import { NUMBER_OF_RECENT_POSTS } from '../../api/recent-posts';
21
22
 
22
23
  export default function RecentlyEdited() {
23
24
  const activeDocument = useActiveDocument();
@@ -26,14 +27,32 @@ export default function RecentlyEdited() {
26
27
  ? activeDocument
27
28
  : hostDocument;
28
29
 
29
- const { recentPosts } = useRecentPosts( document?.id );
30
+ const { data } = useRecentPosts();
31
+
32
+ const getRecentPosts = () => {
33
+ if ( ! data ) {
34
+ return [];
35
+ }
36
+
37
+ return data.filter( ( post ) => post.id !== document?.id ).splice( 0, NUMBER_OF_RECENT_POSTS - 1 );
38
+ };
39
+ const recentPosts = getRecentPosts();
30
40
 
31
41
  const popupState = usePopupState( {
32
42
  variant: 'popover',
33
43
  popupId: 'elementor-v2-top-bar-recently-edited',
34
44
  } );
35
45
 
36
- const documentTitle = useReverseHtmlEntities( document?.title );
46
+ const getCurrentDocumentFromRecentPosts = () => {
47
+ if ( ! document ) {
48
+ return null;
49
+ }
50
+
51
+ return data?.find( ( post ) => post.id === document.id );
52
+ };
53
+ const currentDocumentFromRecentPosts = getCurrentDocumentFromRecentPosts();
54
+
55
+ const documentTitle = useReverseHtmlEntities( currentDocumentFromRecentPosts ? currentDocumentFromRecentPosts.title : document?.title );
37
56
 
38
57
  if ( ! document ) {
39
58
  return null;
@@ -26,6 +26,7 @@ type ContextType = {
26
26
  editMode: EditMode,
27
27
  setEditMode: Dispatch<SetStateAction<EditMode>>,
28
28
  resetEditMode: () => void,
29
+ setError: () => void,
29
30
  };
30
31
 
31
32
  const defaultValues: ContextType = {
@@ -33,15 +34,18 @@ const defaultValues: ContextType = {
33
34
  editMode: { mode: 'none', details: {} },
34
35
  setEditMode: () => null,
35
36
  resetEditMode: () => null,
37
+ setError: () => null,
36
38
  };
37
39
 
38
40
  export const PostListContext = createContext<ContextType>( defaultValues );
39
41
 
40
42
  export const PostListContextProvider = ( {
41
43
  type,
44
+ setError,
42
45
  children,
43
46
  }: {
44
47
  type: ContextType[ 'type' ],
48
+ setError: ContextType[ 'setError' ],
45
49
  children: ReactNode,
46
50
  } ) => {
47
51
  const [ editMode, setEditMode ] = useState( defaultValues.editMode );
@@ -56,6 +60,7 @@ export const PostListContextProvider = ( {
56
60
  editMode,
57
61
  setEditMode,
58
62
  resetEditMode,
63
+ setError,
59
64
  } }>
60
65
  { children }
61
66
  </PostListContext.Provider>
@@ -1,15 +1,13 @@
1
- import { waitFor, renderHook } from '@testing-library/react';
1
+ import { waitFor } from '@testing-library/react';
2
2
  import apiFetch from '@wordpress/api-fetch';
3
- import useRecentPosts, { endpointPath } from '../use-recent-posts';
3
+ import useRecentPosts from '../use-recent-posts';
4
+ import { renderHookWithQuery } from 'test-utils';
5
+ import { baseUrl } from '../../api/recent-posts';
4
6
 
5
7
  // Mock apiFetch to return a promise that resolves to an empty array.
6
8
  jest.mock( '@wordpress/api-fetch' );
7
9
 
8
10
  describe( 'useRecentPosts', () => {
9
- beforeEach( () => {
10
- jest.mocked( apiFetch ).mockImplementation( () => Promise.resolve( [] ) );
11
- } );
12
-
13
11
  afterEach( () => {
14
12
  jest.clearAllMocks();
15
13
  } );
@@ -28,14 +26,15 @@ describe( 'useRecentPosts', () => {
28
26
 
29
27
  jest.mocked( apiFetch ).mockImplementation( () => Promise.resolve( posts ) );
30
28
 
31
- const { result } = renderHook( () => useRecentPosts( 1 ) );
29
+ // Act.
30
+ const { component } = renderHookWithQuery( () => useRecentPosts() );
32
31
 
33
32
  expect( apiFetch ).toHaveBeenCalledWith( {
34
- path: endpointPath + '?posts_per_page=5&post__not_in=1',
33
+ path: `${ baseUrl }?posts_per_page=6`,
35
34
  } );
36
35
 
37
36
  await waitFor( () => {
38
- expect( result.current.recentPosts ).toBe( posts );
37
+ expect( component.result.current.data ).toBe( posts );
39
38
  } );
40
39
  } );
41
40
  } );
@@ -1,6 +1,7 @@
1
1
  import { useQueryClient, useMutation } from '@elementor/query';
2
2
  import { createRequest, deleteRequest, updateRequest, duplicateRequest, NewPost, Slug, UpdatePost } from '../api/post';
3
3
  import { postsQueryKey } from './use-posts';
4
+ import { recentPostsQueryKey } from './use-recent-posts';
4
5
 
5
6
  export function usePostActions( postTypeSlug: Slug ) {
6
7
  const invalidatePosts = useInvalidatePosts( postTypeSlug );
@@ -40,7 +41,7 @@ function useInvalidatePosts( postTypeSlug: string ) {
40
41
 
41
42
  return ( options = {} ) => {
42
43
  const queryKey = postsQueryKey( postTypeSlug );
43
-
44
+ queryClient.invalidateQueries( { queryKey: recentPostsQueryKey }, options );
44
45
  return queryClient.invalidateQueries( { queryKey }, options );
45
46
  };
46
47
  }
@@ -1,50 +1,11 @@
1
- import { useEffect, useState } from 'react';
2
- import apiFetch from '@wordpress/api-fetch';
3
- import { addQueryArgs } from '@wordpress/url';
1
+ import { useQuery } from '@elementor/query';
2
+ import { getRequest } from '../api/recent-posts';
4
3
 
5
- export interface Post {
6
- id: number,
7
- title: string,
8
- edit_url: string,
9
- type: {
10
- post_type: string,
11
- doc_type: string,
12
- label: string,
13
- },
14
- date_modified: number,
15
- }
16
-
17
- export const endpointPath = '/elementor/v1/site-navigation/recent-posts';
18
-
19
- export default function useRecentPosts( documentId?: number ) {
20
- const [ recentPosts, setRecentPosts ] = useState<Post[]>( [] );
21
- const [ isLoading, setIsLoading ] = useState( false );
22
-
23
- useEffect( () => {
24
- if ( documentId ) {
25
- setIsLoading( true );
26
-
27
- fetchRecentlyEditedPosts( documentId ).then( ( posts ) => {
28
- setRecentPosts( posts );
29
- setIsLoading( false );
30
- } );
31
- }
32
- }, [ documentId ] );
33
-
34
- return {
35
- isLoading,
36
- recentPosts,
37
- };
38
- }
39
-
40
- async function fetchRecentlyEditedPosts( documentId: number ) {
41
- const queryParams = {
42
- posts_per_page: 5,
43
- post__not_in: documentId,
44
- };
4
+ export const recentPostsQueryKey = [ 'site-navigation', 'recent-posts' ];
45
5
 
46
- return await apiFetch( {
47
- path: addQueryArgs( endpointPath, queryParams ),
48
- } ).then( ( response ) => response as Post[] )
49
- .catch( () => [] );
6
+ export default function useRecentPosts() {
7
+ return useQuery( {
8
+ queryKey: recentPostsQueryKey,
9
+ queryFn: () => getRequest(),
10
+ } );
50
11
  }
package/src/types.ts CHANGED
@@ -8,3 +8,15 @@ export type Post = {
8
8
  rendered: string;
9
9
  }
10
10
  };
11
+
12
+ export type RecentPost = {
13
+ id: number,
14
+ title: string,
15
+ edit_url: string,
16
+ type: {
17
+ post_type: string,
18
+ doc_type: string,
19
+ label: string,
20
+ },
21
+ date_modified: number,
22
+ }