@elementor/editor-site-navigation 0.19.9 → 0.19.11

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 (38) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/index.js +324 -177
  3. package/dist/index.mjs +309 -163
  4. package/package.json +4 -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 +4 -4
  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 +25 -11
  25. package/src/components/panel/posts-list/list-items/list-item-view.tsx +8 -13
  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 +4 -3
  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 +23 -11
  31. package/src/components/top-bar/post-list-item.tsx +2 -2
  32. package/src/components/top-bar/recently-edited.tsx +11 -1
  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/hooks/use-rename-active-document.ts +23 -0
  38. package/src/types.ts +12 -0
package/dist/index.mjs CHANGED
@@ -60,35 +60,27 @@ function Tooltip(props) {
60
60
  }
61
61
 
62
62
  // src/hooks/use-recent-posts.ts
63
- import { useEffect, useState } from "react";
63
+ import { useQuery } from "@elementor/query";
64
+
65
+ // src/api/recent-posts.ts
64
66
  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(() => []);
67
+ var baseUrl = "/elementor/v1/site-navigation/recent-posts";
68
+ var NUMBER_OF_RECENT_POSTS = 6;
69
+ var getRequest = () => {
70
+ const queryParams = new URLSearchParams({
71
+ posts_per_page: `${NUMBER_OF_RECENT_POSTS}`
72
+ });
73
+ const path = `${baseUrl}?${queryParams.toString()}`;
74
+ return apiFetch({ path });
75
+ };
76
+
77
+ // src/hooks/use-recent-posts.ts
78
+ var recentPostsQueryKey = ["site-navigation", "recent-posts"];
79
+ function useRecentPosts() {
80
+ return useQuery({
81
+ queryKey: recentPostsQueryKey,
82
+ queryFn: () => getRequest()
83
+ });
92
84
  }
93
85
 
94
86
  // src/components/top-bar/recently-edited.tsx
@@ -174,10 +166,10 @@ import * as React4 from "react";
174
166
 
175
167
  // src/hooks/use-create-page.ts
176
168
  import apiFetch2 from "@wordpress/api-fetch";
177
- import { useState as useState2 } from "react";
178
- var endpointPath2 = "/elementor/v1/site-navigation/add-new-post";
169
+ import { useState } from "react";
170
+ var endpointPath = "/elementor/v1/site-navigation/add-new-post";
179
171
  function useCreatePage() {
180
- const [isLoading, setIsLoading] = useState2(false);
172
+ const [isLoading, setIsLoading] = useState(false);
181
173
  return {
182
174
  create: () => {
183
175
  setIsLoading(true);
@@ -188,7 +180,7 @@ function useCreatePage() {
188
180
  }
189
181
  async function addNewPage() {
190
182
  return await apiFetch2({
191
- path: endpointPath2,
183
+ path: endpointPath,
192
184
  method: "POST",
193
185
  data: { post_type: "page" }
194
186
  });
@@ -227,7 +219,14 @@ function RecentlyEdited() {
227
219
  const activeDocument = useActiveDocument();
228
220
  const hostDocument = useHostDocument();
229
221
  const document2 = activeDocument && activeDocument.type.value !== "kit" ? activeDocument : hostDocument;
230
- const { recentPosts } = useRecentPosts(document2?.id);
222
+ const { data } = useRecentPosts();
223
+ const getRecentPosts = () => {
224
+ if (!data) {
225
+ return [];
226
+ }
227
+ return data.filter((post) => post.id !== document2?.id).splice(0, NUMBER_OF_RECENT_POSTS - 1);
228
+ };
229
+ const recentPosts = getRecentPosts();
231
230
  const popupState = usePopupState({
232
231
  variant: "popover",
233
232
  popupId: "elementor-v2-top-bar-recently-edited"
@@ -280,24 +279,24 @@ function RecentlyEdited() {
280
279
  import { injectIntoPageIndication, toolsMenu } from "@elementor/editor-app-bar";
281
280
 
282
281
  // src/hooks/use-toggle-button-props.ts
283
- import { __ as __15 } from "@wordpress/i18n";
282
+ import { __ as __16 } from "@wordpress/i18n";
284
283
  import { PagesIcon } from "@elementor/icons";
285
284
 
286
285
  // src/components/panel/panel.ts
287
286
  import { __createPanel } from "@elementor/editor-panels";
288
287
 
289
288
  // src/components/panel/shell.tsx
290
- import * as React23 from "react";
289
+ import * as React25 from "react";
291
290
  import { Panel, PanelBody, PanelHeader, PanelHeaderTitle } from "@elementor/editor-panels";
292
- import { __ as __14 } from "@wordpress/i18n";
291
+ import { __ as __15 } from "@wordpress/i18n";
293
292
 
294
293
  // src/components/panel/posts-list/posts-collapsible-list.tsx
295
- import * as React22 from "react";
294
+ import * as React23 from "react";
296
295
  import { PageTypeIcon as PageTypeIcon2 } from "@elementor/icons";
297
- import { Skeleton, Box as Box3, List as List2 } from "@elementor/ui";
296
+ import { Skeleton, Box as Box4, List as List2 } from "@elementor/ui";
298
297
 
299
298
  // src/hooks/use-posts.ts
300
- import { useQuery } from "@elementor/query";
299
+ import { useQuery as useQuery2 } from "@elementor/query";
301
300
 
302
301
  // src/api/post.ts
303
302
  import apiFetch3 from "@wordpress/api-fetch";
@@ -311,7 +310,7 @@ var postTypesMap = {
311
310
  rest_base: "pages"
312
311
  }
313
312
  };
314
- var getRequest = (postTypeSlug) => {
313
+ var getRequest2 = (postTypeSlug) => {
315
314
  const baseUri = `/wp/v2/${postTypesMap[postTypeSlug].rest_base}`;
316
315
  const keys = ["id", "type", "title", "link", "status"];
317
316
  const queryParams = new URLSearchParams({
@@ -362,27 +361,29 @@ var duplicateRequest = (originalPost) => {
362
361
  // src/hooks/use-posts.ts
363
362
  var postsQueryKey = (postTypeSlug) => ["site-navigation", "posts", postTypeSlug];
364
363
  function usePosts(postTypeSlug) {
365
- return useQuery({
364
+ return useQuery2({
366
365
  queryKey: postsQueryKey(postTypeSlug),
367
- queryFn: () => getRequest(postTypeSlug)
366
+ queryFn: () => getRequest2(postTypeSlug)
368
367
  });
369
368
  }
370
369
 
371
370
  // src/contexts/post-list-context.tsx
372
371
  import * as React6 from "react";
373
- import { useState as useState3, useContext, createContext } from "react";
372
+ import { useState as useState2, useContext, createContext } from "react";
374
373
  var defaultValues = {
375
374
  type: "page",
376
375
  editMode: { mode: "none", details: {} },
377
376
  setEditMode: () => null,
378
- resetEditMode: () => null
377
+ resetEditMode: () => null,
378
+ setError: () => null
379
379
  };
380
380
  var PostListContext = createContext(defaultValues);
381
381
  var PostListContextProvider = ({
382
382
  type,
383
+ setError,
383
384
  children
384
385
  }) => {
385
- const [editMode, setEditMode] = useState3(defaultValues.editMode);
386
+ const [editMode, setEditMode] = useState2(defaultValues.editMode);
386
387
  const resetEditMode = () => {
387
388
  setEditMode(defaultValues.editMode);
388
389
  };
@@ -390,7 +391,8 @@ var PostListContextProvider = ({
390
391
  type,
391
392
  editMode,
392
393
  setEditMode,
393
- resetEditMode
394
+ resetEditMode,
395
+ setError
394
396
  } }, children);
395
397
  };
396
398
  function usePostListContext() {
@@ -403,7 +405,7 @@ function usePostListContext() {
403
405
 
404
406
  // src/components/panel/posts-list/collapsible-list.tsx
405
407
  import * as React7 from "react";
406
- import { useState as useState4 } from "react";
408
+ import { useState as useState3 } from "react";
407
409
  import { Collapse, IconButton, List, ListItem, ListItemIcon as ListItemIcon2, ListItemText as ListItemText4, styled, Divider as Divider2 } from "@elementor/ui";
408
410
  import { ChevronDownIcon as ChevronDownIcon2 } from "@elementor/icons";
409
411
  var RotateIcon = styled(ChevronDownIcon2, {
@@ -414,22 +416,38 @@ var RotateIcon = styled(ChevronDownIcon2, {
414
416
  duration: theme.transitions.duration.standard
415
417
  })
416
418
  }));
419
+ var StyledListItemIcon = styled(ListItemIcon2)(({ theme }) => ({
420
+ minWidth: theme.spacing(4)
421
+ }));
417
422
  function CollapsibleList({
418
423
  label,
419
424
  Icon,
420
425
  isOpenByDefault = false,
421
426
  children
422
427
  }) {
423
- const [isOpen, setIsOpen] = useState4(isOpenByDefault);
424
- return /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(ListItem, null, /* @__PURE__ */ React7.createElement(ListItemIcon2, null, /* @__PURE__ */ React7.createElement(
428
+ const [isOpen, setIsOpen] = useState3(isOpenByDefault);
429
+ return /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(ListItem, null, /* @__PURE__ */ React7.createElement(StyledListItemIcon, { sx: {
430
+ color: "text.secondary"
431
+ } }, /* @__PURE__ */ React7.createElement(
425
432
  IconButton,
426
433
  {
427
434
  onClick: () => setIsOpen((prev) => !prev),
428
- sx: { color: "inherit" },
429
- size: "small"
435
+ size: "small",
436
+ sx: {
437
+ color: "inherit"
438
+ }
430
439
  },
431
440
  /* @__PURE__ */ React7.createElement(RotateIcon, { fontSize: "small", isOpen })
432
- )), /* @__PURE__ */ React7.createElement(ListItemIcon2, null, /* @__PURE__ */ React7.createElement(Icon, null)), /* @__PURE__ */ React7.createElement(ListItemText4, { primaryTypographyProps: { variant: "subtitle1", component: "span", sx: { fontWeight: "bold" } }, primary: label })), /* @__PURE__ */ React7.createElement(
441
+ )), /* @__PURE__ */ React7.createElement(
442
+ StyledListItemIcon,
443
+ {
444
+ size: "small",
445
+ sx: {
446
+ color: "inherit"
447
+ }
448
+ },
449
+ /* @__PURE__ */ React7.createElement(Icon, { fontSize: "small" })
450
+ ), /* @__PURE__ */ React7.createElement(ListItemText4, { primaryTypographyProps: { variant: "subtitle2", component: "span" }, primary: label })), /* @__PURE__ */ React7.createElement(
433
451
  Collapse,
434
452
  {
435
453
  in: isOpen,
@@ -478,25 +496,28 @@ function useInvalidatePosts(postTypeSlug) {
478
496
  const queryClient = useQueryClient();
479
497
  return (options = {}) => {
480
498
  const queryKey = postsQueryKey(postTypeSlug);
499
+ queryClient.invalidateQueries({ queryKey: recentPostsQueryKey }, options);
481
500
  return queryClient.invalidateQueries({ queryKey }, options);
482
501
  };
483
502
  }
484
503
 
485
504
  // src/components/panel/posts-list/list-items/edit-mode-template.tsx
486
505
  import * as React8 from "react";
487
- import { useState as useState5, useRef } from "react";
506
+ import { useState as useState4, useRef } from "react";
488
507
  import {
489
508
  Box,
490
509
  ListItem as ListItem2,
491
510
  TextField,
492
511
  IconButton as IconButton2,
493
- CircularProgress as CircularProgress2
512
+ CircularProgress as CircularProgress2,
513
+ ListItemText as ListItemText5
494
514
  } from "@elementor/ui";
495
515
  import { XIcon } from "@elementor/icons";
496
516
  import { __ as __4 } from "@wordpress/i18n";
497
517
  function EditModeTemplate({ postTitle, isLoading, callback }) {
498
- const [title, setTitle] = useState5(postTitle);
499
- const [inputError, setInputError] = useState5("");
518
+ const [title, setTitle] = useState4(postTitle);
519
+ const [touched, setTouched] = useState4(false);
520
+ const [inputError, setInputError] = useState4(null);
500
521
  const closeButton = useRef();
501
522
  const onBlur = (e) => {
502
523
  if (closeButton.current === e.relatedTarget) {
@@ -508,43 +529,48 @@ function EditModeTemplate({ postTitle, isLoading, callback }) {
508
529
  e.preventDefault();
509
530
  runCallback();
510
531
  };
511
- const validateInput = () => {
512
- let isValid = true;
513
- if (title.trim() === "") {
514
- isValid = false;
515
- setInputError(__4("Name is required", "elementor"));
516
- }
517
- return isValid;
532
+ const validateInput = (input) => {
533
+ return input.trim() !== "";
518
534
  };
519
535
  const runCallback = () => {
520
- if (!validateInput()) {
536
+ if (!validateInput(title)) {
521
537
  return;
522
538
  }
523
539
  callback(title);
524
540
  };
525
- return /* @__PURE__ */ React8.createElement(
541
+ const onChange = (e) => {
542
+ if (!touched) {
543
+ setTouched(true);
544
+ }
545
+ const value = e.target.value;
546
+ if (!validateInput(value)) {
547
+ setInputError(__4("Name is required", "elementor"));
548
+ } else {
549
+ setInputError(null);
550
+ }
551
+ setTitle(value);
552
+ };
553
+ return /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(
526
554
  ListItem2,
527
555
  {
528
- sx: { pt: 1, pl: 0 },
529
556
  secondaryAction: /* @__PURE__ */ React8.createElement(CloseButton, { isLoading, closeButton })
530
557
  },
531
- /* @__PURE__ */ React8.createElement(Box, { width: "100%", sx: { ml: 4, pr: 3 }, component: "form", onSubmit: onFormSubmit }, /* @__PURE__ */ React8.createElement(
558
+ /* @__PURE__ */ React8.createElement(Box, { width: "100%", component: "form", onSubmit: onFormSubmit }, /* @__PURE__ */ React8.createElement(
532
559
  TextField,
533
560
  {
534
561
  autoFocus: true,
535
562
  fullWidth: true,
536
563
  value: title,
537
- onChange: (e) => setTitle(e.target.value),
564
+ onChange,
538
565
  disabled: isLoading,
539
566
  error: !!inputError,
540
567
  onBlur,
541
568
  variant: "outlined",
542
569
  color: "secondary",
543
- size: "small",
544
- margin: "dense"
570
+ size: "small"
545
571
  }
546
572
  ))
547
- );
573
+ ), inputError && /* @__PURE__ */ React8.createElement(ListItem2, null, /* @__PURE__ */ React8.createElement(ListItemText5, { sx: { color: "error.main" } }, inputError)));
548
574
  }
549
575
  function CloseButton({ isLoading, closeButton }) {
550
576
  const { resetEditMode } = usePostListContext();
@@ -561,24 +587,58 @@ function CloseButton({ isLoading, closeButton }) {
561
587
  );
562
588
  }
563
589
 
590
+ // src/components/panel/posts-list/list-items/list-item-rename.tsx
591
+ import { __useActiveDocument as useActiveDocument2 } from "@elementor/editor-documents";
592
+
593
+ // src/hooks/use-rename-active-document.ts
594
+ import { __privateRunCommand as runCommand } from "@elementor/editor-v1-adapters";
595
+ function getV1DocumentsManager() {
596
+ const documentsManager = window.elementor?.documents;
597
+ if (!documentsManager) {
598
+ throw new Error("Elementor Editor V1 documents manager not found");
599
+ }
600
+ return documentsManager;
601
+ }
602
+ function useRenameActiveDocument() {
603
+ return async (title) => {
604
+ const currentDocument = getV1DocumentsManager().getCurrent();
605
+ const container = currentDocument.container;
606
+ await runCommand("document/elements/settings", {
607
+ container,
608
+ settings: { post_title: title }
609
+ });
610
+ };
611
+ }
612
+
564
613
  // src/components/panel/posts-list/list-items/list-item-rename.tsx
565
614
  function ListItemRename({ post }) {
566
615
  const { type, resetEditMode } = usePostListContext();
567
616
  const { updatePost } = usePostActions(type);
568
- const renamePostCallback = (inputValue) => {
569
- if (inputValue === post.title.rendered) {
617
+ const { setError } = usePostListContext();
618
+ const activeDocument = useActiveDocument2();
619
+ const rename = useRenameActiveDocument();
620
+ const isActive = activeDocument?.id === post.id;
621
+ const title = isActive ? activeDocument?.title : post.title.rendered;
622
+ const renamePostCallback = async (inputValue) => {
623
+ if (inputValue === title) {
570
624
  resetEditMode();
571
625
  }
572
- updatePost.mutateAsync({
573
- id: post.id,
574
- title: inputValue
575
- }, {
576
- onSuccess: () => {
577
- resetEditMode();
626
+ try {
627
+ if (isActive) {
628
+ await rename(inputValue);
629
+ } else {
630
+ await updatePost.mutateAsync({
631
+ id: post.id,
632
+ title: inputValue
633
+ });
578
634
  }
579
- });
635
+ } catch (e) {
636
+ setError();
637
+ } finally {
638
+ resetEditMode();
639
+ }
580
640
  };
581
- return /* @__PURE__ */ React9.createElement(EditModeTemplate, { postTitle: post.title.rendered, isLoading: updatePost.isPending, callback: renamePostCallback });
641
+ return /* @__PURE__ */ React9.createElement(EditModeTemplate, { postTitle: title, isLoading: updatePost.isPending, callback: renamePostCallback });
582
642
  }
583
643
 
584
644
  // src/components/panel/posts-list/list-items/list-item-create.tsx
@@ -589,16 +649,19 @@ function ListItemCreate() {
589
649
  const { type, resetEditMode } = usePostListContext();
590
650
  const { createPost } = usePostActions(type);
591
651
  const navigateToDocument = useNavigateToDocument3();
592
- const createPostCallback = (inputValue) => {
593
- createPost.mutateAsync({
594
- title: inputValue,
595
- status: "draft"
596
- }, {
597
- onSuccess: (data) => {
598
- resetEditMode();
599
- navigateToDocument(data.id);
600
- }
601
- });
652
+ const { setError } = usePostListContext();
653
+ const createPostCallback = async (inputValue) => {
654
+ try {
655
+ const { id } = await createPost.mutateAsync({
656
+ title: inputValue,
657
+ status: "draft"
658
+ });
659
+ navigateToDocument(id);
660
+ } catch (e) {
661
+ setError();
662
+ } finally {
663
+ resetEditMode();
664
+ }
602
665
  };
603
666
  return /* @__PURE__ */ React10.createElement(EditModeTemplate, { postTitle: __5("New Page", "elementor"), isLoading: createPost.isPending, callback: createPostCallback });
604
667
  }
@@ -611,19 +674,22 @@ function ListItemDuplicate() {
611
674
  const { type, editMode, resetEditMode } = usePostListContext();
612
675
  const navigateToDocument = useNavigateToDocument4();
613
676
  const { duplicatePost } = usePostActions(type);
677
+ const { setError } = usePostListContext();
614
678
  if ("duplicate" !== editMode.mode) {
615
679
  return null;
616
680
  }
617
- const duplicatePostCallback = (inputValue) => {
618
- duplicatePost.mutateAsync({
619
- id: editMode.details.postId,
620
- title: inputValue
621
- }, {
622
- onSuccess: (data) => {
623
- resetEditMode();
624
- navigateToDocument(data.post_id);
625
- }
626
- });
681
+ const duplicatePostCallback = async (inputValue) => {
682
+ try {
683
+ const { post_id: postId } = await duplicatePost.mutateAsync({
684
+ id: editMode.details.postId,
685
+ title: inputValue
686
+ });
687
+ navigateToDocument(postId);
688
+ } catch (e) {
689
+ setError();
690
+ } finally {
691
+ resetEditMode();
692
+ }
627
693
  };
628
694
  return /* @__PURE__ */ React11.createElement(EditModeTemplate, { postTitle: `${editMode.details.title} ${__6("copy", "elementor")}`, isLoading: duplicatePost.isPending, callback: duplicatePostCallback });
629
695
  }
@@ -634,16 +700,15 @@ import {
634
700
  bindMenu as bindMenu2,
635
701
  bindTrigger as bindTrigger2,
636
702
  Divider as Divider4,
703
+ IconButton as IconButton3,
637
704
  ListItem as ListItem3,
638
- ListItemButton as ListItemButton2,
639
- ListItemIcon as ListItemIcon4,
640
- ListItemText as ListItemText6,
705
+ ListItemButton,
706
+ ListItemText as ListItemText7,
641
707
  Menu as Menu2,
642
- ToggleButton,
643
708
  usePopupState as usePopupState2
644
709
  } from "@elementor/ui";
645
710
  import { DotsVerticalIcon, HomeIcon as HomeIcon2 } from "@elementor/icons";
646
- import { __useActiveDocument as useActiveDocument3, __useNavigateToDocument as useNavigateToDocument5 } from "@elementor/editor-documents";
711
+ import { __useActiveDocument as useActiveDocument4, __useNavigateToDocument as useNavigateToDocument5 } from "@elementor/editor-documents";
647
712
 
648
713
  // src/components/shared/page-title-and-status.tsx
649
714
  import * as React12 from "react";
@@ -657,6 +722,7 @@ var PageStatus = ({ status }) => {
657
722
  {
658
723
  component: "span",
659
724
  variant: "body2",
725
+ color: "text.secondary",
660
726
  sx: {
661
727
  textTransform: "capitalize",
662
728
  fontStyle: "italic",
@@ -676,6 +742,7 @@ var PageTitle = ({ title }) => {
676
742
  {
677
743
  component: "span",
678
744
  variant: "body2",
745
+ color: "text.secondary",
679
746
  noWrap: true,
680
747
  sx: {
681
748
  flexBasis: "auto"
@@ -684,8 +751,8 @@ var PageTitle = ({ title }) => {
684
751
  modifiedTitle
685
752
  );
686
753
  };
687
- function PageTitleAndStatus({ page }) {
688
- return /* @__PURE__ */ React12.createElement(Box2, { display: "flex" }, /* @__PURE__ */ React12.createElement(PageTitle, { title: page.title.rendered }), "\xA0", /* @__PURE__ */ React12.createElement(PageStatus, { status: page.status }));
754
+ function PageTitleAndStatus({ title, status }) {
755
+ return /* @__PURE__ */ React12.createElement(Box2, { display: "flex" }, /* @__PURE__ */ React12.createElement(PageTitle, { title }), "\xA0", /* @__PURE__ */ React12.createElement(PageStatus, { status }));
689
756
  }
690
757
 
691
758
  // src/components/panel/actions-menu/actions/rename.tsx
@@ -696,20 +763,14 @@ import { __ as __7 } from "@wordpress/i18n";
696
763
  // src/components/panel/actions-menu/action-menu-item.tsx
697
764
  import * as React13 from "react";
698
765
  import {
699
- ListItemButton,
700
766
  ListItemIcon as ListItemIcon3,
701
- ListItemText as ListItemText5,
767
+ ListItemText as ListItemText6,
702
768
  MenuItem as MenuItem4
703
769
  } from "@elementor/ui";
704
- function ActionMenuItem({ title, icon: Icon, ListItemButtonProps }) {
705
- return /* @__PURE__ */ React13.createElement(MenuItem4, { disableGutters: true }, /* @__PURE__ */ React13.createElement(
706
- ListItemButton,
707
- {
708
- ...ListItemButtonProps
709
- },
710
- /* @__PURE__ */ React13.createElement(ListItemIcon3, null, /* @__PURE__ */ React13.createElement(Icon, null)),
711
- /* @__PURE__ */ React13.createElement(ListItemText5, { primary: title })
712
- ));
770
+ function ActionMenuItem({ title, icon: Icon, MenuItemProps: MenuItemProps3 }) {
771
+ return /* @__PURE__ */ React13.createElement(MenuItem4, { ...MenuItemProps3 }, /* @__PURE__ */ React13.createElement(ListItemIcon3, { sx: {
772
+ color: "inherit"
773
+ } }, /* @__PURE__ */ React13.createElement(Icon, null)), /* @__PURE__ */ React13.createElement(ListItemText6, { primary: title }));
713
774
  }
714
775
 
715
776
  // src/components/panel/actions-menu/actions/rename.tsx
@@ -720,7 +781,7 @@ function Rename({ post }) {
720
781
  {
721
782
  title: __7("Rename", "elementor"),
722
783
  icon: EraseIcon,
723
- ListItemButtonProps: {
784
+ MenuItemProps: {
724
785
  onClick: () => {
725
786
  setEditMode({
726
787
  mode: "rename",
@@ -755,7 +816,7 @@ function Duplicate({ post, popupState }) {
755
816
  {
756
817
  title: __8("Duplicate", "elementor"),
757
818
  icon: CopyIcon,
758
- ListItemButtonProps: {
819
+ MenuItemProps: {
759
820
  onClick
760
821
  }
761
822
  }
@@ -776,18 +837,18 @@ import {
776
837
  DialogTitle,
777
838
  Divider as Divider3
778
839
  } from "@elementor/ui";
779
- import { useState as useState6 } from "react";
780
- import { __useActiveDocument as useActiveDocument2 } from "@elementor/editor-documents";
840
+ import { useState as useState5 } from "react";
841
+ import { __useActiveDocument as useActiveDocument3 } from "@elementor/editor-documents";
781
842
  function Delete({ post }) {
782
- const [isDialogOpen, setIsDialogOpen] = useState6(false);
783
- const activeDocument = useActiveDocument2();
843
+ const [isDialogOpen, setIsDialogOpen] = useState5(false);
844
+ const activeDocument = useActiveDocument3();
784
845
  const isPostActive = activeDocument?.id === post.id;
785
846
  return /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(
786
847
  ActionMenuItem,
787
848
  {
788
849
  title: __9("Delete", "elementor"),
789
850
  icon: TrashIcon,
790
- ListItemButtonProps: {
851
+ MenuItemProps: {
791
852
  disabled: post.isHome || isPostActive,
792
853
  onClick: () => setIsDialogOpen(true),
793
854
  sx: { "&:hover": { color: "error.main" } }
@@ -798,9 +859,15 @@ function Delete({ post }) {
798
859
  function DeleteDialog({ post, setIsDialogOpen }) {
799
860
  const { type } = usePostListContext();
800
861
  const { deletePost } = usePostActions(type);
862
+ const { setError } = usePostListContext();
801
863
  const dialogTitle = sprintf(__9('Delete "%s"?', "elementor"), post.title.rendered);
802
864
  const deletePage = async () => {
803
- await deletePost.mutateAsync(post.id);
865
+ try {
866
+ await deletePost.mutateAsync(post.id);
867
+ } catch (e) {
868
+ setError();
869
+ setIsDialogOpen(false);
870
+ }
804
871
  };
805
872
  const handleCancel = () => {
806
873
  if (deletePost.isPending) {
@@ -834,7 +901,7 @@ function View({ post }) {
834
901
  {
835
902
  title,
836
903
  icon: EyeIcon,
837
- ListItemButtonProps: {
904
+ MenuItemProps: {
838
905
  onClick: () => window.open(post.link, "_blank")
839
906
  }
840
907
  }
@@ -869,10 +936,10 @@ var updateSettings = (settings) => {
869
936
  };
870
937
 
871
938
  // src/hooks/use-homepage.ts
872
- import { useQuery as useQuery2 } from "@elementor/query";
939
+ import { useQuery as useQuery3 } from "@elementor/query";
873
940
  var settingsQueryKey = () => ["site-navigation", "homepage"];
874
941
  function useHomepage() {
875
- return useQuery2({
942
+ return useQuery3({
876
943
  queryKey: settingsQueryKey(),
877
944
  queryFn: () => getSettings()
878
945
  });
@@ -898,17 +965,24 @@ function useInvalidateSettings() {
898
965
 
899
966
  // src/components/panel/actions-menu/actions/set-home.tsx
900
967
  import { CircularProgress as CircularProgress4 } from "@elementor/ui";
901
- function SetHome({ post }) {
968
+ function SetHome({ post, closeMenu }) {
902
969
  const { updateSettingsMutation } = useHomepageActions();
903
- const handleClick = () => {
904
- updateSettingsMutation.mutateAsync({ show_on_front: "page", page_on_front: post.id });
970
+ const { setError } = usePostListContext();
971
+ const handleClick = async () => {
972
+ try {
973
+ await updateSettingsMutation.mutateAsync({ show_on_front: "page", page_on_front: post.id });
974
+ } catch (error) {
975
+ setError();
976
+ } finally {
977
+ closeMenu();
978
+ }
905
979
  };
906
980
  return /* @__PURE__ */ React18.createElement(
907
981
  ActionMenuItem,
908
982
  {
909
983
  title: __11("Set as homepage", "elementor"),
910
984
  icon: !updateSettingsMutation.isPending ? HomeIcon : CircularProgress4,
911
- ListItemButtonProps: {
985
+ MenuItemProps: {
912
986
  disabled: !!post.isHome || post.status !== "publish" || updateSettingsMutation.isPending,
913
987
  onClick: handleClick
914
988
  }
@@ -919,7 +993,7 @@ function SetHome({ post }) {
919
993
  // src/components/panel/posts-list/list-items/list-item-view.tsx
920
994
  import { __ as __12 } from "@wordpress/i18n";
921
995
  function ListItemView({ post }) {
922
- const activeDocument = useActiveDocument3();
996
+ const activeDocument = useActiveDocument4();
923
997
  const navigateToDocument = useNavigateToDocument5();
924
998
  const popupState = usePopupState2({
925
999
  variant: "popover",
@@ -927,24 +1001,24 @@ function ListItemView({ post }) {
927
1001
  disableAutoFocus: true
928
1002
  });
929
1003
  const isActive = activeDocument?.id === post.id;
1004
+ const status = isActive ? activeDocument?.status.value : post.status;
1005
+ const title = isActive ? activeDocument?.title : post.title.rendered;
930
1006
  return /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement(
931
1007
  ListItem3,
932
1008
  {
933
1009
  disablePadding: true,
934
1010
  secondaryAction: /* @__PURE__ */ React19.createElement(
935
- ToggleButton,
1011
+ IconButton3,
936
1012
  {
937
1013
  value: true,
938
- color: "secondary",
939
1014
  size: "small",
940
- selected: popupState.isOpen,
941
1015
  ...bindTrigger2(popupState)
942
1016
  },
943
1017
  /* @__PURE__ */ React19.createElement(DotsVerticalIcon, { fontSize: "small" })
944
1018
  )
945
1019
  },
946
1020
  /* @__PURE__ */ React19.createElement(
947
- ListItemButton2,
1021
+ ListItemButton,
948
1022
  {
949
1023
  selected: isActive,
950
1024
  onClick: () => {
@@ -952,18 +1026,16 @@ function ListItemView({ post }) {
952
1026
  navigateToDocument(post.id);
953
1027
  }
954
1028
  },
955
- dense: true,
956
- disableGutters: true
1029
+ dense: true
957
1030
  },
958
- /* @__PURE__ */ React19.createElement(ListItemIcon4, null),
959
1031
  /* @__PURE__ */ React19.createElement(
960
- ListItemText6,
1032
+ ListItemText7,
961
1033
  {
962
1034
  disableTypography: true
963
1035
  },
964
- /* @__PURE__ */ React19.createElement(PageTitleAndStatus, { page: post })
1036
+ /* @__PURE__ */ React19.createElement(PageTitleAndStatus, { title, status })
965
1037
  ),
966
- post.isHome && /* @__PURE__ */ React19.createElement(ListItemIcon4, null, /* @__PURE__ */ React19.createElement(HomeIcon2, { titleAccess: __12("Homepage", "elementor"), color: "disabled" }))
1038
+ post.isHome && /* @__PURE__ */ React19.createElement(HomeIcon2, { titleAccess: __12("Homepage", "elementor"), color: "disabled" })
967
1039
  )
968
1040
  ), /* @__PURE__ */ React19.createElement(
969
1041
  Menu2,
@@ -977,7 +1049,7 @@ function ListItemView({ post }) {
977
1049
  /* @__PURE__ */ React19.createElement(Delete, { post }),
978
1050
  /* @__PURE__ */ React19.createElement(View, { post }),
979
1051
  /* @__PURE__ */ React19.createElement(Divider4, null),
980
- /* @__PURE__ */ React19.createElement(SetHome, { post })
1052
+ /* @__PURE__ */ React19.createElement(SetHome, { post, closeMenu: () => popupState.close() })
981
1053
  ));
982
1054
  }
983
1055
 
@@ -1010,61 +1082,135 @@ function AddNewButton() {
1010
1082
  Button3,
1011
1083
  {
1012
1084
  size: "small",
1013
- sx: { mt: 4, mb: 4, mr: 5 },
1014
1085
  startIcon: /* @__PURE__ */ React21.createElement(PlusIcon2, null),
1015
1086
  onClick: () => {
1016
1087
  setEditMode({ mode: "create", details: {} });
1088
+ },
1089
+ sx: {
1090
+ px: 1.5
1017
1091
  }
1018
1092
  },
1019
1093
  __13("Add New", "elementor")
1020
1094
  );
1021
1095
  }
1022
1096
 
1097
+ // src/components/panel/posts-list/error-state.tsx
1098
+ import { Error404TemplateIcon } from "@elementor/icons";
1099
+ import { Box as Box3, Link, Typography as Typography3 } from "@elementor/ui";
1100
+ import { __ as __14 } from "@wordpress/i18n";
1101
+ import * as React22 from "react";
1102
+ function ErrorState() {
1103
+ return /* @__PURE__ */ React22.createElement(Box3, { sx: {
1104
+ display: "flex",
1105
+ flexDirection: "column",
1106
+ justifyContent: "center",
1107
+ alignItems: "center",
1108
+ pt: "40px",
1109
+ gap: "16px"
1110
+ } }, /* @__PURE__ */ React22.createElement(Error404TemplateIcon, null), /* @__PURE__ */ React22.createElement(Box3, { sx: {
1111
+ display: "flex",
1112
+ flexDirection: "column",
1113
+ justifyContent: "center",
1114
+ alignItems: "center",
1115
+ gap: "8px"
1116
+ } }, /* @__PURE__ */ React22.createElement(Typography3, { variant: "body1", color: "text.primary" }, __14("We couldn\u2019t display your pages.", "elementor")), /* @__PURE__ */ React22.createElement(Box3, null, /* @__PURE__ */ React22.createElement(Typography3, { variant: "body2", color: "text.primary", sx: { textAlign: "center" } }, __14("It\u2019s probably a temporary issue.", "elementor")), /* @__PURE__ */ React22.createElement(Typography3, { variant: "body2", color: "text.primary", sx: { textAlign: "center" } }, __14("If the problem persists,", "elementor"), " ", /* @__PURE__ */ React22.createElement(Link, { target: "_blank", href: "https://go.elementor.com/wp-editor-support-open-ticket/" }, "Notify support")))));
1117
+ }
1118
+
1023
1119
  // src/components/panel/posts-list/posts-collapsible-list.tsx
1024
1120
  function PostsCollapsibleList({ isOpenByDefault = false }) {
1025
1121
  const { type, editMode } = usePostListContext();
1026
- const { data: posts, isLoading: postsLoading } = usePosts(type);
1122
+ const { data: posts, isLoading: postsLoading, isError: postsError } = usePosts(type);
1027
1123
  const { data: homepageSettings } = useHomepage();
1124
+ if (postsError) {
1125
+ return /* @__PURE__ */ React23.createElement(ErrorState, null);
1126
+ }
1028
1127
  if (!posts || postsLoading) {
1029
- return /* @__PURE__ */ React22.createElement(Box3, { sx: { px: 5 } }, /* @__PURE__ */ React22.createElement(
1030
- Box3,
1128
+ return /* @__PURE__ */ React23.createElement(Box4, { sx: { px: 5 } }, /* @__PURE__ */ React23.createElement(
1129
+ Box4,
1031
1130
  {
1032
1131
  display: "flex",
1033
1132
  justifyContent: "flex-end",
1034
1133
  alignItems: "center"
1035
1134
  },
1036
- /* @__PURE__ */ React22.createElement(Skeleton, { sx: { my: 4 }, animation: "wave", variant: "rounded", width: "110px", height: "28px" })
1037
- ), /* @__PURE__ */ React22.createElement(Box3, null, /* @__PURE__ */ React22.createElement(Skeleton, { sx: { my: 3 }, animation: "wave", variant: "rounded", width: "100%", height: "24px" }), /* @__PURE__ */ React22.createElement(Skeleton, { sx: { my: 3 }, animation: "wave", variant: "rounded", width: "70%", height: "24px" }), /* @__PURE__ */ React22.createElement(Skeleton, { sx: { my: 3 }, animation: "wave", variant: "rounded", width: "70%", height: "24px" }), /* @__PURE__ */ React22.createElement(Skeleton, { sx: { my: 3 }, animation: "wave", variant: "rounded", width: "70%", height: "24px" })));
1135
+ /* @__PURE__ */ React23.createElement(Skeleton, { sx: { my: 4 }, animation: "wave", variant: "rounded", width: "110px", height: "28px" })
1136
+ ), /* @__PURE__ */ React23.createElement(Box4, null, /* @__PURE__ */ React23.createElement(Skeleton, { sx: { my: 3 }, animation: "wave", variant: "rounded", width: "100%", height: "24px" }), /* @__PURE__ */ React23.createElement(Skeleton, { sx: { my: 3 }, animation: "wave", variant: "rounded", width: "70%", height: "24px" }), /* @__PURE__ */ React23.createElement(Skeleton, { sx: { my: 3 }, animation: "wave", variant: "rounded", width: "70%", height: "24px" }), /* @__PURE__ */ React23.createElement(Skeleton, { sx: { my: 3 }, animation: "wave", variant: "rounded", width: "70%", height: "24px" })));
1038
1137
  }
1039
1138
  const label = `${postTypesMap[type].labels.plural_name} (${posts.length.toString()})`;
1040
1139
  const isHomepageSet = homepageSettings?.show_on_front === "page" && !!homepageSettings?.page_on_front;
1041
1140
  const homepageId = isHomepageSet ? homepageSettings.page_on_front : null;
1042
- return /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement(
1043
- Box3,
1141
+ const mappedPosts = posts.map((post) => {
1142
+ if (post.id === homepageId) {
1143
+ return { ...post, isHome: true };
1144
+ }
1145
+ return post;
1146
+ });
1147
+ const sortedPosts = mappedPosts.sort((a, b) => {
1148
+ if (a.id === homepageId) {
1149
+ return -1;
1150
+ }
1151
+ if (b.id === homepageId) {
1152
+ return 1;
1153
+ }
1154
+ return 0;
1155
+ });
1156
+ return /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(
1157
+ Box4,
1044
1158
  {
1045
1159
  display: "flex",
1046
1160
  justifyContent: "flex-end",
1047
- alignItems: "center"
1161
+ alignItems: "center",
1162
+ sx: {
1163
+ py: 1,
1164
+ px: 2
1165
+ }
1048
1166
  },
1049
- /* @__PURE__ */ React22.createElement(AddNewButton, null)
1050
- ), /* @__PURE__ */ React22.createElement(List2, { dense: true }, /* @__PURE__ */ React22.createElement(
1167
+ /* @__PURE__ */ React23.createElement(AddNewButton, null)
1168
+ ), /* @__PURE__ */ React23.createElement(List2, { dense: true }, /* @__PURE__ */ React23.createElement(
1051
1169
  CollapsibleList,
1052
1170
  {
1053
1171
  label,
1054
1172
  Icon: PageTypeIcon2,
1055
1173
  isOpenByDefault: isOpenByDefault || false
1056
1174
  },
1057
- posts.map((post) => {
1058
- post = { ...post, isHome: post.id === homepageId };
1059
- return /* @__PURE__ */ React22.createElement(PostListItem2, { key: post.id, post });
1175
+ sortedPosts.map((post) => {
1176
+ return /* @__PURE__ */ React23.createElement(PostListItem2, { key: post.id, post });
1060
1177
  }),
1061
- ["duplicate", "create"].includes(editMode.mode) && /* @__PURE__ */ React22.createElement(PostListItem2, null)
1178
+ ["duplicate", "create"].includes(editMode.mode) && /* @__PURE__ */ React23.createElement(PostListItem2, null)
1062
1179
  )));
1063
1180
  }
1064
1181
 
1182
+ // src/components/panel/error-snackbar.tsx
1183
+ import { Snackbar, Alert, Typography as Typography4 } from "@elementor/ui";
1184
+ import * as React24 from "react";
1185
+ var ErrorSnackbar = ({ open, onClose }) => {
1186
+ return /* @__PURE__ */ React24.createElement(
1187
+ Snackbar,
1188
+ {
1189
+ open,
1190
+ onClose,
1191
+ anchorOrigin: {
1192
+ vertical: "bottom",
1193
+ horizontal: "left"
1194
+ }
1195
+ },
1196
+ /* @__PURE__ */ React24.createElement(Alert, { onClose, severity: "error", sx: { width: "100%" } }, /* @__PURE__ */ React24.createElement(
1197
+ Typography4,
1198
+ {
1199
+ component: "span",
1200
+ sx: {
1201
+ fontWeight: "bold"
1202
+ }
1203
+ },
1204
+ "We couldn\u2019t complete the action."
1205
+ ), " ", "Please try again")
1206
+ );
1207
+ };
1208
+ var error_snackbar_default = ErrorSnackbar;
1209
+
1065
1210
  // src/components/panel/shell.tsx
1066
1211
  var Shell = () => {
1067
- return /* @__PURE__ */ React23.createElement(Panel, null, /* @__PURE__ */ React23.createElement(PanelHeader, null, /* @__PURE__ */ React23.createElement(PanelHeaderTitle, null, __14("Pages", "elementor"))), /* @__PURE__ */ React23.createElement(PanelBody, null, /* @__PURE__ */ React23.createElement(PostListContextProvider, { type: "page" }, /* @__PURE__ */ React23.createElement(PostsCollapsibleList, { isOpenByDefault: true }))));
1212
+ const [isErrorSnackbarOpen, setIsErrorSnackbarOpen] = React25.useState(false);
1213
+ return /* @__PURE__ */ React25.createElement(Panel, null, /* @__PURE__ */ React25.createElement(PanelHeader, null, /* @__PURE__ */ React25.createElement(PanelHeaderTitle, null, __15("Pages", "elementor"))), /* @__PURE__ */ React25.createElement(PanelBody, null, /* @__PURE__ */ React25.createElement(PostListContextProvider, { type: "page", setError: () => setIsErrorSnackbarOpen(true) }, /* @__PURE__ */ React25.createElement(PostsCollapsibleList, { isOpenByDefault: true })), /* @__PURE__ */ React25.createElement(error_snackbar_default, { open: isErrorSnackbarOpen, onClose: () => setIsErrorSnackbarOpen(false) })));
1068
1214
  };
1069
1215
  var shell_default = Shell;
1070
1216
 
@@ -1083,7 +1229,7 @@ function useToggleButtonProps() {
1083
1229
  const { isOpen, isBlocked } = usePanelStatus();
1084
1230
  const { open, close } = usePanelActions();
1085
1231
  return {
1086
- title: __15("Pages", "elementor"),
1232
+ title: __16("Pages", "elementor"),
1087
1233
  icon: PagesIcon,
1088
1234
  onClick: () => isOpen ? close() : open(),
1089
1235
  selected: isOpen,