@elementor/editor-site-navigation 0.3.0 → 0.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/CHANGELOG.md CHANGED
@@ -3,6 +3,18 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [0.4.0](https://github.com/elementor/elementor-packages/compare/@elementor/editor-site-navigation@0.3.0...@elementor/editor-site-navigation@0.4.0) (2023-05-21)
7
+
8
+
9
+ ### Features
10
+
11
+ * **editor-site-navigation:** change post without refresh [ED-10713] ([#39](https://github.com/elementor/elementor-packages/issues/39)) ([b72e82f](https://github.com/elementor/elementor-packages/commit/b72e82f9adb9c1237300cbf603f33f268f9f0400))
12
+ * **locations:** change api to support props for slots [ED-10730] ([#38](https://github.com/elementor/elementor-packages/issues/38)) ([44bec3c](https://github.com/elementor/elementor-packages/commit/44bec3cda1020037ba7105c6f05ce4baa8e3b376))
13
+
14
+
15
+
16
+
17
+
6
18
  # 0.3.0 (2023-05-16)
7
19
 
8
20
 
package/dist/index.js CHANGED
@@ -52,10 +52,10 @@ function getIconsMap() {
52
52
  }
53
53
 
54
54
  // src/components/top-bar/recently-edited.tsx
55
- var React4 = __toESM(require("react"));
56
- var import_ui4 = require("@elementor/ui");
55
+ var React5 = __toESM(require("react"));
56
+ var import_ui5 = require("@elementor/ui");
57
57
  var import_icons4 = require("@elementor/icons");
58
- var import_editor_documents = require("@elementor/editor-documents");
58
+ var import_editor_documents3 = require("@elementor/editor-documents");
59
59
 
60
60
  // src/components/top-bar/indicator.tsx
61
61
  var React = __toESM(require("react"));
@@ -79,10 +79,40 @@ function Tooltip(props) {
79
79
  );
80
80
  }
81
81
 
82
- // src/components/top-bar/posts-list.tsx
83
- var import_ui3 = require("@elementor/ui");
84
- var React3 = __toESM(require("react"));
85
- var import_i18n = require("@wordpress/i18n");
82
+ // src/hooks/use-recent-posts.ts
83
+ var import_react = require("react");
84
+ var import_api_fetch = __toESM(require("@wordpress/api-fetch"));
85
+ var import_url = require("@wordpress/url");
86
+ var endpointPath = "/elementor/v1/site-navigation/recent-posts";
87
+ function useRecentPosts(documentId) {
88
+ const [recentPosts, setRecentPosts] = (0, import_react.useState)([]);
89
+ const [isLoading, setIsLoading] = (0, import_react.useState)(false);
90
+ (0, import_react.useEffect)(() => {
91
+ if (documentId) {
92
+ setIsLoading(true);
93
+ fetchRecentlyEditedPosts(documentId).then((posts) => {
94
+ setRecentPosts(posts);
95
+ setIsLoading(false);
96
+ });
97
+ }
98
+ }, [documentId]);
99
+ return {
100
+ isLoading,
101
+ recentPosts
102
+ };
103
+ }
104
+ async function fetchRecentlyEditedPosts(documentId) {
105
+ const queryParams = {
106
+ posts_per_page: 5,
107
+ post__not_in: documentId
108
+ };
109
+ return await (0, import_api_fetch.default)({
110
+ path: (0, import_url.addQueryArgs)(endpointPath, queryParams)
111
+ }).then((response) => response).catch(() => []);
112
+ }
113
+
114
+ // src/components/top-bar/recently-edited.tsx
115
+ var import_i18n2 = require("@wordpress/i18n");
86
116
 
87
117
  // src/components/top-bar/chip-doc-type.tsx
88
118
  var import_icons2 = require("@elementor/icons");
@@ -104,132 +134,98 @@ function DocTypeChip({ postType, docType, label }) {
104
134
  );
105
135
  }
106
136
 
137
+ // src/components/top-bar/post-list-item.tsx
138
+ var import_ui3 = require("@elementor/ui");
139
+ var React3 = __toESM(require("react"));
140
+ var import_editor_documents = require("@elementor/editor-documents");
141
+ function PostListItem({ post, closePopup }) {
142
+ const navigateToDocument = (0, import_editor_documents.useNavigateToDocument)();
143
+ return /* @__PURE__ */ React3.createElement(import_ui3.MenuItem, { dense: true, sx: { width: "100%" }, onClick: () => {
144
+ closePopup();
145
+ navigateToDocument(post.id);
146
+ } }, post.title, /* @__PURE__ */ React3.createElement(DocTypeChip, { postType: post.type.post_type, docType: post.type.doc_type, label: post.type.label }));
147
+ }
148
+
149
+ // src/components/top-bar/create-post-list-item.tsx
150
+ var import_ui4 = require("@elementor/ui");
151
+ var React4 = __toESM(require("react"));
152
+
107
153
  // src/hooks/use-create-page.ts
108
- var import_api_fetch = __toESM(require("@wordpress/api-fetch"));
109
- var import_react = require("react");
110
- var endpointPath = "/elementor/v1/site-navigation/add-new-post";
111
- function useCreatePage({ onCreated: onCreated2 }) {
112
- const [isLoading, setIsLoading] = (0, import_react.useState)(false);
154
+ var import_api_fetch2 = __toESM(require("@wordpress/api-fetch"));
155
+ var import_react2 = require("react");
156
+ var endpointPath2 = "/elementor/v1/site-navigation/add-new-post";
157
+ function useCreatePage() {
158
+ const [isLoading, setIsLoading] = (0, import_react2.useState)(false);
113
159
  return {
114
160
  create: () => {
115
161
  setIsLoading(true);
116
- addNewPage().then((newPost) => newPost).then((newPost) => {
117
- setIsLoading(false);
118
- onCreated2(newPost.edit_url);
119
- }).catch(() => {
120
- setIsLoading(false);
121
- });
162
+ return addNewPage().then((newPost) => newPost).finally(() => setIsLoading(false));
122
163
  },
123
164
  isLoading
124
165
  };
125
166
  }
126
167
  async function addNewPage() {
127
- return await (0, import_api_fetch.default)({
128
- path: endpointPath,
168
+ return await (0, import_api_fetch2.default)({
169
+ path: endpointPath2,
129
170
  method: "POST",
130
171
  data: { post_type: "page" }
131
172
  });
132
173
  }
133
174
 
134
- // src/components/top-bar/posts-list.tsx
175
+ // src/components/top-bar/create-post-list-item.tsx
135
176
  var import_icons3 = require("@elementor/icons");
136
- function PostsList({ recentPosts }) {
137
- const { create, isLoading } = useCreatePage({ onCreated });
138
- return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(import_ui3.ListSubheader, { sx: { fontSize: 12, fontStyle: "italic", pl: 4 }, component: "div", id: "nested-list-subheader" }, (0, import_i18n.__)("Recent", "elementor")), recentPosts.length ? recentPosts.map(({ title, edit_url: editUrl, type, id }) => /* @__PURE__ */ React3.createElement(
139
- import_ui3.MenuItem,
140
- {
141
- dense: true,
142
- key: id,
143
- component: "a",
144
- href: editUrl
145
- },
146
- title,
147
- /* @__PURE__ */ React3.createElement(DocTypeChip, { postType: type.post_type, docType: type.doc_type, label: type.label })
148
- )) : /* @__PURE__ */ React3.createElement(import_ui3.Typography, { variant: "caption", sx: { color: "grey.500", fontStyle: "italic", p: 4 }, component: "div", "aria-label": void 0 }, (0, import_i18n.__)("There are no other pages or templates on this site yet.", "elementor")), /* @__PURE__ */ React3.createElement(import_ui3.Divider, null), /* @__PURE__ */ React3.createElement(
149
- import_ui3.MenuItem,
150
- {
151
- dense: true,
152
- size: "small",
153
- color: "inherit",
154
- component: "div",
155
- onClick: create
156
- },
157
- /* @__PURE__ */ React3.createElement(import_ui3.ListItemIcon, null, isLoading ? /* @__PURE__ */ React3.createElement(import_ui3.CircularProgress, null) : /* @__PURE__ */ React3.createElement(import_icons3.PlusIcon, null)),
158
- (0, import_i18n.__)("Add new page", "elementor")
159
- ));
160
- }
161
- function onCreated(url) {
162
- window.location.href = url;
163
- }
164
-
165
- // src/hooks/use-recent-posts.ts
166
- var import_react2 = require("react");
167
- var import_api_fetch2 = __toESM(require("@wordpress/api-fetch"));
168
- var import_url = require("@wordpress/url");
169
- var endpointPath2 = "/elementor/v1/site-navigation/recent-posts";
170
- function useRecentPosts(documentId) {
171
- const [recentPosts, setRecentPosts] = (0, import_react2.useState)([]);
172
- const [isLoading, setIsLoading] = (0, import_react2.useState)(false);
173
- (0, import_react2.useEffect)(() => {
174
- if (documentId) {
175
- setIsLoading(true);
176
- fetchRecentlyEditedPosts(documentId).then((posts) => {
177
- setRecentPosts(posts);
178
- setIsLoading(false);
179
- });
180
- }
181
- }, [documentId]);
182
- return {
183
- isLoading,
184
- recentPosts
185
- };
186
- }
187
- async function fetchRecentlyEditedPosts(documentId) {
188
- const queryParams = {
189
- posts_per_page: 5,
190
- post__not_in: documentId
191
- };
192
- return await (0, import_api_fetch2.default)({
193
- path: (0, import_url.addQueryArgs)(endpointPath2, queryParams)
194
- }).then((response) => response).catch(() => []);
177
+ var import_i18n = require("@wordpress/i18n");
178
+ var import_editor_documents2 = require("@elementor/editor-documents");
179
+ function CreatePostListItem({ closePopup }) {
180
+ const { create, isLoading } = useCreatePage();
181
+ const navigateToDocument = (0, import_editor_documents2.useNavigateToDocument)();
182
+ return /* @__PURE__ */ React4.createElement(import_ui4.MenuItem, { dense: true, size: "small", color: "inherit", component: "div", onClick: async () => {
183
+ const { id } = await create();
184
+ closePopup();
185
+ navigateToDocument(id);
186
+ } }, /* @__PURE__ */ React4.createElement(import_ui4.ListItemIcon, null, isLoading ? /* @__PURE__ */ React4.createElement(import_ui4.CircularProgress, null) : /* @__PURE__ */ React4.createElement(import_icons3.PlusIcon, null)), (0, import_i18n.__)("Add new page", "elementor"));
195
187
  }
196
188
 
197
189
  // src/components/top-bar/recently-edited.tsx
198
190
  function RecentlyEdited() {
199
- const activeDocument = (0, import_editor_documents.useActiveDocument)();
200
- const hostDocument = (0, import_editor_documents.useHostDocument)();
191
+ const activeDocument = (0, import_editor_documents3.useActiveDocument)();
192
+ const hostDocument = (0, import_editor_documents3.useHostDocument)();
201
193
  const document = activeDocument && activeDocument.type.value !== "kit" ? activeDocument : hostDocument;
202
194
  const { recentPosts } = useRecentPosts(document?.id);
203
- const popupState = (0, import_ui4.usePopupState)({
195
+ const popupState = (0, import_ui5.usePopupState)({
204
196
  variant: "popover",
205
197
  popupId: "elementor-v2-top-bar-recently-edited"
206
198
  });
207
199
  if (!document) {
208
200
  return null;
209
201
  }
210
- return /* @__PURE__ */ React4.createElement(import_ui4.Box, { sx: { cursor: "default" } }, /* @__PURE__ */ React4.createElement(
211
- import_ui4.Button,
202
+ return /* @__PURE__ */ React5.createElement(import_ui5.Box, { sx: { cursor: "default" } }, /* @__PURE__ */ React5.createElement(
203
+ import_ui5.Button,
212
204
  {
213
205
  color: "inherit",
214
206
  size: "small",
215
- endIcon: /* @__PURE__ */ React4.createElement(import_icons4.ChevronDownIcon, { fontSize: "small" }),
216
- ...(0, import_ui4.bindTrigger)(popupState)
207
+ endIcon: /* @__PURE__ */ React5.createElement(import_icons4.ChevronDownIcon, { fontSize: "small" }),
208
+ ...(0, import_ui5.bindTrigger)(popupState)
217
209
  },
218
- /* @__PURE__ */ React4.createElement(
210
+ /* @__PURE__ */ React5.createElement(
219
211
  Indicator,
220
212
  {
221
213
  title: document.title,
222
214
  status: document.status
223
215
  }
224
216
  )
225
- ), /* @__PURE__ */ React4.createElement(
226
- import_ui4.Menu,
217
+ ), /* @__PURE__ */ React5.createElement(
218
+ import_ui5.Menu,
227
219
  {
228
220
  MenuListProps: { component: "div" },
229
221
  PaperProps: { sx: { mt: 4, minWidth: 314 } },
230
- ...(0, import_ui4.bindMenu)(popupState)
222
+ ...(0, import_ui5.bindMenu)(popupState)
231
223
  },
232
- /* @__PURE__ */ React4.createElement(PostsList, { recentPosts })
224
+ /* @__PURE__ */ React5.createElement(import_ui5.ListSubheader, { sx: { fontSize: 12, fontStyle: "italic", pl: 4 }, component: "div", id: "nested-list-subheader" }, (0, import_i18n2.__)("Recent", "elementor")),
225
+ recentPosts.map((post) => /* @__PURE__ */ React5.createElement(PostListItem, { key: post.id, post, closePopup: popupState.close })),
226
+ recentPosts.length === 0 && /* @__PURE__ */ React5.createElement(import_ui5.Typography, { variant: "caption", sx: { color: "grey.500", fontStyle: "italic", p: 4 }, component: "div", "aria-label": void 0 }, (0, import_i18n2.__)("There are no other pages or templates on this site yet.", "elementor")),
227
+ /* @__PURE__ */ React5.createElement(import_ui5.Divider, null),
228
+ /* @__PURE__ */ React5.createElement(CreatePostListItem, { closePopup: popupState.close })
233
229
  ));
234
230
  }
235
231
 
@@ -240,7 +236,7 @@ function init() {
240
236
  }
241
237
  function registerTopBarMenuItems() {
242
238
  (0, import_editor_app_bar.injectIntoPageIndication)({
243
- name: "document-recently-edited",
239
+ id: "document-recently-edited",
244
240
  filler: RecentlyEdited
245
241
  });
246
242
  }
package/dist/index.mjs CHANGED
@@ -22,14 +22,17 @@ function getIconsMap() {
22
22
  }
23
23
 
24
24
  // src/components/top-bar/recently-edited.tsx
25
- import * as React4 from "react";
25
+ import * as React5 from "react";
26
26
  import {
27
27
  bindMenu,
28
28
  usePopupState,
29
29
  bindTrigger,
30
30
  Menu,
31
31
  Button,
32
- Box
32
+ Box,
33
+ ListSubheader,
34
+ Typography as Typography2,
35
+ Divider
33
36
  } from "@elementor/ui";
34
37
  import { ChevronDownIcon } from "@elementor/icons";
35
38
  import { useActiveDocument, useHostDocument } from "@elementor/editor-documents";
@@ -56,17 +59,40 @@ function Tooltip(props) {
56
59
  );
57
60
  }
58
61
 
59
- // src/components/top-bar/posts-list.tsx
60
- import {
61
- Divider,
62
- MenuItem,
63
- ListItemIcon,
64
- ListSubheader,
65
- Typography as Typography2,
66
- CircularProgress
67
- } from "@elementor/ui";
68
- import * as React3 from "react";
69
- import { __ } from "@wordpress/i18n";
62
+ // src/hooks/use-recent-posts.ts
63
+ import { useEffect, useState } from "react";
64
+ import apiFetch from "@wordpress/api-fetch";
65
+ import { addQueryArgs } from "@wordpress/url";
66
+ var endpointPath = "/elementor/v1/site-navigation/recent-posts";
67
+ function useRecentPosts(documentId) {
68
+ const [recentPosts, setRecentPosts] = useState([]);
69
+ const [isLoading, setIsLoading] = useState(false);
70
+ useEffect(() => {
71
+ if (documentId) {
72
+ setIsLoading(true);
73
+ fetchRecentlyEditedPosts(documentId).then((posts) => {
74
+ setRecentPosts(posts);
75
+ setIsLoading(false);
76
+ });
77
+ }
78
+ }, [documentId]);
79
+ return {
80
+ isLoading,
81
+ recentPosts
82
+ };
83
+ }
84
+ async function fetchRecentlyEditedPosts(documentId) {
85
+ const queryParams = {
86
+ posts_per_page: 5,
87
+ post__not_in: documentId
88
+ };
89
+ return await apiFetch({
90
+ path: addQueryArgs(endpointPath, queryParams)
91
+ }).then((response) => response).catch(() => []);
92
+ }
93
+
94
+ // src/components/top-bar/recently-edited.tsx
95
+ import { __ as __2 } from "@wordpress/i18n";
70
96
 
71
97
  // src/components/top-bar/chip-doc-type.tsx
72
98
  import {
@@ -90,94 +116,56 @@ function DocTypeChip({ postType, docType, label }) {
90
116
  );
91
117
  }
92
118
 
119
+ // src/components/top-bar/post-list-item.tsx
120
+ import { MenuItem } from "@elementor/ui";
121
+ import * as React3 from "react";
122
+ import { useNavigateToDocument } from "@elementor/editor-documents";
123
+ function PostListItem({ post, closePopup }) {
124
+ const navigateToDocument = useNavigateToDocument();
125
+ return /* @__PURE__ */ React3.createElement(MenuItem, { dense: true, sx: { width: "100%" }, onClick: () => {
126
+ closePopup();
127
+ navigateToDocument(post.id);
128
+ } }, post.title, /* @__PURE__ */ React3.createElement(DocTypeChip, { postType: post.type.post_type, docType: post.type.doc_type, label: post.type.label }));
129
+ }
130
+
131
+ // src/components/top-bar/create-post-list-item.tsx
132
+ import { CircularProgress, ListItemIcon, MenuItem as MenuItem2 } from "@elementor/ui";
133
+ import * as React4 from "react";
134
+
93
135
  // src/hooks/use-create-page.ts
94
- import apiFetch from "@wordpress/api-fetch";
95
- import { useState } from "react";
96
- var endpointPath = "/elementor/v1/site-navigation/add-new-post";
97
- function useCreatePage({ onCreated: onCreated2 }) {
98
- const [isLoading, setIsLoading] = useState(false);
136
+ import apiFetch2 from "@wordpress/api-fetch";
137
+ import { useState as useState2 } from "react";
138
+ var endpointPath2 = "/elementor/v1/site-navigation/add-new-post";
139
+ function useCreatePage() {
140
+ const [isLoading, setIsLoading] = useState2(false);
99
141
  return {
100
142
  create: () => {
101
143
  setIsLoading(true);
102
- addNewPage().then((newPost) => newPost).then((newPost) => {
103
- setIsLoading(false);
104
- onCreated2(newPost.edit_url);
105
- }).catch(() => {
106
- setIsLoading(false);
107
- });
144
+ return addNewPage().then((newPost) => newPost).finally(() => setIsLoading(false));
108
145
  },
109
146
  isLoading
110
147
  };
111
148
  }
112
149
  async function addNewPage() {
113
- return await apiFetch({
114
- path: endpointPath,
150
+ return await apiFetch2({
151
+ path: endpointPath2,
115
152
  method: "POST",
116
153
  data: { post_type: "page" }
117
154
  });
118
155
  }
119
156
 
120
- // src/components/top-bar/posts-list.tsx
157
+ // src/components/top-bar/create-post-list-item.tsx
121
158
  import { PlusIcon } from "@elementor/icons";
122
- function PostsList({ recentPosts }) {
123
- const { create, isLoading } = useCreatePage({ onCreated });
124
- return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(ListSubheader, { sx: { fontSize: 12, fontStyle: "italic", pl: 4 }, component: "div", id: "nested-list-subheader" }, __("Recent", "elementor")), recentPosts.length ? recentPosts.map(({ title, edit_url: editUrl, type, id }) => /* @__PURE__ */ React3.createElement(
125
- MenuItem,
126
- {
127
- dense: true,
128
- key: id,
129
- component: "a",
130
- href: editUrl
131
- },
132
- title,
133
- /* @__PURE__ */ React3.createElement(DocTypeChip, { postType: type.post_type, docType: type.doc_type, label: type.label })
134
- )) : /* @__PURE__ */ React3.createElement(Typography2, { variant: "caption", sx: { color: "grey.500", fontStyle: "italic", p: 4 }, component: "div", "aria-label": void 0 }, __("There are no other pages or templates on this site yet.", "elementor")), /* @__PURE__ */ React3.createElement(Divider, null), /* @__PURE__ */ React3.createElement(
135
- MenuItem,
136
- {
137
- dense: true,
138
- size: "small",
139
- color: "inherit",
140
- component: "div",
141
- onClick: create
142
- },
143
- /* @__PURE__ */ React3.createElement(ListItemIcon, null, isLoading ? /* @__PURE__ */ React3.createElement(CircularProgress, null) : /* @__PURE__ */ React3.createElement(PlusIcon, null)),
144
- __("Add new page", "elementor")
145
- ));
146
- }
147
- function onCreated(url) {
148
- window.location.href = url;
149
- }
150
-
151
- // src/hooks/use-recent-posts.ts
152
- import { useEffect, useState as useState2 } from "react";
153
- import apiFetch2 from "@wordpress/api-fetch";
154
- import { addQueryArgs } from "@wordpress/url";
155
- var endpointPath2 = "/elementor/v1/site-navigation/recent-posts";
156
- function useRecentPosts(documentId) {
157
- const [recentPosts, setRecentPosts] = useState2([]);
158
- const [isLoading, setIsLoading] = useState2(false);
159
- useEffect(() => {
160
- if (documentId) {
161
- setIsLoading(true);
162
- fetchRecentlyEditedPosts(documentId).then((posts) => {
163
- setRecentPosts(posts);
164
- setIsLoading(false);
165
- });
166
- }
167
- }, [documentId]);
168
- return {
169
- isLoading,
170
- recentPosts
171
- };
172
- }
173
- async function fetchRecentlyEditedPosts(documentId) {
174
- const queryParams = {
175
- posts_per_page: 5,
176
- post__not_in: documentId
177
- };
178
- return await apiFetch2({
179
- path: addQueryArgs(endpointPath2, queryParams)
180
- }).then((response) => response).catch(() => []);
159
+ import { __ } from "@wordpress/i18n";
160
+ import { useNavigateToDocument as useNavigateToDocument2 } from "@elementor/editor-documents";
161
+ function CreatePostListItem({ closePopup }) {
162
+ const { create, isLoading } = useCreatePage();
163
+ const navigateToDocument = useNavigateToDocument2();
164
+ return /* @__PURE__ */ React4.createElement(MenuItem2, { dense: true, size: "small", color: "inherit", component: "div", onClick: async () => {
165
+ const { id } = await create();
166
+ closePopup();
167
+ navigateToDocument(id);
168
+ } }, /* @__PURE__ */ React4.createElement(ListItemIcon, null, isLoading ? /* @__PURE__ */ React4.createElement(CircularProgress, null) : /* @__PURE__ */ React4.createElement(PlusIcon, null)), __("Add new page", "elementor"));
181
169
  }
182
170
 
183
171
  // src/components/top-bar/recently-edited.tsx
@@ -193,29 +181,33 @@ function RecentlyEdited() {
193
181
  if (!document) {
194
182
  return null;
195
183
  }
196
- return /* @__PURE__ */ React4.createElement(Box, { sx: { cursor: "default" } }, /* @__PURE__ */ React4.createElement(
184
+ return /* @__PURE__ */ React5.createElement(Box, { sx: { cursor: "default" } }, /* @__PURE__ */ React5.createElement(
197
185
  Button,
198
186
  {
199
187
  color: "inherit",
200
188
  size: "small",
201
- endIcon: /* @__PURE__ */ React4.createElement(ChevronDownIcon, { fontSize: "small" }),
189
+ endIcon: /* @__PURE__ */ React5.createElement(ChevronDownIcon, { fontSize: "small" }),
202
190
  ...bindTrigger(popupState)
203
191
  },
204
- /* @__PURE__ */ React4.createElement(
192
+ /* @__PURE__ */ React5.createElement(
205
193
  Indicator,
206
194
  {
207
195
  title: document.title,
208
196
  status: document.status
209
197
  }
210
198
  )
211
- ), /* @__PURE__ */ React4.createElement(
199
+ ), /* @__PURE__ */ React5.createElement(
212
200
  Menu,
213
201
  {
214
202
  MenuListProps: { component: "div" },
215
203
  PaperProps: { sx: { mt: 4, minWidth: 314 } },
216
204
  ...bindMenu(popupState)
217
205
  },
218
- /* @__PURE__ */ React4.createElement(PostsList, { recentPosts })
206
+ /* @__PURE__ */ React5.createElement(ListSubheader, { sx: { fontSize: 12, fontStyle: "italic", pl: 4 }, component: "div", id: "nested-list-subheader" }, __2("Recent", "elementor")),
207
+ recentPosts.map((post) => /* @__PURE__ */ React5.createElement(PostListItem, { key: post.id, post, closePopup: popupState.close })),
208
+ recentPosts.length === 0 && /* @__PURE__ */ React5.createElement(Typography2, { variant: "caption", sx: { color: "grey.500", fontStyle: "italic", p: 4 }, component: "div", "aria-label": void 0 }, __2("There are no other pages or templates on this site yet.", "elementor")),
209
+ /* @__PURE__ */ React5.createElement(Divider, null),
210
+ /* @__PURE__ */ React5.createElement(CreatePostListItem, { closePopup: popupState.close })
219
211
  ));
220
212
  }
221
213
 
@@ -226,7 +218,7 @@ function init() {
226
218
  }
227
219
  function registerTopBarMenuItems() {
228
220
  injectIntoPageIndication({
229
- name: "document-recently-edited",
221
+ id: "document-recently-edited",
230
222
  filler: RecentlyEdited
231
223
  });
232
224
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elementor/editor-site-navigation",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "private": false,
5
5
  "author": "Elementor Team",
6
6
  "homepage": "https://elementor.com/",
@@ -32,8 +32,8 @@
32
32
  "dev": "tsup src/index.ts --format esm --clean"
33
33
  },
34
34
  "dependencies": {
35
- "@elementor/editor-app-bar": "^0.3.0",
36
- "@elementor/editor-documents": "^0.3.0",
35
+ "@elementor/editor-app-bar": "^0.4.0",
36
+ "@elementor/editor-documents": "^0.4.0",
37
37
  "@elementor/icons": "^0.2.1",
38
38
  "@elementor/ui": "^1.4.50",
39
39
  "@wordpress/api-fetch": "^6.27.0",
@@ -46,5 +46,5 @@
46
46
  "elementor": {
47
47
  "type": "extension"
48
48
  },
49
- "gitHead": "ccd6099031737d52202ba98812e21d16fac4bef2"
49
+ "gitHead": "45afd449fda346eea0f8a431ebca7d6c1d518dd1"
50
50
  }
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
- import { render } from '@testing-library/react';
3
- import { useHostDocument, useActiveDocument } from '@elementor/editor-documents';
2
+ import { render, waitFor } from '@testing-library/react';
3
+ import { useHostDocument, useActiveDocument, useNavigateToDocument } from '@elementor/editor-documents';
4
4
  import RecentlyEdited from '../recently-edited';
5
5
  import { createMockDocument } from 'test-utils';
6
6
  import useRecentPosts, { Post } from '../../../hooks/use-recent-posts';
@@ -9,6 +9,7 @@ import useCreatePage from '../../../hooks/use-create-page';
9
9
  jest.mock( '@elementor/editor-documents', () => ( {
10
10
  useActiveDocument: jest.fn(),
11
11
  useHostDocument: jest.fn(),
12
+ useNavigateToDocument: jest.fn(),
12
13
  } ) );
13
14
 
14
15
  jest.mock( '../../../hooks/use-recent-posts', () => (
@@ -55,16 +56,18 @@ describe( '@elementor/recently-edited - Top bar add new page', () => {
55
56
  expect( label ).toBeInTheDocument();
56
57
  } );
57
58
 
58
- it( 'should trigger create page hook on click', () => {
59
+ it( 'should trigger create page hook on click', async () => {
59
60
  // Arrange.
60
61
  mockActiveDocument();
61
62
 
62
63
  const isLoading = false;
63
64
  const recentPosts: Post[] = [];
64
- const create = jest.fn();
65
+ const create = jest.fn().mockReturnValue( Promise.resolve( { id: 123 } ) );
66
+ const navigateToDocument = jest.fn();
65
67
 
66
68
  jest.mocked( useRecentPosts ).mockReturnValue( { isLoading, recentPosts } );
67
69
  jest.mocked( useCreatePage ).mockReturnValue( { isLoading, create } );
70
+ jest.mocked( useNavigateToDocument ).mockReturnValue( navigateToDocument );
68
71
 
69
72
  const { getByText, getAllByRole } = render( <RecentlyEdited /> );
70
73
 
@@ -76,7 +79,12 @@ describe( '@elementor/recently-edited - Top bar add new page', () => {
76
79
  addNewPage.click();
77
80
 
78
81
  // Assert.
79
- expect( create ).toHaveBeenCalledTimes( 1 );
82
+ await waitFor( () => {
83
+ expect( create ).toHaveBeenCalledTimes( 1 );
84
+
85
+ expect( navigateToDocument ).toHaveBeenCalledTimes( 1 );
86
+ expect( navigateToDocument ).toHaveBeenCalledWith( 123 );
87
+ } );
80
88
  } );
81
89
  } );
82
90
 
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { render } from '@testing-library/react';
3
- import { useHostDocument, useActiveDocument } from '@elementor/editor-documents';
3
+ import { useHostDocument, useActiveDocument, useNavigateToDocument } from '@elementor/editor-documents';
4
4
  import RecentlyEdited from '../recently-edited';
5
5
  import { createMockDocument } from 'test-utils';
6
6
  import useRecentPosts, { Post } from '../../../hooks/use-recent-posts';
@@ -8,6 +8,7 @@ import useRecentPosts, { Post } from '../../../hooks/use-recent-posts';
8
8
  jest.mock( '@elementor/editor-documents', () => ( {
9
9
  useActiveDocument: jest.fn(),
10
10
  useHostDocument: jest.fn(),
11
+ useNavigateToDocument: jest.fn(),
11
12
  } ) );
12
13
 
13
14
  jest.mock( '../../../hooks/use-recent-posts', () => (
@@ -175,4 +176,38 @@ describe( '@elementor/recently-edited - Top bar Recently Edited', () => {
175
176
 
176
177
  expect( getByText( 'Test post' ) ).toBeInTheDocument();
177
178
  } );
179
+
180
+ it( 'should navigate to document on click', () => {
181
+ // Arrange.
182
+ const navigateToDocument = jest.fn();
183
+
184
+ jest.mocked( useNavigateToDocument ).mockReturnValue( navigateToDocument );
185
+
186
+ jest.mocked( useRecentPosts ).mockReturnValue( {
187
+ isLoading: false,
188
+ recentPosts: [ {
189
+ id: 123,
190
+ title: 'Test post',
191
+ edit_url: 'some_url',
192
+ type: {
193
+ post_type: 'post',
194
+ doc_type: 'wp-post',
195
+ label: 'Post',
196
+ },
197
+ date_modified: 123,
198
+ } ],
199
+ } );
200
+
201
+ const { getByText, getByRole } = render( <RecentlyEdited /> );
202
+
203
+ // Open the posts list.
204
+ getByRole( 'button' ).click();
205
+
206
+ // Act.
207
+ getByText( 'Test post' ).click();
208
+
209
+ // Assert.
210
+ expect( navigateToDocument ).toHaveBeenCalledTimes( 1 );
211
+ expect( navigateToDocument ).toHaveBeenCalledWith( 123 );
212
+ } );
178
213
  } );
@@ -0,0 +1,26 @@
1
+ import { CircularProgress, ListItemIcon, MenuItem } from '@elementor/ui';
2
+ import * as React from 'react';
3
+ import useCreatePage from '../../hooks/use-create-page';
4
+ import { PlusIcon } from '@elementor/icons';
5
+ import { __ } from '@wordpress/i18n';
6
+ import { useNavigateToDocument } from '@elementor/editor-documents';
7
+
8
+ export function CreatePostListItem( { closePopup }: { closePopup: () => void } ) {
9
+ const { create, isLoading } = useCreatePage();
10
+ const navigateToDocument = useNavigateToDocument();
11
+
12
+ return (
13
+ <MenuItem dense size="small" color="inherit" component="div" onClick={ async () => {
14
+ const { id } = await create();
15
+
16
+ closePopup();
17
+ navigateToDocument( id );
18
+ } }>
19
+ <ListItemIcon>
20
+ { isLoading ? <CircularProgress /> : <PlusIcon /> }
21
+ </ListItemIcon>
22
+
23
+ { __( 'Add new page', 'elementor' ) }
24
+ </MenuItem>
25
+ );
26
+ }
@@ -0,0 +1,24 @@
1
+ import DocTypeChip from './chip-doc-type';
2
+ import { MenuItem, MenuItemProps } from '@elementor/ui';
3
+ import * as React from 'react';
4
+ import { Post } from '../../hooks/use-recent-posts';
5
+ import { useNavigateToDocument } from '@elementor/editor-documents';
6
+
7
+ type Props = MenuItemProps & {
8
+ post: Post;
9
+ closePopup: () => void;
10
+ }
11
+
12
+ export function PostListItem( { post, closePopup }: Props ) {
13
+ const navigateToDocument = useNavigateToDocument();
14
+
15
+ return (
16
+ <MenuItem dense sx={ { width: '100%' } } onClick={ () => {
17
+ closePopup();
18
+ navigateToDocument( post.id );
19
+ } }>
20
+ { post.title }
21
+ <DocTypeChip postType={ post.type.post_type } docType={ post.type.doc_type } label={ post.type.label } />
22
+ </MenuItem>
23
+ );
24
+ }
@@ -6,12 +6,17 @@ import {
6
6
  Menu,
7
7
  Button,
8
8
  Box,
9
+ ListSubheader,
10
+ Typography,
11
+ Divider,
9
12
  } from '@elementor/ui';
10
13
  import { ChevronDownIcon } from '@elementor/icons';
11
14
  import { useActiveDocument, useHostDocument } from '@elementor/editor-documents';
12
15
  import Indicator from './indicator';
13
- import PostsList from './posts-list';
14
16
  import useRecentPosts from '../../hooks/use-recent-posts';
17
+ import { __ } from '@wordpress/i18n';
18
+ import { PostListItem } from './post-list-item';
19
+ import { CreatePostListItem } from './create-post-list-item';
15
20
 
16
21
  export default function RecentlyEdited() {
17
22
  const activeDocument = useActiveDocument();
@@ -50,7 +55,23 @@ export default function RecentlyEdited() {
50
55
  PaperProps={ { sx: { mt: 4, minWidth: 314 } } }
51
56
  { ...bindMenu( popupState ) }
52
57
  >
53
- <PostsList recentPosts={ recentPosts } />
58
+ <ListSubheader sx={ { fontSize: 12, fontStyle: 'italic', pl: 4 } } component="div" id="nested-list-subheader">
59
+ { __( 'Recent', 'elementor' ) }
60
+ </ListSubheader>
61
+
62
+ { recentPosts.map( ( post ) => (
63
+ <PostListItem key={ post.id } post={ post } closePopup={ popupState.close } />
64
+ ) ) }
65
+
66
+ { recentPosts.length === 0 && (
67
+ <Typography variant="caption" sx={ { color: 'grey.500', fontStyle: 'italic', p: 4 } } component="div" aria-label={ undefined }>
68
+ { __( 'There are no other pages or templates on this site yet.', 'elementor' ) }
69
+ </Typography>
70
+ ) }
71
+
72
+ <Divider />
73
+
74
+ <CreatePostListItem closePopup={ popupState.close } />
54
75
  </Menu>
55
76
  </Box>
56
77
  );
@@ -17,8 +17,7 @@ describe( '@elementor/recently-edited/use-page', () => {
17
17
 
18
18
  it( 'should run useCreatePage hook', async () => {
19
19
  // Arrange.
20
- const onCreated = jest.fn();
21
- const { result } = renderHook( () => useCreatePage( { onCreated } ) );
20
+ const { result } = renderHook( useCreatePage );
22
21
  const newPost = {
23
22
  id: 1,
24
23
  edit_url: 'editurl.com',
@@ -6,28 +6,18 @@ export interface NewPost {
6
6
  edit_url: string,
7
7
  }
8
8
 
9
- export type Args = {
10
- onCreated: ( url : string ) => void;
11
- }
12
-
13
9
  export const endpointPath = '/elementor/v1/site-navigation/add-new-post';
14
10
 
15
- export default function useCreatePage( { onCreated }: Args ) {
11
+ export default function useCreatePage() {
16
12
  const [ isLoading, setIsLoading ] = useState( false );
17
13
 
18
14
  return {
19
15
  create: () => {
20
16
  setIsLoading( true );
21
17
 
22
- addNewPage()
18
+ return addNewPage()
23
19
  .then( ( newPost ) => newPost as NewPost )
24
- .then( ( newPost ) => {
25
- setIsLoading( false );
26
- onCreated( newPost.edit_url );
27
- } )
28
- .catch( () => {
29
- setIsLoading( false );
30
- } );
20
+ .finally( () => setIsLoading( false ) );
31
21
  },
32
22
  isLoading,
33
23
  };
package/src/init.ts CHANGED
@@ -7,7 +7,7 @@ export default function init() {
7
7
 
8
8
  function registerTopBarMenuItems() {
9
9
  injectIntoPageIndication( {
10
- name: 'document-recently-edited',
10
+ id: 'document-recently-edited',
11
11
  filler: RecentlyEdited,
12
12
  } );
13
13
  }
@@ -1,67 +0,0 @@
1
- import {
2
- Divider,
3
- MenuItem,
4
- ListItemIcon,
5
- ListSubheader,
6
- Typography,
7
- CircularProgress,
8
- } from '@elementor/ui';
9
-
10
- import * as React from 'react';
11
- import { __ } from '@wordpress/i18n';
12
- import DocTypeChip, { Props } from './chip-doc-type';
13
- import { Post } from '../../hooks/use-recent-posts';
14
- import useCreatePage from '../../hooks/use-create-page';
15
- import { PlusIcon } from '@elementor/icons';
16
-
17
- export type RecentPostsProps = {
18
- recentPosts: Post[];
19
- };
20
-
21
- export default function PostsList( { recentPosts }: RecentPostsProps ) {
22
- const { create, isLoading } = useCreatePage( { onCreated } );
23
-
24
- return (
25
- <>
26
- <ListSubheader sx={ { fontSize: 12, fontStyle: 'italic', pl: 4 } } component="div" id="nested-list-subheader">
27
- { __( 'Recent', 'elementor' ) }
28
- </ListSubheader>
29
-
30
- { recentPosts.length
31
- ? ( recentPosts.map( ( { title, edit_url: editUrl, type, id } ) => (
32
- <MenuItem
33
- dense
34
- key={ id }
35
- component="a"
36
- href={ editUrl }
37
- >
38
- { title }
39
- <DocTypeChip postType={ type.post_type } docType={ type.doc_type as Props['docType'] } label={ type.label } />
40
- </MenuItem>
41
- ) ) ) : (
42
- <Typography variant="caption" sx={ { color: 'grey.500', fontStyle: 'italic', p: 4 } } component="div" aria-label={ undefined }>
43
- { __( 'There are no other pages or templates on this site yet.', 'elementor' ) }
44
- </Typography>
45
- )
46
- }
47
- <Divider />
48
- <MenuItem
49
- dense
50
- size="small"
51
- color="inherit"
52
- component="div"
53
- onClick={ create }
54
- >
55
- <ListItemIcon>
56
- { isLoading ? <CircularProgress /> : <PlusIcon /> }
57
- </ListItemIcon>
58
-
59
- { __( 'Add new page', 'elementor' ) }
60
- </MenuItem>
61
- </>
62
- );
63
- }
64
-
65
- function onCreated( url: string ) {
66
- window.location.href = url;
67
- }