@elementor/editor-site-navigation 0.11.0 → 0.12.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 (32) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/index.js +444 -173
  3. package/dist/index.mjs +440 -160
  4. package/package.json +2 -2
  5. package/src/api/post.ts +14 -6
  6. package/src/components/panel/actions-menu/action-list-item.tsx +1 -1
  7. package/src/components/panel/{pages-actions → actions-menu/actions}/delete.tsx +5 -5
  8. package/src/components/panel/actions-menu/actions/duplicate.tsx +29 -0
  9. package/src/components/panel/actions-menu/actions/rename.tsx +25 -0
  10. package/src/components/panel/{pages-actions → actions-menu/actions}/set-home.tsx +4 -4
  11. package/src/components/panel/actions-menu/actions/view.tsx +25 -0
  12. package/src/components/panel/add-new-button.tsx +22 -0
  13. package/src/components/panel/{pages-list/__tests__/page-list-item.test.tsx → posts-list/__tests__/post-list-item.test.tsx} +14 -11
  14. package/src/components/panel/{pages-list/__tests__/pages-collapsible-list.test.tsx → posts-list/__tests__/posts-collapsible-list.test.tsx} +6 -9
  15. package/src/components/panel/{pages-list → posts-list}/collapsible-list.tsx +4 -4
  16. package/src/components/panel/posts-list/list-items/edit-mode-template.tsx +103 -0
  17. package/src/components/panel/posts-list/list-items/list-item-create.tsx +25 -0
  18. package/src/components/panel/posts-list/list-items/list-item-duplicate.tsx +29 -0
  19. package/src/components/panel/posts-list/list-items/list-item-rename.tsx +33 -0
  20. package/src/components/panel/posts-list/list-items/list-item-view.tsx +87 -0
  21. package/src/components/panel/posts-list/post-list-item.tsx +29 -0
  22. package/src/components/panel/posts-list/posts-collapsible-list.tsx +44 -0
  23. package/src/components/panel/shell.tsx +14 -13
  24. package/src/contexts/post-list-context.tsx +73 -0
  25. package/src/hooks/__tests__/use-posts.test.ts +1 -1
  26. package/src/components/panel/actions-menu/page-actions-menu.tsx +0 -29
  27. package/src/components/panel/add-new-page-button.tsx +0 -15
  28. package/src/components/panel/pages-actions/duplicate.tsx +0 -14
  29. package/src/components/panel/pages-actions/rename.tsx +0 -14
  30. package/src/components/panel/pages-actions/view.tsx +0 -14
  31. package/src/components/panel/pages-list/page-list-item.tsx +0 -66
  32. package/src/components/panel/pages-list/pages-collapsible-list.tsx +0 -37
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+ import { Post } from '../../../types';
3
+ import ListItemRename from './list-items/list-item-rename';
4
+ import ListItemCreate from './list-items/list-item-create';
5
+ import ListItemDuplicate from './list-items/list-item-duplicate';
6
+ import ListItemView from './list-items/list-item-view';
7
+ import { usePostListContext } from '../../../contexts/post-list-context';
8
+
9
+ export default function PostListItem( { post }: { post?: Post } ) {
10
+ const { editMode } = usePostListContext();
11
+
12
+ if ( 'rename' === editMode.mode && post?.id && post?.id === editMode.details.postId ) {
13
+ return <ListItemRename post={ post } />;
14
+ }
15
+
16
+ if ( 'create' === editMode.mode && ! post ) {
17
+ return <ListItemCreate />;
18
+ }
19
+
20
+ if ( 'duplicate' === editMode.mode && ! post ) {
21
+ return <ListItemDuplicate />;
22
+ }
23
+
24
+ if ( ! post ) {
25
+ return null;
26
+ }
27
+
28
+ return <ListItemView post={ post } />;
29
+ }
@@ -0,0 +1,44 @@
1
+ import * as React from 'react';
2
+ import { PageTypeIcon } from '@elementor/icons';
3
+ import { Skeleton, Box, List } from '@elementor/ui';
4
+ import { usePosts } from '../../../hooks/use-posts';
5
+ import { usePostListContext } from '../../../contexts/post-list-context';
6
+ import { postTypesMap } from '../../../api/post';
7
+ import CollapsibleList from './collapsible-list';
8
+ import PostListItem from './post-list-item';
9
+
10
+ type Props = {
11
+ isOpenByDefault?: boolean,
12
+ }
13
+
14
+ export default function PostsCollapsibleList( { isOpenByDefault = false }: Props ) {
15
+ const { type, editMode } = usePostListContext();
16
+ const { data: posts, isLoading: postsLoading } = usePosts( type );
17
+
18
+ if ( ! posts || postsLoading ) {
19
+ return (
20
+ <Box spacing={ 4 } sx={ { px: 6 } }>
21
+ <Skeleton variant="text" sx={ { fontSize: '2rem' } } />
22
+ <Skeleton variant="rounded" width="100%" height="48" />
23
+ </Box>
24
+ );
25
+ }
26
+
27
+ const label = `${ postTypesMap[ type ].labels.plural_name } (${ posts.length.toString() })`;
28
+
29
+ return (
30
+ <List dense>
31
+ <CollapsibleList
32
+ label={ label }
33
+ Icon={ PageTypeIcon }
34
+ isOpenByDefault={ isOpenByDefault || false }
35
+ >
36
+ { posts.map( ( post ) => <PostListItem key={ post.id } post={ post } /> ) }
37
+ {
38
+ [ 'duplicate', 'create' ].includes( editMode.mode ) &&
39
+ <PostListItem />
40
+ }
41
+ </CollapsibleList>
42
+ </List>
43
+ );
44
+ }
@@ -1,9 +1,10 @@
1
1
  import * as React from 'react';
2
- import { Box, List } from '@elementor/ui';
2
+ import { Box } from '@elementor/ui';
3
3
  import { Panel, PanelBody, PanelHeader, PanelHeaderTitle } from '@elementor/editor-panels';
4
- import PagesCollapsibleList from './pages-list/pages-collapsible-list';
5
4
  import { __ } from '@wordpress/i18n';
6
- import AddNewPageButton from './add-new-page-button';
5
+ import PostsCollapsibleList from './posts-list/posts-collapsible-list';
6
+ import { PostListContextProvider } from '../../contexts/post-list-context';
7
+ import AddNewButton from './add-new-button';
7
8
 
8
9
  const Shell = () => {
9
10
  return (
@@ -12,16 +13,16 @@ const Shell = () => {
12
13
  <PanelHeaderTitle>{ __( 'Pages', 'elementor' ) }</PanelHeaderTitle>
13
14
  </PanelHeader>
14
15
  <PanelBody>
15
- <Box
16
- display="flex"
17
- justifyContent="flex-end"
18
- alignItems="center"
19
- >
20
- <AddNewPageButton />
21
- </Box>
22
- <List dense>
23
- <PagesCollapsibleList isOpenByDefault={ true } />
24
- </List>
16
+ <PostListContextProvider type={ 'page' }>
17
+ <Box
18
+ display="flex"
19
+ justifyContent="flex-end"
20
+ alignItems="center"
21
+ >
22
+ <AddNewButton />
23
+ </Box>
24
+ <PostsCollapsibleList isOpenByDefault={ true } />
25
+ </PostListContextProvider>
25
26
  </PanelBody>
26
27
  </Panel>
27
28
  );
@@ -0,0 +1,73 @@
1
+ import * as React from 'react';
2
+ import { useState, useContext, createContext, Dispatch, SetStateAction, ReactNode } from 'react';
3
+ import { Slug } from '../api/post';
4
+
5
+ export type EditMode = {
6
+ mode: 'rename',
7
+ details: {
8
+ postId: number,
9
+ },
10
+ } | {
11
+ mode: 'create',
12
+ details: Record<string, never>,
13
+ } | {
14
+ mode: 'duplicate',
15
+ details: {
16
+ postId: number,
17
+ title: string,
18
+ },
19
+ } | {
20
+ mode: 'none',
21
+ details: Record<string, never>,
22
+ };
23
+
24
+ type ContextType = {
25
+ type: Slug,
26
+ editMode: EditMode,
27
+ setEditMode: Dispatch<SetStateAction<EditMode>>,
28
+ resetEditMode: () => void,
29
+ };
30
+
31
+ const defaultValues: ContextType = {
32
+ type: 'page',
33
+ editMode: { mode: 'none', details: {} },
34
+ setEditMode: () => null,
35
+ resetEditMode: () => null,
36
+ };
37
+
38
+ export const PostListContext = createContext<ContextType>( defaultValues );
39
+
40
+ export const PostListContextProvider = ( {
41
+ type,
42
+ children,
43
+ }: {
44
+ type: ContextType[ 'type' ],
45
+ children: ReactNode,
46
+ } ) => {
47
+ const [ editMode, setEditMode ] = useState( defaultValues.editMode );
48
+
49
+ const resetEditMode = () => {
50
+ setEditMode( defaultValues.editMode );
51
+ };
52
+
53
+ return (
54
+ <PostListContext.Provider value={ {
55
+ type,
56
+ editMode,
57
+ setEditMode,
58
+ resetEditMode,
59
+ } }>
60
+ { children }
61
+ </PostListContext.Provider>
62
+ );
63
+ };
64
+
65
+ export function usePostListContext() {
66
+ const context = useContext( PostListContext );
67
+
68
+ if ( ! context ) {
69
+ throw new Error( 'The `usePostListContext()` hook must be used within an `<PostListContextProvider />`' );
70
+ }
71
+
72
+ return context;
73
+ }
@@ -27,7 +27,7 @@ describe( '@elementor/site-settings/use-posts', () => {
27
27
  const { component } = renderHookWithQuery( () => usePosts( 'page' ) );
28
28
 
29
29
  // Assert.
30
- const expectedPath = `/wp/v2/pages?status=any&per_page=-1&_fields=${ encodeURIComponent( 'id,type,title,link,status' ) }`;
30
+ const expectedPath = `/wp/v2/pages?status=any&per_page=-1&order=asc&_fields=${ encodeURIComponent( 'id,type,title,link,status' ) }`;
31
31
 
32
32
  expect( apiFetch ).toHaveBeenCalledWith( {
33
33
  path: expectedPath,
@@ -1,29 +0,0 @@
1
- import * as React from 'react';
2
- import { Divider, Menu, MenuProps } from '@elementor/ui';
3
- import Rename from '../pages-actions/rename';
4
- import Duplicate from '../pages-actions/duplicate';
5
- import Delete from '../pages-actions/delete';
6
- import { Post } from '../../../types';
7
- import View from '../pages-actions/view';
8
- import SetHome from '../pages-actions/set-home';
9
-
10
- type Props = MenuProps & {
11
- page: Post
12
- };
13
-
14
- export default function PageActionsMenu( { page, ...props }: Props ) {
15
- return (
16
- <Menu
17
- PaperProps={ { sx: { mt: 4, width: 200 } } }
18
- MenuListProps={ { dense: true } }
19
- { ...props }
20
- >
21
- <Rename />
22
- <Duplicate />
23
- <Delete page={ page } />
24
- <View />
25
- <Divider />
26
- <SetHome page={ page } />
27
- </Menu>
28
- );
29
- }
@@ -1,15 +0,0 @@
1
- import { Button } from '@elementor/ui';
2
- import { PlusIcon } from '@elementor/icons';
3
- import * as React from 'react';
4
-
5
- export default function AddNewPageButton() {
6
- return (
7
- <Button
8
- sx={ { mt: 4, mb: 4, mr: 5 } }
9
- startIcon={ <PlusIcon /> }
10
- onClick={ () => null }
11
- >
12
- Add New
13
- </Button>
14
- );
15
- }
@@ -1,14 +0,0 @@
1
- import * as React from 'react';
2
- import { __ } from '@wordpress/i18n';
3
- import { CopyIcon } from '@elementor/icons';
4
- import ActionMenuItem from '../actions-menu/action-menu-item';
5
-
6
- export default function Duplicate() {
7
- return (
8
- <ActionMenuItem
9
- title={ __( 'Duplicate', 'elementor' ) }
10
- icon={ CopyIcon }
11
- onClick={ () => null }
12
- />
13
- );
14
- }
@@ -1,14 +0,0 @@
1
- import * as React from 'react';
2
- import { EraseIcon } from '@elementor/icons';
3
- import { __ } from '@wordpress/i18n';
4
- import ActionMenuItem from '../actions-menu/action-menu-item';
5
-
6
- export default function Rename() {
7
- return (
8
- <ActionMenuItem
9
- title={ __( 'Rename', 'elementor' ) }
10
- icon={ EraseIcon }
11
- onClick={ () => null }
12
- />
13
- );
14
- }
@@ -1,14 +0,0 @@
1
- import * as React from 'react';
2
- import { EyeIcon } from '@elementor/icons';
3
- import { __ } from '@wordpress/i18n';
4
- import ActionMenuItem from '../actions-menu/action-menu-item';
5
-
6
- export default function View() {
7
- return (
8
- <ActionMenuItem
9
- title={ __( 'View Page', 'elementor' ) } // TODO 21/06/2023 : post label should come from post type
10
- icon={ EyeIcon }
11
- onClick={ () => null }
12
- />
13
- );
14
- }
@@ -1,66 +0,0 @@
1
- import * as React from 'react';
2
- import {
3
- bindMenu,
4
- bindTrigger,
5
- ListItem,
6
- ListItemButton,
7
- ListItemIcon,
8
- ListItemText,
9
- ToggleButton,
10
- usePopupState,
11
- } from '@elementor/ui';
12
- import { DotsVerticalIcon, HomeIcon } from '@elementor/icons';
13
- import { Post } from '../../../types';
14
- import { useActiveDocument, useNavigateToDocument } from '@elementor/editor-documents';
15
- import PageTitleAndStatus from '../../shared/page-title-and-status';
16
- import PageActionsMenu from '../actions-menu/page-actions-menu';
17
-
18
- export default function PageListItem( { page }: { page: Post } ) {
19
- const popupState = usePopupState( {
20
- variant: 'popover',
21
- popupId: 'page-actions',
22
- } );
23
-
24
- const activeDocument = useActiveDocument();
25
- const navigateToDocument = useNavigateToDocument();
26
-
27
- const isActive = activeDocument?.id === page.id;
28
-
29
- return (
30
- <>
31
- <ListItem
32
- disablePadding
33
- secondaryAction={
34
- <ToggleButton
35
- value
36
- color="secondary"
37
- size="small"
38
- selected={ popupState.isOpen }
39
- { ...bindTrigger( popupState ) }
40
- >
41
- <DotsVerticalIcon fontSize="small" />
42
- </ToggleButton>
43
- }
44
- >
45
- <ListItemButton
46
- selected={ isActive }
47
- onClick={ () => navigateToDocument( page.id ) }
48
- dense
49
- >
50
- <ListItemIcon />
51
- <ListItemText
52
- disableTypography={ true }
53
- >
54
- <PageTitleAndStatus page={ page } />
55
- </ListItemText>
56
- { page.isHome &&
57
- <ListItemIcon>
58
- <HomeIcon color="disabled" />
59
- </ListItemIcon>
60
- }
61
- </ListItemButton>
62
- </ListItem>
63
- <PageActionsMenu page={ page } { ...bindMenu( popupState ) } />
64
- </>
65
- );
66
- }
@@ -1,37 +0,0 @@
1
- import * as React from 'react';
2
- import CollapsibleList from './collapsible-list';
3
- import { PageTypeIcon } from '@elementor/icons';
4
- import { Skeleton, Box } from '@elementor/ui';
5
- import PageListItem from './page-list-item';
6
- import { usePosts } from '../../../hooks/use-posts';
7
- import { __ } from '@wordpress/i18n';
8
-
9
- type Props = {
10
- isOpenByDefault?: boolean;
11
- }
12
-
13
- export default function PagesCollapsibleList( { isOpenByDefault = false }: Props ) {
14
- const { data: pages, isLoading: pagesLoading } = usePosts( 'page' );
15
-
16
- if ( ! pages || pagesLoading ) {
17
- return (
18
- <Box spacing={ 4 } sx={ { px: 6 } }>
19
- <Skeleton variant="text" sx={ { fontSize: '2rem' } } />
20
- <Skeleton variant="rounded" width="100%" height="48" />
21
- </Box>
22
- );
23
- }
24
-
25
- // translators: %s: Number of pages
26
- const label = __( 'Pages (%s)', 'elementor' ).replace( '%s', ( pages.length ).toString() );
27
-
28
- return (
29
- <CollapsibleList
30
- label={ label }
31
- Icon={ PageTypeIcon }
32
- isOpenByDefault={ isOpenByDefault }
33
- >
34
- { pages.map( ( page ) => <PageListItem key={ page.id } page={ page } /> ) }
35
- </CollapsibleList>
36
- );
37
- }