@elementor/editor-site-navigation 0.22.5 → 0.22.7

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 (44) hide show
  1. package/CHANGELOG.md +38 -328
  2. package/dist/index.js +147 -156
  3. package/dist/index.mjs +168 -175
  4. package/package.json +49 -49
  5. package/src/api/post.ts +18 -18
  6. package/src/api/recent-posts.ts +1 -1
  7. package/src/api/settings.ts +4 -4
  8. package/src/api/user.ts +4 -4
  9. package/src/components/panel/actions-menu/action-menu-item.tsx +7 -10
  10. package/src/components/panel/actions-menu/actions/__tests__/set-home.test.tsx +12 -9
  11. package/src/components/panel/actions-menu/actions/delete.tsx +27 -25
  12. package/src/components/panel/actions-menu/actions/duplicate.tsx +5 -7
  13. package/src/components/panel/actions-menu/actions/rename.tsx +11 -13
  14. package/src/components/panel/actions-menu/actions/set-home.tsx +6 -8
  15. package/src/components/panel/actions-menu/actions/view.tsx +3 -5
  16. package/src/components/panel/error-snackbar.tsx +4 -3
  17. package/src/components/panel/panel.ts +1 -5
  18. package/src/components/panel/posts-list/__tests__/posts-collapsible-list.test.tsx +66 -19
  19. package/src/components/panel/posts-list/collapsible-list.tsx +38 -29
  20. package/src/components/panel/posts-list/error-state.tsx +35 -27
  21. package/src/components/panel/posts-list/list-items/edit-mode-template.tsx +18 -40
  22. package/src/components/panel/posts-list/list-items/list-item-create.tsx +5 -1
  23. package/src/components/panel/posts-list/list-items/list-item-duplicate.tsx +5 -1
  24. package/src/components/panel/posts-list/list-items/list-item-rename.tsx +3 -5
  25. package/src/components/panel/posts-list/list-items/list-item-view.tsx +20 -19
  26. package/src/components/panel/posts-list/posts-collapsible-list.tsx +22 -24
  27. package/src/components/shared/page-title-and-status.tsx +4 -2
  28. package/src/components/top-bar/__tests__/add-new-page.test.tsx +33 -16
  29. package/src/components/top-bar/__tests__/recently-edited.test.tsx +157 -120
  30. package/src/components/top-bar/chip-doc-type.tsx +1 -3
  31. package/src/components/top-bar/create-post-list-item.tsx +1 -1
  32. package/src/components/top-bar/indicator.tsx +17 -15
  33. package/src/components/top-bar/post-list-item.tsx +2 -6
  34. package/src/components/top-bar/recently-edited.tsx +13 -19
  35. package/src/contexts/post-list-context.tsx +40 -34
  36. package/src/env.ts +2 -2
  37. package/src/hooks/__tests__/use-posts.test.ts +19 -3
  38. package/src/hooks/use-create-page.ts +2 -2
  39. package/src/hooks/use-homepage.ts +1 -1
  40. package/src/hooks/use-posts.ts +1 -1
  41. package/src/hooks/use-toggle-button-props.ts +1 -5
  42. package/src/hooks/use-user.ts +1 -1
  43. package/src/icons-map.ts +1 -1
  44. package/src/types.ts +22 -22
@@ -4,34 +4,42 @@ import { __ } from '@wordpress/i18n';
4
4
  import * as React from 'react';
5
5
 
6
6
  export default function ErrorState() {
7
- return ( <Box sx={ {
8
- display: 'flex',
9
- flexDirection: 'column',
10
- justifyContent: 'center',
11
- alignItems: 'center',
12
- pt: '40px',
13
- gap: '16px',
14
- } }>
15
- <Error404TemplateIcon />
16
- <Box sx={ {
17
- display: 'flex',
18
- flexDirection: 'column',
19
- justifyContent: 'center',
20
- alignItems: 'center',
21
- gap: '8px',
22
- } }>
23
- <Typography variant="body1" color="text.primary">
24
- { __( 'We couldn’t display your pages.', 'elementor' ) }
25
- </Typography>
26
- <Box>
27
- <Typography variant="body2" color="text.primary" sx={ { textAlign: 'center' } }>
28
- { __( 'It’s probably a temporary issue.', 'elementor' ) }
7
+ return (
8
+ <Box
9
+ sx={ {
10
+ display: 'flex',
11
+ flexDirection: 'column',
12
+ justifyContent: 'center',
13
+ alignItems: 'center',
14
+ pt: '40px',
15
+ gap: '16px',
16
+ } }
17
+ >
18
+ <Error404TemplateIcon />
19
+ <Box
20
+ sx={ {
21
+ display: 'flex',
22
+ flexDirection: 'column',
23
+ justifyContent: 'center',
24
+ alignItems: 'center',
25
+ gap: '8px',
26
+ } }
27
+ >
28
+ <Typography variant="body1" color="text.primary">
29
+ { __( 'We couldn’t display your pages.', 'elementor' ) }
29
30
  </Typography>
30
- <Typography variant="body2" color="text.primary" sx={ { textAlign: 'center' } }>
31
- { __( 'If the problem persists,', 'elementor' ) } <Link target="_blank" href="https://go.elementor.com/wp-editor-support-open-ticket/">Notify support</Link>
32
- </Typography>
33
-
31
+ <Box>
32
+ <Typography variant="body2" color="text.primary" sx={ { textAlign: 'center' } }>
33
+ { __( 'It’s probably a temporary issue.', 'elementor' ) }
34
+ </Typography>
35
+ <Typography variant="body2" color="text.primary" sx={ { textAlign: 'center' } }>
36
+ { __( 'If the problem persists,', 'elementor' ) }{ ' ' }
37
+ <Link target="_blank" href="https://go.elementor.com/wp-editor-support-open-ticket/">
38
+ Notify support
39
+ </Link>
40
+ </Typography>
41
+ </Box>
34
42
  </Box>
35
43
  </Box>
36
- </Box> );
44
+ );
37
45
  }
@@ -1,28 +1,21 @@
1
1
  import * as React from 'react';
2
2
  import { useState, useRef, FormEvent, MutableRefObject, FocusEvent } from 'react';
3
- import {
4
- Box,
5
- ListItem,
6
- TextField,
7
- IconButton,
8
- CircularProgress,
9
- ListItemText,
10
- } from '@elementor/ui';
3
+ import { Box, ListItem, TextField, IconButton, CircularProgress, ListItemText } from '@elementor/ui';
11
4
  import { XIcon } from '@elementor/icons';
12
5
  import { __ } from '@wordpress/i18n';
13
6
  import { usePostListContext } from '../../../../contexts/post-list-context';
14
7
 
15
8
  type Props = {
16
- postTitle: string,
17
- isLoading: boolean,
18
- callback: ( inputValue: string ) => void,
19
- }
9
+ postTitle: string;
10
+ isLoading: boolean;
11
+ callback: ( inputValue: string ) => void;
12
+ };
20
13
 
21
14
  export default function EditModeTemplate( { postTitle, isLoading, callback }: Props ) {
22
15
  const [ title, setTitle ] = useState( postTitle );
23
16
  const [ touched, setTouched ] = useState( false );
24
- const [ inputError, setInputError ] = useState<string | null>( null );
25
- const closeButton = useRef<HTMLButtonElement>();
17
+ const [ inputError, setInputError ] = useState< string | null >( null );
18
+ const closeButton = useRef< HTMLButtonElement >();
26
19
 
27
20
  const onBlur = ( e: FocusEvent ) => {
28
21
  if ( closeButton.current === e.relatedTarget ) {
@@ -32,7 +25,7 @@ export default function EditModeTemplate( { postTitle, isLoading, callback }: Pr
32
25
  runCallback();
33
26
  };
34
27
 
35
- const onFormSubmit = ( e: FormEvent<HTMLFormElement> ) => {
28
+ const onFormSubmit = ( e: FormEvent< HTMLFormElement > ) => {
36
29
  e.preventDefault();
37
30
  runCallback();
38
31
  };
@@ -49,7 +42,7 @@ export default function EditModeTemplate( { postTitle, isLoading, callback }: Pr
49
42
  callback( title );
50
43
  };
51
44
 
52
- const onChange = ( e: React.ChangeEvent<{ value: string; }> ) => {
45
+ const onChange = ( e: React.ChangeEvent< { value: string } > ) => {
53
46
  if ( ! touched ) {
54
47
  setTouched( true );
55
48
  }
@@ -65,9 +58,7 @@ export default function EditModeTemplate( { postTitle, isLoading, callback }: Pr
65
58
 
66
59
  return (
67
60
  <>
68
- <ListItem
69
- secondaryAction={ <CloseButton isLoading={ isLoading } closeButton={ closeButton } /> }
70
- >
61
+ <ListItem secondaryAction={ <CloseButton isLoading={ isLoading } closeButton={ closeButton } /> }>
71
62
  <Box width="100%" component="form" onSubmit={ onFormSubmit }>
72
63
  <TextField
73
64
  autoFocus // eslint-disable-line jsx-a11y/no-autofocus
@@ -83,39 +74,26 @@ export default function EditModeTemplate( { postTitle, isLoading, callback }: Pr
83
74
  />
84
75
  </Box>
85
76
  </ListItem>
86
- {
87
- inputError &&
77
+ { inputError && (
88
78
  <ListItem>
89
- <ListItemText sx={ { color: 'error.main' } }>
90
- { inputError }
91
- </ListItemText>
79
+ <ListItemText sx={ { color: 'error.main' } }>{ inputError }</ListItemText>
92
80
  </ListItem>
93
- }
81
+ ) }
94
82
  </>
95
83
  );
96
84
  }
97
85
 
98
86
  type CloseButtonProps = {
99
- isLoading: boolean,
100
- closeButton: MutableRefObject<HTMLButtonElement | undefined>,
101
- }
87
+ isLoading: boolean;
88
+ closeButton: MutableRefObject< HTMLButtonElement | undefined >;
89
+ };
102
90
 
103
91
  function CloseButton( { isLoading, closeButton }: CloseButtonProps ) {
104
92
  const { resetEditMode } = usePostListContext();
105
93
 
106
94
  return (
107
- <IconButton
108
- size="small"
109
- color="secondary"
110
- onClick={ resetEditMode }
111
- ref={ closeButton }
112
- disabled={ isLoading }
113
- >
114
- {
115
- isLoading
116
- ? <CircularProgress />
117
- : <XIcon fontSize="small" />
118
- }
95
+ <IconButton size="small" color="secondary" onClick={ resetEditMode } ref={ closeButton } disabled={ isLoading }>
96
+ { isLoading ? <CircularProgress /> : <XIcon fontSize="small" /> }
119
97
  </IconButton>
120
98
  );
121
99
  }
@@ -27,6 +27,10 @@ export default function ListItemCreate() {
27
27
  };
28
28
 
29
29
  return (
30
- <EditModeTemplate postTitle={ __( 'New Page', 'elementor' ) } isLoading={ createPost.isPending } callback={ createPostCallback } />
30
+ <EditModeTemplate
31
+ postTitle={ __( 'New Page', 'elementor' ) }
32
+ isLoading={ createPost.isPending }
33
+ callback={ createPostCallback }
34
+ />
31
35
  );
32
36
  }
@@ -31,6 +31,10 @@ export default function ListItemDuplicate() {
31
31
  };
32
32
 
33
33
  return (
34
- <EditModeTemplate postTitle={ `${ editMode.details.title } ${ __( 'copy', 'elementor' ) }` } isLoading={ duplicatePost.isPending } callback={ duplicatePostCallback } />
34
+ <EditModeTemplate
35
+ postTitle={ `${ editMode.details.title } ${ __( 'copy', 'elementor' ) }` }
36
+ isLoading={ duplicatePost.isPending }
37
+ callback={ duplicatePostCallback }
38
+ />
35
39
  );
36
40
  }
@@ -7,8 +7,8 @@ import { __useActiveDocument as useActiveDocument } from '@elementor/editor-docu
7
7
  import useRenameActiveDocument from '../../../../hooks/use-rename-active-document';
8
8
 
9
9
  type Props = {
10
- post: Post,
11
- }
10
+ post: Post;
11
+ };
12
12
 
13
13
  export default function ListItemRename( { post }: Props ) {
14
14
  const { type, resetEditMode } = usePostListContext();
@@ -41,7 +41,5 @@ export default function ListItemRename( { post }: Props ) {
41
41
  }
42
42
  };
43
43
 
44
- return (
45
- <EditModeTemplate postTitle={ title } isLoading={ updatePost.isPending } callback={ renamePostCallback } />
46
- );
44
+ return <EditModeTemplate postTitle={ title } isLoading={ updatePost.isPending } callback={ renamePostCallback } />;
47
45
  }
@@ -13,7 +13,10 @@ import {
13
13
  usePopupState,
14
14
  } from '@elementor/ui';
15
15
  import { DotsVerticalIcon, HomeIcon } from '@elementor/icons';
16
- import { __useActiveDocument as useActiveDocument, __useNavigateToDocument as useNavigateToDocument } from '@elementor/editor-documents';
16
+ import {
17
+ __useActiveDocument as useActiveDocument,
18
+ __useNavigateToDocument as useNavigateToDocument,
19
+ } from '@elementor/editor-documents';
17
20
  import PageTitleAndStatus from '../../../shared/page-title-and-status';
18
21
  import Rename from '../../actions-menu/actions/rename';
19
22
  import Duplicate from '../../actions-menu/actions/duplicate';
@@ -23,18 +26,22 @@ import SetHome from '../../actions-menu/actions/set-home';
23
26
  import { Post } from '../../../../types';
24
27
  import { __ } from '@wordpress/i18n';
25
28
 
26
- const DisabledPostTooltip = ( { children, isDisabled }: {children: React.ReactNode, isDisabled: boolean} ) => {
29
+ const DisabledPostTooltip = ( { children, isDisabled }: { children: React.ReactNode; isDisabled: boolean } ) => {
27
30
  if ( isDisabled ) {
28
- const title = <Typography variant="caption">You cannot edit this page.<br />To edit it directly, contact the site owner</Typography>;
31
+ const title = (
32
+ <Typography variant="caption">
33
+ You cannot edit this page.
34
+ <br />
35
+ To edit it directly, contact the site owner
36
+ </Typography>
37
+ );
29
38
 
30
- return <Tooltip
31
- title={ title }
32
- placement="bottom"
33
- arrow={ false }
34
- >
35
- { /* @see https://mui.com/material-ui/react-tooltip/#disabled-elements */ }
36
- { children }
37
- </Tooltip>;
39
+ return (
40
+ <Tooltip title={ title } placement="bottom" arrow={ false }>
41
+ { /* @see https://mui.com/material-ui/react-tooltip/#disabled-elements */ }
42
+ { children }
43
+ </Tooltip>
44
+ );
38
45
  }
39
46
 
40
47
  return <>{ children }</>;
@@ -61,11 +68,7 @@ export default function ListItemView( { post }: { post: Post } ) {
61
68
  <ListItem
62
69
  disablePadding
63
70
  secondaryAction={
64
- <IconButton
65
- value
66
- size="small"
67
- { ...bindTrigger( popupState ) }
68
- >
71
+ <IconButton value size="small" { ...bindTrigger( popupState ) }>
69
72
  <DotsVerticalIcon fontSize="small" />
70
73
  </IconButton>
71
74
  }
@@ -83,9 +86,7 @@ export default function ListItemView( { post }: { post: Post } ) {
83
86
  <ListItemText disableTypography={ true }>
84
87
  <PageTitleAndStatus title={ title } status={ status } />
85
88
  </ListItemText>
86
- { post.isHome &&
87
- <HomeIcon titleAccess={ __( 'Homepage', 'elementor' ) } color="disabled" />
88
- }
89
+ { post.isHome && <HomeIcon titleAccess={ __( 'Homepage', 'elementor' ) } color="disabled" /> }
89
90
  </ListItemButton>
90
91
  </ListItem>
91
92
  </DisabledPostTooltip>
@@ -11,12 +11,19 @@ import AddNewButton from '../add-new-button';
11
11
  import ErrorState from './error-state';
12
12
 
13
13
  type Props = {
14
- isOpenByDefault?: boolean,
15
- }
14
+ isOpenByDefault?: boolean;
15
+ };
16
16
 
17
17
  export default function PostsCollapsibleList( { isOpenByDefault = false }: Props ) {
18
18
  const { type, editMode } = usePostListContext();
19
- const { data: { posts, total }, isLoading: postsLoading, isError: postsError, fetchNextPage, hasNextPage, isFetchingNextPage } = usePosts( type );
19
+ const {
20
+ data: { posts, total },
21
+ isLoading: postsLoading,
22
+ isError: postsError,
23
+ fetchNextPage,
24
+ hasNextPage,
25
+ isFetchingNextPage,
26
+ } = usePosts( type );
20
27
  const { data: homepageId } = useHomepage();
21
28
 
22
29
  if ( postsError ) {
@@ -26,14 +33,10 @@ export default function PostsCollapsibleList( { isOpenByDefault = false }: Props
26
33
  if ( ! posts || postsLoading ) {
27
34
  return (
28
35
  <Box sx={ { px: 5 } }>
29
- <Box
30
- display="flex"
31
- justifyContent="flex-end"
32
- alignItems="center"
33
- >
36
+ <Box display="flex" justifyContent="flex-end" alignItems="center">
34
37
  <Skeleton sx={ { my: 4 } } animation="wave" variant="rounded" width="110px" height="28px" />
35
38
  </Box>
36
- <Box >
39
+ <Box>
37
40
  <Skeleton sx={ { my: 3 } } animation="wave" variant="rounded" width="100%" height="24px" />
38
41
  <Skeleton sx={ { my: 3 } } animation="wave" variant="rounded" width="70%" height="24px" />
39
42
  <Skeleton sx={ { my: 3 } } animation="wave" variant="rounded" width="70%" height="24px" />
@@ -79,28 +82,23 @@ export default function PostsCollapsibleList( { isOpenByDefault = false }: Props
79
82
  <AddNewButton />
80
83
  </Box>
81
84
  <List dense>
82
- <CollapsibleList
83
- label={ label }
84
- Icon={ PageTypeIcon }
85
- isOpenByDefault={ isOpenByDefault || false }
86
- >
85
+ <CollapsibleList label={ label } Icon={ PageTypeIcon } isOpenByDefault={ isOpenByDefault || false }>
87
86
  { sortedPosts.map( ( post ) => {
88
87
  return <PostListItem key={ post.id } post={ post } />;
89
88
  } ) }
90
- {
91
- [ 'duplicate', 'create' ].includes( editMode.mode ) &&
92
- <PostListItem />
93
- }
94
- { hasNextPage &&
95
- <Box sx={ {
96
- display: 'flex',
97
- justifyContent: 'center',
98
- } }>
89
+ { [ 'duplicate', 'create' ].includes( editMode.mode ) && <PostListItem /> }
90
+ { hasNextPage && (
91
+ <Box
92
+ sx={ {
93
+ display: 'flex',
94
+ justifyContent: 'center',
95
+ } }
96
+ >
99
97
  <Button onClick={ fetchNextPage } color="secondary">
100
98
  { isFetchingNextPage ? <CircularProgress /> : 'Load More' }
101
99
  </Button>
102
100
  </Box>
103
- }
101
+ ) }
104
102
  </CollapsibleList>
105
103
  </List>
106
104
  </>
@@ -42,10 +42,12 @@ const PageTitle = ( { title }: { title: string } ) => {
42
42
  );
43
43
  };
44
44
 
45
- export default function PageTitleAndStatus( { title, status }: { title: string, status: string } ) {
45
+ export default function PageTitleAndStatus( { title, status }: { title: string; status: string } ) {
46
46
  return (
47
47
  <Box display="flex">
48
- <PageTitle title={ title } />&nbsp;<PageStatus status={ status } />
48
+ <PageTitle title={ title } />
49
+ &nbsp;
50
+ <PageStatus status={ status } />
49
51
  </Box>
50
52
  );
51
53
  }
@@ -1,6 +1,9 @@
1
1
  import * as React from 'react';
2
2
  import { fireEvent, render, screen, waitFor } from '@testing-library/react';
3
- import { __useActiveDocument as useActiveDocument, __useNavigateToDocument as useNavigateToDocument } from '@elementor/editor-documents';
3
+ import {
4
+ __useActiveDocument as useActiveDocument,
5
+ __useNavigateToDocument as useNavigateToDocument,
6
+ } from '@elementor/editor-documents';
4
7
  import RecentlyEdited from '../recently-edited';
5
8
  import { createMockDocument } from 'test-utils';
6
9
  import useRecentPosts from '../../../hooks/use-recent-posts';
@@ -24,14 +27,17 @@ jest.mock( '../../../hooks/use-create-page', () => ( {
24
27
  default: jest.fn( () => ( { create: jest.fn(), isLoading: false } ) ),
25
28
  } ) );
26
29
 
27
- jest.mock( '../../../hooks/use-user', () => (
28
- {
29
- default: jest.fn( () => ( { isLoading: false, data: { capabilities: {
30
- edit_pages: true,
31
- } } } ) ),
32
- __esModule: true,
33
- }
34
- ) );
30
+ jest.mock( '../../../hooks/use-user', () => ( {
31
+ default: jest.fn( () => ( {
32
+ isLoading: false,
33
+ data: {
34
+ capabilities: {
35
+ edit_pages: true,
36
+ },
37
+ },
38
+ } ) ),
39
+ __esModule: true,
40
+ } ) );
35
41
 
36
42
  describe( '@elementor/recently-edited - Top bar add new page', () => {
37
43
  beforeEach( () => {
@@ -47,7 +53,9 @@ describe( '@elementor/recently-edited - Top bar add new page', () => {
47
53
  const isLoading = false;
48
54
  const recentPosts: RecentPost[] = [];
49
55
 
50
- jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, data: recentPosts } as ReturnType<typeof useRecentPosts> );
56
+ jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, data: recentPosts } as ReturnType<
57
+ typeof useRecentPosts
58
+ > );
51
59
 
52
60
  render( <RecentlyEdited /> );
53
61
 
@@ -67,7 +75,9 @@ describe( '@elementor/recently-edited - Top bar add new page', () => {
67
75
  const create = jest.fn().mockReturnValue( Promise.resolve( { id: 123 } ) );
68
76
  const navigateToDocument = jest.fn();
69
77
 
70
- jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, data: recentPosts } as ReturnType<typeof useRecentPosts> );
78
+ jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, data: recentPosts } as ReturnType<
79
+ typeof useRecentPosts
80
+ > );
71
81
  jest.mocked( useCreatePage ).mockReturnValue( { isLoading, create } );
72
82
  jest.mocked( useNavigateToDocument ).mockReturnValue( navigateToDocument );
73
83
 
@@ -90,14 +100,21 @@ describe( '@elementor/recently-edited - Top bar add new page', () => {
90
100
 
91
101
  it( 'should be disabled if user does not have edit_posts capability', () => {
92
102
  // Arrange.
93
- jest.mocked( useUser ).mockReturnValue( { isLoading: false, data: { capabilities: {
94
- edit_pages: false,
95
- } } } as unknown as ReturnType<typeof useUser> );
103
+ jest.mocked( useUser ).mockReturnValue( {
104
+ isLoading: false,
105
+ data: {
106
+ capabilities: {
107
+ edit_pages: false,
108
+ },
109
+ },
110
+ } as unknown as ReturnType< typeof useUser > );
96
111
 
97
112
  const isLoading = false;
98
113
  const recentPosts: RecentPost[] = [];
99
114
 
100
- jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, data: recentPosts } as ReturnType<typeof useRecentPosts> );
115
+ jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, data: recentPosts } as ReturnType<
116
+ typeof useRecentPosts
117
+ > );
101
118
 
102
119
  render( <RecentlyEdited /> );
103
120
 
@@ -106,7 +123,7 @@ describe( '@elementor/recently-edited - Top bar add new page', () => {
106
123
  fireEvent.click( buttons[ 0 ] ); // Opens the recently edited menu
107
124
 
108
125
  // Assert.
109
- const addNewPage = screen.getByRole( 'menuitem', { name: /Add new page/i }, );
126
+ const addNewPage = screen.getByRole( 'menuitem', { name: /Add new page/i } );
110
127
  expect( addNewPage ).toHaveAttribute( 'aria-disabled', 'true' );
111
128
  } );
112
129
  } );