@elementor/editor-site-navigation 0.1.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.
@@ -0,0 +1,41 @@
1
+ import * as React from 'react';
2
+ import {
3
+ MenuItem,
4
+ ListSubheader,
5
+ Typography,
6
+ } from '@elementor/ui';
7
+
8
+ import { __ } from '@wordpress/i18n';
9
+ import DocTypeChip, { Props } from '../top-bar/chip-doc-type';
10
+ import { Post } from '../../hooks/use-recent-posts';
11
+
12
+ export type RecentPostsProps = {
13
+ recentPosts: Post[];
14
+ };
15
+
16
+ export default function PostsList( { recentPosts }: RecentPostsProps ) {
17
+ return (
18
+ <>
19
+ <ListSubheader sx={ { fontSize: 12, fontStyle: 'italic', pl: 4 } } component="div" id="nested-list-subheader">
20
+ { __( 'Recent', 'elementor' ) }
21
+ </ListSubheader>
22
+
23
+ { recentPosts.length
24
+ ? ( recentPosts.map( ( { title, edit_url: editUrl, type, id } ) => (
25
+ <MenuItem
26
+ key={ id }
27
+ component="a"
28
+ href={ editUrl }
29
+ >
30
+ { title }
31
+ <DocTypeChip postType={ type.post_type } docType={ type.doc_type as Props['docType'] } label={ type.label } />
32
+ </MenuItem>
33
+ ) ) ) : (
34
+ <Typography variant="caption" sx={ { color: 'grey.500', fontStyle: 'italic', p: 4 } } component="div" aria-label={ undefined }>
35
+ { __( 'There are no other pages or templates on this site yet.', 'elementor' ) }
36
+ </Typography>
37
+ )
38
+ }
39
+ </>
40
+ );
41
+ }
@@ -0,0 +1,55 @@
1
+ import * as React from 'react';
2
+ import {
3
+ bindMenu,
4
+ usePopupState,
5
+ bindTrigger,
6
+ Menu,
7
+ Button,
8
+ Box,
9
+ } from '@elementor/ui';
10
+ import { ChevronDownIcon } from '@elementor/icons';
11
+ import { useActiveDocument, useHostDocument } from '@elementor/editor-documents';
12
+ import Indicator from './indicator';
13
+ import PostsList from './posts-list';
14
+ import useRecentPosts from '../../hooks/use-recent-posts';
15
+
16
+ export default function RecentlyEdited() {
17
+ const activeDocument = useActiveDocument();
18
+ const hostDocument = useHostDocument();
19
+ const document = activeDocument && activeDocument.type.value !== 'kit'
20
+ ? activeDocument
21
+ : hostDocument;
22
+
23
+ const { recentPosts } = useRecentPosts( document?.id );
24
+
25
+ const popupState = usePopupState( {
26
+ variant: 'popover',
27
+ popupId: 'elementor-v2-top-bar-recently-edited',
28
+ } );
29
+
30
+ if ( ! document ) {
31
+ return null;
32
+ }
33
+
34
+ return (
35
+ <Box sx={ { cursor: 'default' } }>
36
+ <Button
37
+ color="inherit"
38
+ endIcon={ <ChevronDownIcon /> }
39
+ { ...bindTrigger( popupState ) }
40
+ >
41
+ <Indicator
42
+ title={ document.title }
43
+ status={ document.status }
44
+ />
45
+ </Button>
46
+
47
+ <Menu
48
+ PaperProps={ { sx: { minWidth: 314 } } }
49
+ { ...bindMenu( popupState ) }
50
+ >
51
+ <PostsList recentPosts={ recentPosts } />
52
+ </Menu>
53
+ </Box>
54
+ );
55
+ }
@@ -0,0 +1,49 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { DocType } from '../types';
3
+ import apiFetch from '@wordpress/api-fetch';
4
+ import { addQueryArgs } from '@wordpress/url';
5
+
6
+ export interface Post {
7
+ id: number,
8
+ title: string,
9
+ edit_url: string,
10
+ type: {
11
+ post_type: string,
12
+ doc_type: DocType,
13
+ label: string,
14
+ },
15
+ date_modified: number,
16
+ }
17
+
18
+ export default function useRecentPosts( documentId?: number ) {
19
+ const [ recentPosts, setRecentPosts ] = useState<Post[]>( [] );
20
+ const [ isLoading, setIsLoading ] = useState( false );
21
+
22
+ useEffect( () => {
23
+ if ( documentId ) {
24
+ setIsLoading( true );
25
+
26
+ fetchRecentlyEditedPosts( documentId ).then( ( posts ) => {
27
+ setRecentPosts( posts );
28
+ setIsLoading( false );
29
+ } );
30
+ }
31
+ }, [ documentId ] );
32
+
33
+ return {
34
+ isLoading,
35
+ recentPosts,
36
+ };
37
+ }
38
+
39
+ async function fetchRecentlyEditedPosts( documentId: number ) {
40
+ const queryParams = {
41
+ posts_per_page: 5,
42
+ post__not_in: documentId,
43
+ };
44
+
45
+ return await apiFetch( {
46
+ path: addQueryArgs( '/elementor/v1/site-navigation/recent-posts', queryParams ),
47
+ } ).then( ( response ) => response as Post[] )
48
+ .catch( () => [] );
49
+ }
package/src/index.ts ADDED
@@ -0,0 +1,3 @@
1
+ import init from './init';
2
+
3
+ init();
package/src/init.ts ADDED
@@ -0,0 +1,13 @@
1
+ import RecentlyEdited from './components/top-bar/recently-edited';
2
+ import { injectIntoPageIndication } from '@elementor/editor-app-bar';
3
+
4
+ export default function init() {
5
+ registerTopBarMenuItems();
6
+ }
7
+
8
+ function registerTopBarMenuItems() {
9
+ injectIntoPageIndication( {
10
+ name: 'document-recently-edited',
11
+ filler: RecentlyEdited,
12
+ } );
13
+ }
package/src/types.ts ADDED
@@ -0,0 +1 @@
1
+ export type DocType = 'header' | 'footer' | 'single-post' | 'single-page' | 'popup' | 'archive' | 'search-results' | 'loop-item' | 'error-404' | 'landing-page' | 'page' | 'section' | 'container' | 'wp-page' | 'wp-post';