@elementor/editor-site-navigation 0.14.0 → 0.16.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,28 @@
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.16.0](https://github.com/elementor/elementor-packages/compare/@elementor/editor-site-navigation@0.15.0...@elementor/editor-site-navigation@0.16.0) (2023-07-30)
7
+
8
+
9
+ ### Features
10
+
11
+ * **site-navigation:** add delete action to pages panel [ED-10868] ([#94](https://github.com/elementor/elementor-packages/issues/94)) ([96447ff](https://github.com/elementor/elementor-packages/commit/96447ff3dede4681b10d904ee1ad9e82ef677392))
12
+
13
+
14
+
15
+
16
+
17
+ # [0.15.0](https://github.com/elementor/elementor-packages/compare/@elementor/editor-site-navigation@0.14.0...@elementor/editor-site-navigation@0.15.0) (2023-07-30)
18
+
19
+
20
+ ### Features
21
+
22
+ * **site-navigation:** add duplicate action to pages panel - fix [ED-10867] ([#96](https://github.com/elementor/elementor-packages/issues/96)) ([a1ece1b](https://github.com/elementor/elementor-packages/commit/a1ece1bf08657e8bc905cad59e3f9f65064b2f9a))
23
+
24
+
25
+
26
+
27
+
6
28
  # [0.14.0](https://github.com/elementor/elementor-packages/compare/@elementor/editor-site-navigation@0.13.0...@elementor/editor-site-navigation@0.14.0) (2023-07-27)
7
29
 
8
30
 
package/dist/index.js CHANGED
@@ -257,13 +257,13 @@ var import_icons15 = require("@elementor/icons");
257
257
  var import_editor_panels2 = require("@elementor/editor-panels");
258
258
 
259
259
  // src/components/panel/shell.tsx
260
- var React24 = __toESM(require("react"));
260
+ var React23 = __toESM(require("react"));
261
261
  var import_ui14 = require("@elementor/ui");
262
262
  var import_editor_panels = require("@elementor/editor-panels");
263
263
  var import_i18n13 = require("@wordpress/i18n");
264
264
 
265
265
  // src/components/panel/posts-list/posts-collapsible-list.tsx
266
- var React22 = __toESM(require("react"));
266
+ var React21 = __toESM(require("react"));
267
267
  var import_icons13 = require("@elementor/icons");
268
268
  var import_ui12 = require("@elementor/ui");
269
269
 
@@ -412,7 +412,7 @@ function CollapsibleList({
412
412
  }
413
413
 
414
414
  // src/components/panel/posts-list/post-list-item.tsx
415
- var React21 = __toESM(require("react"));
415
+ var React20 = __toESM(require("react"));
416
416
 
417
417
  // src/components/panel/posts-list/list-items/list-item-rename.tsx
418
418
  var React9 = __toESM(require("react"));
@@ -566,7 +566,7 @@ function ListItemCreate() {
566
566
  // src/components/panel/posts-list/list-items/list-item-duplicate.tsx
567
567
  var React11 = __toESM(require("react"));
568
568
  var import_i18n6 = require("@wordpress/i18n");
569
- function ListItemDuplicate({ post }) {
569
+ function ListItemDuplicate() {
570
570
  const { type, editMode, resetEditMode } = usePostListContext();
571
571
  const { duplicatePost } = usePostActions(type);
572
572
  if ("duplicate" !== editMode.mode) {
@@ -574,7 +574,7 @@ function ListItemDuplicate({ post }) {
574
574
  }
575
575
  const duplicatePostCallback = (inputValue) => {
576
576
  duplicatePost.mutateAsync({
577
- id: post.id,
577
+ id: editMode.details.postId,
578
578
  title: inputValue
579
579
  }, {
580
580
  onSuccess: () => {
@@ -586,7 +586,7 @@ function ListItemDuplicate({ post }) {
586
586
  }
587
587
 
588
588
  // src/components/panel/posts-list/list-items/list-item-view.tsx
589
- var React20 = __toESM(require("react"));
589
+ var React19 = __toESM(require("react"));
590
590
  var import_ui11 = require("@elementor/ui");
591
591
  var import_icons12 = require("@elementor/icons");
592
592
  var import_editor_documents5 = require("@elementor/editor-documents");
@@ -635,129 +635,158 @@ function PageTitleAndStatus({ page }) {
635
635
  }
636
636
 
637
637
  // src/components/panel/actions-menu/actions/rename.tsx
638
- var React15 = __toESM(require("react"));
638
+ var React14 = __toESM(require("react"));
639
639
  var import_icons7 = require("@elementor/icons");
640
640
  var import_i18n7 = require("@wordpress/i18n");
641
641
 
642
642
  // src/components/panel/actions-menu/action-menu-item.tsx
643
- var React14 = __toESM(require("react"));
644
-
645
- // src/components/panel/actions-menu/action-list-item.tsx
646
643
  var React13 = __toESM(require("react"));
647
644
  var import_ui9 = require("@elementor/ui");
648
- function ActionListItem({ title, icon: Icon, disabled, onClick }) {
649
- return /* @__PURE__ */ React13.createElement(
645
+ function ActionMenuItem({ title, icon: Icon, ListItemButtonProps }) {
646
+ return /* @__PURE__ */ React13.createElement(import_ui9.MenuItem, { disableGutters: true }, /* @__PURE__ */ React13.createElement(
650
647
  import_ui9.ListItemButton,
651
648
  {
652
- disabled,
653
- onClick
649
+ ...ListItemButtonProps
654
650
  },
655
651
  /* @__PURE__ */ React13.createElement(import_ui9.ListItemIcon, null, /* @__PURE__ */ React13.createElement(Icon, null)),
656
652
  /* @__PURE__ */ React13.createElement(import_ui9.ListItemText, null, title)
657
- );
658
- }
659
-
660
- // src/components/panel/actions-menu/action-menu-item.tsx
661
- var import_ui10 = require("@elementor/ui");
662
- function ActionMenuItem(props) {
663
- return /* @__PURE__ */ React14.createElement(import_ui10.MenuItem, { disableGutters: true }, /* @__PURE__ */ React14.createElement(ActionListItem, { ...props }));
653
+ ));
664
654
  }
665
655
 
666
656
  // src/components/panel/actions-menu/actions/rename.tsx
667
657
  function Rename({ post }) {
668
658
  const { setEditMode } = usePostListContext();
669
- return /* @__PURE__ */ React15.createElement(
659
+ return /* @__PURE__ */ React14.createElement(
670
660
  ActionMenuItem,
671
661
  {
672
662
  title: (0, import_i18n7.__)("Rename", "elementor"),
673
663
  icon: import_icons7.EraseIcon,
674
- onClick: () => {
675
- setEditMode({
676
- mode: "rename",
677
- details: {
678
- postId: post.id
679
- }
680
- });
664
+ ListItemButtonProps: {
665
+ onClick: () => {
666
+ setEditMode({
667
+ mode: "rename",
668
+ details: {
669
+ postId: post.id
670
+ }
671
+ });
672
+ }
681
673
  }
682
674
  }
683
675
  );
684
676
  }
685
677
 
686
678
  // src/components/panel/actions-menu/actions/duplicate.tsx
687
- var React16 = __toESM(require("react"));
679
+ var React15 = __toESM(require("react"));
688
680
  var import_icons8 = require("@elementor/icons");
689
681
  var import_i18n8 = require("@wordpress/i18n");
690
682
  function Duplicate({ post, popupState }) {
691
683
  const { setEditMode } = usePostListContext();
692
- return /* @__PURE__ */ React16.createElement(
684
+ const onClick = () => {
685
+ popupState.close();
686
+ setEditMode({
687
+ mode: "duplicate",
688
+ details: {
689
+ postId: post.id,
690
+ title: post.title.rendered
691
+ }
692
+ });
693
+ };
694
+ return /* @__PURE__ */ React15.createElement(
693
695
  ActionMenuItem,
694
696
  {
695
697
  title: (0, import_i18n8.__)("Duplicate", "elementor"),
696
698
  icon: import_icons8.CopyIcon,
697
- onClick: () => {
698
- popupState.close();
699
- setEditMode({
700
- mode: "duplicate",
701
- details: {
702
- postId: post.id,
703
- title: post.title.rendered
704
- }
705
- });
699
+ ListItemButtonProps: {
700
+ onClick
706
701
  }
707
702
  }
708
703
  );
709
704
  }
710
705
 
711
706
  // src/components/panel/actions-menu/actions/delete.tsx
712
- var React17 = __toESM(require("react"));
707
+ var React16 = __toESM(require("react"));
713
708
  var import_icons9 = require("@elementor/icons");
714
- var import_editor_documents4 = require("@elementor/editor-documents");
715
709
  var import_i18n9 = require("@wordpress/i18n");
710
+ var import_ui10 = require("@elementor/ui");
711
+ var import_react7 = require("react");
712
+ var import_editor_documents4 = require("@elementor/editor-documents");
716
713
  function Delete({ post }) {
714
+ const [isDialogOpen, setIsDialogOpen] = (0, import_react7.useState)(false);
717
715
  const activeDocument = (0, import_editor_documents4.useActiveDocument)();
718
- const isActive = activeDocument?.id === post.id;
719
- return /* @__PURE__ */ React17.createElement(
716
+ const isPostActive = activeDocument?.id === post.id;
717
+ return /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(
720
718
  ActionMenuItem,
721
719
  {
722
720
  title: (0, import_i18n9.__)("Delete", "elementor"),
723
721
  icon: import_icons9.TrashIcon,
724
- disabled: post.isHome || isActive,
725
- onClick: () => null
722
+ ListItemButtonProps: {
723
+ disabled: post.isHome || isPostActive,
724
+ onClick: () => setIsDialogOpen(true),
725
+ sx: { "&:hover": { color: "error.main" } }
726
+ }
727
+ }
728
+ ), isDialogOpen && /* @__PURE__ */ React16.createElement(DeleteDialog, { post, setIsDialogOpen }));
729
+ }
730
+ function DeleteDialog({ post, setIsDialogOpen }) {
731
+ const { type } = usePostListContext();
732
+ const { deletePost } = usePostActions(type);
733
+ const dialogTitle = (0, import_i18n9.sprintf)((0, import_i18n9.__)("Delete \u201C%s\u201D?", "elementor"), post.title.rendered);
734
+ const deletePage = async () => {
735
+ await deletePost.mutateAsync(post.id);
736
+ };
737
+ const handleCancel = () => {
738
+ if (deletePost.isLoading) {
739
+ return;
726
740
  }
741
+ setIsDialogOpen(false);
742
+ };
743
+ return /* @__PURE__ */ React16.createElement(
744
+ import_ui10.Dialog,
745
+ {
746
+ open: true,
747
+ onClose: handleCancel,
748
+ "aria-labelledby": "delete-dialog"
749
+ },
750
+ /* @__PURE__ */ React16.createElement(import_ui10.DialogTitle, null, dialogTitle),
751
+ /* @__PURE__ */ React16.createElement(import_ui10.Divider, null),
752
+ /* @__PURE__ */ React16.createElement(import_ui10.DialogContent, null, /* @__PURE__ */ React16.createElement(import_ui10.DialogContentText, null, (0, import_i18n9.__)("The page and its content will be deleted forever and we won\u2019t be able to recover them.", "elementor"))),
753
+ /* @__PURE__ */ React16.createElement(import_ui10.DialogActions, null, /* @__PURE__ */ React16.createElement(import_ui10.Button, { variant: "contained", color: "secondary", onClick: handleCancel, disabled: deletePost.isLoading }, (0, import_i18n9.__)("Cancel", "elementor")), /* @__PURE__ */ React16.createElement(import_ui10.Button, { variant: "contained", color: "error", onClick: deletePage, disabled: deletePost.isLoading }, !deletePost.isLoading ? (0, import_i18n9.__)("Delete", "elementor") : /* @__PURE__ */ React16.createElement(import_ui10.CircularProgress, null)))
727
754
  );
728
755
  }
729
756
 
730
757
  // src/components/panel/actions-menu/actions/view.tsx
731
- var React18 = __toESM(require("react"));
758
+ var React17 = __toESM(require("react"));
732
759
  var import_icons10 = require("@elementor/icons");
733
760
  var import_i18n10 = require("@wordpress/i18n");
734
761
  function View({ post }) {
735
762
  const { type } = usePostListContext();
736
763
  const title = (0, import_i18n10.__)("View %s", "elementor").replace("%s", postTypesMap[type].labels.singular_name);
737
- return /* @__PURE__ */ React18.createElement(
764
+ return /* @__PURE__ */ React17.createElement(
738
765
  ActionMenuItem,
739
766
  {
740
767
  title,
741
768
  icon: import_icons10.EyeIcon,
742
- onClick: () => {
743
- window.open(post.link, "_blank");
769
+ ListItemButtonProps: {
770
+ onClick: () => window.open(post.link, "_blank")
744
771
  }
745
772
  }
746
773
  );
747
774
  }
748
775
 
749
776
  // src/components/panel/actions-menu/actions/set-home.tsx
750
- var React19 = __toESM(require("react"));
777
+ var React18 = __toESM(require("react"));
751
778
  var import_icons11 = require("@elementor/icons");
752
779
  var import_i18n11 = require("@wordpress/i18n");
753
780
  function SetHome({ post }) {
754
- return /* @__PURE__ */ React19.createElement(
781
+ return /* @__PURE__ */ React18.createElement(
755
782
  ActionMenuItem,
756
783
  {
757
784
  title: (0, import_i18n11.__)("Set as homepage", "elementor"),
758
785
  icon: import_icons11.HomeIcon,
759
- disabled: !!post.isHome,
760
- onClick: () => null
786
+ ListItemButtonProps: {
787
+ disabled: !!post.isHome,
788
+ onClick: () => null
789
+ }
761
790
  }
762
791
  );
763
792
  }
@@ -772,11 +801,11 @@ function ListItemView({ post }) {
772
801
  disableAutoFocus: true
773
802
  });
774
803
  const isActive = activeDocument?.id === post.id;
775
- return /* @__PURE__ */ React20.createElement(React20.Fragment, null, /* @__PURE__ */ React20.createElement(
804
+ return /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement(
776
805
  import_ui11.ListItem,
777
806
  {
778
807
  disablePadding: true,
779
- secondaryAction: /* @__PURE__ */ React20.createElement(
808
+ secondaryAction: /* @__PURE__ */ React19.createElement(
780
809
  import_ui11.ToggleButton,
781
810
  {
782
811
  value: true,
@@ -784,10 +813,10 @@ function ListItemView({ post }) {
784
813
  selected: popupState.isOpen,
785
814
  ...(0, import_ui11.bindTrigger)(popupState)
786
815
  },
787
- /* @__PURE__ */ React20.createElement(import_icons12.DotsVerticalIcon, { fontSize: "small" })
816
+ /* @__PURE__ */ React19.createElement(import_icons12.DotsVerticalIcon, { fontSize: "small" })
788
817
  )
789
818
  },
790
- /* @__PURE__ */ React20.createElement(
819
+ /* @__PURE__ */ React19.createElement(
791
820
  import_ui11.ListItemButton,
792
821
  {
793
822
  selected: isActive,
@@ -798,29 +827,29 @@ function ListItemView({ post }) {
798
827
  },
799
828
  dense: true
800
829
  },
801
- /* @__PURE__ */ React20.createElement(import_ui11.ListItemIcon, null),
802
- /* @__PURE__ */ React20.createElement(
830
+ /* @__PURE__ */ React19.createElement(import_ui11.ListItemIcon, null),
831
+ /* @__PURE__ */ React19.createElement(
803
832
  import_ui11.ListItemText,
804
833
  {
805
834
  disableTypography: true
806
835
  },
807
- /* @__PURE__ */ React20.createElement(PageTitleAndStatus, { page: post })
836
+ /* @__PURE__ */ React19.createElement(PageTitleAndStatus, { page: post })
808
837
  ),
809
- post.isHome && /* @__PURE__ */ React20.createElement(import_ui11.ListItemIcon, null, /* @__PURE__ */ React20.createElement(import_icons12.HomeIcon, { color: "disabled" }))
838
+ post.isHome && /* @__PURE__ */ React19.createElement(import_ui11.ListItemIcon, null, /* @__PURE__ */ React19.createElement(import_icons12.HomeIcon, { color: "disabled" }))
810
839
  )
811
- ), /* @__PURE__ */ React20.createElement(
840
+ ), /* @__PURE__ */ React19.createElement(
812
841
  import_ui11.Menu,
813
842
  {
814
843
  PaperProps: { sx: { mt: 4, width: 200 } },
815
844
  MenuListProps: { dense: true },
816
845
  ...(0, import_ui11.bindMenu)(popupState)
817
846
  },
818
- /* @__PURE__ */ React20.createElement(Rename, { post }),
819
- /* @__PURE__ */ React20.createElement(Duplicate, { post, popupState }),
820
- /* @__PURE__ */ React20.createElement(Delete, { post }),
821
- /* @__PURE__ */ React20.createElement(View, { post }),
822
- /* @__PURE__ */ React20.createElement(import_ui11.Divider, null),
823
- /* @__PURE__ */ React20.createElement(SetHome, { post })
847
+ /* @__PURE__ */ React19.createElement(Rename, { post }),
848
+ /* @__PURE__ */ React19.createElement(Duplicate, { post, popupState }),
849
+ /* @__PURE__ */ React19.createElement(Delete, { post }),
850
+ /* @__PURE__ */ React19.createElement(View, { post }),
851
+ /* @__PURE__ */ React19.createElement(import_ui11.Divider, null),
852
+ /* @__PURE__ */ React19.createElement(SetHome, { post })
824
853
  ));
825
854
  }
826
855
 
@@ -828,18 +857,18 @@ function ListItemView({ post }) {
828
857
  function PostListItem2({ post }) {
829
858
  const { editMode } = usePostListContext();
830
859
  if ("rename" === editMode.mode && post?.id && post?.id === editMode.details.postId) {
831
- return /* @__PURE__ */ React21.createElement(ListItemRename, { post });
860
+ return /* @__PURE__ */ React20.createElement(ListItemRename, { post });
832
861
  }
833
862
  if ("create" === editMode.mode && !post) {
834
- return /* @__PURE__ */ React21.createElement(ListItemCreate, null);
863
+ return /* @__PURE__ */ React20.createElement(ListItemCreate, null);
835
864
  }
836
- if ("duplicate" === editMode.mode && post?.id && post?.id === editMode.details.postId) {
837
- return /* @__PURE__ */ React21.createElement(ListItemDuplicate, { post });
865
+ if ("duplicate" === editMode.mode && !post) {
866
+ return /* @__PURE__ */ React20.createElement(ListItemDuplicate, null);
838
867
  }
839
868
  if (!post) {
840
869
  return null;
841
870
  }
842
- return /* @__PURE__ */ React21.createElement(ListItemView, { post });
871
+ return /* @__PURE__ */ React20.createElement(ListItemView, { post });
843
872
  }
844
873
 
845
874
  // src/components/panel/posts-list/posts-collapsible-list.tsx
@@ -847,34 +876,34 @@ function PostsCollapsibleList({ isOpenByDefault = false }) {
847
876
  const { type, editMode } = usePostListContext();
848
877
  const { data: posts, isLoading: postsLoading } = usePosts(type);
849
878
  if (!posts || postsLoading) {
850
- return /* @__PURE__ */ React22.createElement(import_ui12.Box, { spacing: 4, sx: { px: 6 } }, /* @__PURE__ */ React22.createElement(import_ui12.Skeleton, { variant: "text", sx: { fontSize: "2rem" } }), /* @__PURE__ */ React22.createElement(import_ui12.Skeleton, { variant: "rounded", width: "100%", height: "48" }));
879
+ return /* @__PURE__ */ React21.createElement(import_ui12.Box, { spacing: 4, sx: { px: 6 } }, /* @__PURE__ */ React21.createElement(import_ui12.Skeleton, { variant: "text", sx: { fontSize: "2rem" } }), /* @__PURE__ */ React21.createElement(import_ui12.Skeleton, { variant: "rounded", width: "100%", height: "48" }));
851
880
  }
852
881
  const label = `${postTypesMap[type].labels.plural_name} (${posts.length.toString()})`;
853
- return /* @__PURE__ */ React22.createElement(import_ui12.List, { dense: true }, /* @__PURE__ */ React22.createElement(
882
+ return /* @__PURE__ */ React21.createElement(import_ui12.List, { dense: true }, /* @__PURE__ */ React21.createElement(
854
883
  CollapsibleList,
855
884
  {
856
885
  label,
857
886
  Icon: import_icons13.PageTypeIcon,
858
887
  isOpenByDefault: isOpenByDefault || false
859
888
  },
860
- posts.map((post) => /* @__PURE__ */ React22.createElement(PostListItem2, { key: post.id, post })),
861
- ["duplicate", "create"].includes(editMode.mode) && /* @__PURE__ */ React22.createElement(PostListItem2, null)
889
+ posts.map((post) => /* @__PURE__ */ React21.createElement(PostListItem2, { key: post.id, post })),
890
+ ["duplicate", "create"].includes(editMode.mode) && /* @__PURE__ */ React21.createElement(PostListItem2, null)
862
891
  ));
863
892
  }
864
893
 
865
894
  // src/components/panel/add-new-button.tsx
866
- var React23 = __toESM(require("react"));
895
+ var React22 = __toESM(require("react"));
867
896
  var import_ui13 = require("@elementor/ui");
868
897
  var import_icons14 = require("@elementor/icons");
869
898
  var import_i18n12 = require("@wordpress/i18n");
870
899
  function AddNewButton() {
871
900
  const { setEditMode } = usePostListContext();
872
- return /* @__PURE__ */ React23.createElement(
901
+ return /* @__PURE__ */ React22.createElement(
873
902
  import_ui13.Button,
874
903
  {
875
904
  size: "small",
876
905
  sx: { mt: 4, mb: 4, mr: 5 },
877
- startIcon: /* @__PURE__ */ React23.createElement(import_icons14.PlusIcon, null),
906
+ startIcon: /* @__PURE__ */ React22.createElement(import_icons14.PlusIcon, null),
878
907
  onClick: () => {
879
908
  setEditMode({ mode: "create", details: {} });
880
909
  }
@@ -885,15 +914,15 @@ function AddNewButton() {
885
914
 
886
915
  // src/components/panel/shell.tsx
887
916
  var Shell = () => {
888
- return /* @__PURE__ */ React24.createElement(import_editor_panels.Panel, null, /* @__PURE__ */ React24.createElement(import_editor_panels.PanelHeader, null, /* @__PURE__ */ React24.createElement(import_editor_panels.PanelHeaderTitle, null, (0, import_i18n13.__)("Pages", "elementor"))), /* @__PURE__ */ React24.createElement(import_editor_panels.PanelBody, null, /* @__PURE__ */ React24.createElement(PostListContextProvider, { type: "page" }, /* @__PURE__ */ React24.createElement(
917
+ return /* @__PURE__ */ React23.createElement(import_editor_panels.Panel, null, /* @__PURE__ */ React23.createElement(import_editor_panels.PanelHeader, null, /* @__PURE__ */ React23.createElement(import_editor_panels.PanelHeaderTitle, null, (0, import_i18n13.__)("Pages", "elementor"))), /* @__PURE__ */ React23.createElement(import_editor_panels.PanelBody, null, /* @__PURE__ */ React23.createElement(PostListContextProvider, { type: "page" }, /* @__PURE__ */ React23.createElement(
889
918
  import_ui14.Box,
890
919
  {
891
920
  display: "flex",
892
921
  justifyContent: "flex-end",
893
922
  alignItems: "center"
894
923
  },
895
- /* @__PURE__ */ React24.createElement(AddNewButton, null)
896
- ), /* @__PURE__ */ React24.createElement(PostsCollapsibleList, { isOpenByDefault: true }))));
924
+ /* @__PURE__ */ React23.createElement(AddNewButton, null)
925
+ ), /* @__PURE__ */ React23.createElement(PostsCollapsibleList, { isOpenByDefault: true }))));
897
926
  };
898
927
  var shell_default = Shell;
899
928
 
package/dist/index.mjs CHANGED
@@ -239,13 +239,13 @@ import { PagesIcon } from "@elementor/icons";
239
239
  import { createPanel } from "@elementor/editor-panels";
240
240
 
241
241
  // src/components/panel/shell.tsx
242
- import * as React24 from "react";
242
+ import * as React23 from "react";
243
243
  import { Box as Box5 } from "@elementor/ui";
244
244
  import { Panel, PanelBody, PanelHeader, PanelHeaderTitle } from "@elementor/editor-panels";
245
245
  import { __ as __13 } from "@wordpress/i18n";
246
246
 
247
247
  // src/components/panel/posts-list/posts-collapsible-list.tsx
248
- import * as React22 from "react";
248
+ import * as React21 from "react";
249
249
  import { PageTypeIcon as PageTypeIcon2 } from "@elementor/icons";
250
250
  import { Skeleton, Box as Box4, List as List2 } from "@elementor/ui";
251
251
 
@@ -394,7 +394,7 @@ function CollapsibleList({
394
394
  }
395
395
 
396
396
  // src/components/panel/posts-list/post-list-item.tsx
397
- import * as React21 from "react";
397
+ import * as React20 from "react";
398
398
 
399
399
  // src/components/panel/posts-list/list-items/list-item-rename.tsx
400
400
  import * as React9 from "react";
@@ -555,7 +555,7 @@ function ListItemCreate() {
555
555
  // src/components/panel/posts-list/list-items/list-item-duplicate.tsx
556
556
  import * as React11 from "react";
557
557
  import { __ as __6 } from "@wordpress/i18n";
558
- function ListItemDuplicate({ post }) {
558
+ function ListItemDuplicate() {
559
559
  const { type, editMode, resetEditMode } = usePostListContext();
560
560
  const { duplicatePost } = usePostActions(type);
561
561
  if ("duplicate" !== editMode.mode) {
@@ -563,7 +563,7 @@ function ListItemDuplicate({ post }) {
563
563
  }
564
564
  const duplicatePostCallback = (inputValue) => {
565
565
  duplicatePost.mutateAsync({
566
- id: post.id,
566
+ id: editMode.details.postId,
567
567
  title: inputValue
568
568
  }, {
569
569
  onSuccess: () => {
@@ -575,11 +575,11 @@ function ListItemDuplicate({ post }) {
575
575
  }
576
576
 
577
577
  // src/components/panel/posts-list/list-items/list-item-view.tsx
578
- import * as React20 from "react";
578
+ import * as React19 from "react";
579
579
  import {
580
580
  bindMenu as bindMenu2,
581
581
  bindTrigger as bindTrigger2,
582
- Divider as Divider2,
582
+ Divider as Divider3,
583
583
  ListItem as ListItem3,
584
584
  ListItemButton as ListItemButton2,
585
585
  ListItemIcon as ListItemIcon5,
@@ -635,129 +635,167 @@ function PageTitleAndStatus({ page }) {
635
635
  }
636
636
 
637
637
  // src/components/panel/actions-menu/actions/rename.tsx
638
- import * as React15 from "react";
638
+ import * as React14 from "react";
639
639
  import { EraseIcon } from "@elementor/icons";
640
640
  import { __ as __7 } from "@wordpress/i18n";
641
641
 
642
642
  // src/components/panel/actions-menu/action-menu-item.tsx
643
- import * as React14 from "react";
644
-
645
- // src/components/panel/actions-menu/action-list-item.tsx
646
643
  import * as React13 from "react";
647
- import { ListItemButton, ListItemIcon as ListItemIcon4, ListItemText as ListItemText2 } from "@elementor/ui";
648
- function ActionListItem({ title, icon: Icon, disabled, onClick }) {
649
- return /* @__PURE__ */ React13.createElement(
644
+ import { ListItemButton, ListItemIcon as ListItemIcon4, ListItemText as ListItemText2, MenuItem as MenuItem3 } from "@elementor/ui";
645
+ function ActionMenuItem({ title, icon: Icon, ListItemButtonProps }) {
646
+ return /* @__PURE__ */ React13.createElement(MenuItem3, { disableGutters: true }, /* @__PURE__ */ React13.createElement(
650
647
  ListItemButton,
651
648
  {
652
- disabled,
653
- onClick
649
+ ...ListItemButtonProps
654
650
  },
655
651
  /* @__PURE__ */ React13.createElement(ListItemIcon4, null, /* @__PURE__ */ React13.createElement(Icon, null)),
656
652
  /* @__PURE__ */ React13.createElement(ListItemText2, null, title)
657
- );
658
- }
659
-
660
- // src/components/panel/actions-menu/action-menu-item.tsx
661
- import { MenuItem as MenuItem3 } from "@elementor/ui";
662
- function ActionMenuItem(props) {
663
- return /* @__PURE__ */ React14.createElement(MenuItem3, { disableGutters: true }, /* @__PURE__ */ React14.createElement(ActionListItem, { ...props }));
653
+ ));
664
654
  }
665
655
 
666
656
  // src/components/panel/actions-menu/actions/rename.tsx
667
657
  function Rename({ post }) {
668
658
  const { setEditMode } = usePostListContext();
669
- return /* @__PURE__ */ React15.createElement(
659
+ return /* @__PURE__ */ React14.createElement(
670
660
  ActionMenuItem,
671
661
  {
672
662
  title: __7("Rename", "elementor"),
673
663
  icon: EraseIcon,
674
- onClick: () => {
675
- setEditMode({
676
- mode: "rename",
677
- details: {
678
- postId: post.id
679
- }
680
- });
664
+ ListItemButtonProps: {
665
+ onClick: () => {
666
+ setEditMode({
667
+ mode: "rename",
668
+ details: {
669
+ postId: post.id
670
+ }
671
+ });
672
+ }
681
673
  }
682
674
  }
683
675
  );
684
676
  }
685
677
 
686
678
  // src/components/panel/actions-menu/actions/duplicate.tsx
687
- import * as React16 from "react";
679
+ import * as React15 from "react";
688
680
  import { CopyIcon } from "@elementor/icons";
689
681
  import { __ as __8 } from "@wordpress/i18n";
690
682
  function Duplicate({ post, popupState }) {
691
683
  const { setEditMode } = usePostListContext();
692
- return /* @__PURE__ */ React16.createElement(
684
+ const onClick = () => {
685
+ popupState.close();
686
+ setEditMode({
687
+ mode: "duplicate",
688
+ details: {
689
+ postId: post.id,
690
+ title: post.title.rendered
691
+ }
692
+ });
693
+ };
694
+ return /* @__PURE__ */ React15.createElement(
693
695
  ActionMenuItem,
694
696
  {
695
697
  title: __8("Duplicate", "elementor"),
696
698
  icon: CopyIcon,
697
- onClick: () => {
698
- popupState.close();
699
- setEditMode({
700
- mode: "duplicate",
701
- details: {
702
- postId: post.id,
703
- title: post.title.rendered
704
- }
705
- });
699
+ ListItemButtonProps: {
700
+ onClick
706
701
  }
707
702
  }
708
703
  );
709
704
  }
710
705
 
711
706
  // src/components/panel/actions-menu/actions/delete.tsx
712
- import * as React17 from "react";
707
+ import * as React16 from "react";
713
708
  import { TrashIcon } from "@elementor/icons";
709
+ import { __ as __9, sprintf } from "@wordpress/i18n";
710
+ import {
711
+ Button as Button2,
712
+ CircularProgress as CircularProgress3,
713
+ Dialog,
714
+ DialogActions,
715
+ DialogContent,
716
+ DialogContentText,
717
+ DialogTitle,
718
+ Divider as Divider2
719
+ } from "@elementor/ui";
720
+ import { useState as useState6 } from "react";
714
721
  import { useActiveDocument as useActiveDocument2 } from "@elementor/editor-documents";
715
- import { __ as __9 } from "@wordpress/i18n";
716
722
  function Delete({ post }) {
723
+ const [isDialogOpen, setIsDialogOpen] = useState6(false);
717
724
  const activeDocument = useActiveDocument2();
718
- const isActive = activeDocument?.id === post.id;
719
- return /* @__PURE__ */ React17.createElement(
725
+ const isPostActive = activeDocument?.id === post.id;
726
+ return /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(
720
727
  ActionMenuItem,
721
728
  {
722
729
  title: __9("Delete", "elementor"),
723
730
  icon: TrashIcon,
724
- disabled: post.isHome || isActive,
725
- onClick: () => null
731
+ ListItemButtonProps: {
732
+ disabled: post.isHome || isPostActive,
733
+ onClick: () => setIsDialogOpen(true),
734
+ sx: { "&:hover": { color: "error.main" } }
735
+ }
726
736
  }
737
+ ), isDialogOpen && /* @__PURE__ */ React16.createElement(DeleteDialog, { post, setIsDialogOpen }));
738
+ }
739
+ function DeleteDialog({ post, setIsDialogOpen }) {
740
+ const { type } = usePostListContext();
741
+ const { deletePost } = usePostActions(type);
742
+ const dialogTitle = sprintf(__9("Delete \u201C%s\u201D?", "elementor"), post.title.rendered);
743
+ const deletePage = async () => {
744
+ await deletePost.mutateAsync(post.id);
745
+ };
746
+ const handleCancel = () => {
747
+ if (deletePost.isLoading) {
748
+ return;
749
+ }
750
+ setIsDialogOpen(false);
751
+ };
752
+ return /* @__PURE__ */ React16.createElement(
753
+ Dialog,
754
+ {
755
+ open: true,
756
+ onClose: handleCancel,
757
+ "aria-labelledby": "delete-dialog"
758
+ },
759
+ /* @__PURE__ */ React16.createElement(DialogTitle, null, dialogTitle),
760
+ /* @__PURE__ */ React16.createElement(Divider2, null),
761
+ /* @__PURE__ */ React16.createElement(DialogContent, null, /* @__PURE__ */ React16.createElement(DialogContentText, null, __9("The page and its content will be deleted forever and we won\u2019t be able to recover them.", "elementor"))),
762
+ /* @__PURE__ */ React16.createElement(DialogActions, null, /* @__PURE__ */ React16.createElement(Button2, { variant: "contained", color: "secondary", onClick: handleCancel, disabled: deletePost.isLoading }, __9("Cancel", "elementor")), /* @__PURE__ */ React16.createElement(Button2, { variant: "contained", color: "error", onClick: deletePage, disabled: deletePost.isLoading }, !deletePost.isLoading ? __9("Delete", "elementor") : /* @__PURE__ */ React16.createElement(CircularProgress3, null)))
727
763
  );
728
764
  }
729
765
 
730
766
  // src/components/panel/actions-menu/actions/view.tsx
731
- import * as React18 from "react";
767
+ import * as React17 from "react";
732
768
  import { EyeIcon } from "@elementor/icons";
733
769
  import { __ as __10 } from "@wordpress/i18n";
734
770
  function View({ post }) {
735
771
  const { type } = usePostListContext();
736
772
  const title = __10("View %s", "elementor").replace("%s", postTypesMap[type].labels.singular_name);
737
- return /* @__PURE__ */ React18.createElement(
773
+ return /* @__PURE__ */ React17.createElement(
738
774
  ActionMenuItem,
739
775
  {
740
776
  title,
741
777
  icon: EyeIcon,
742
- onClick: () => {
743
- window.open(post.link, "_blank");
778
+ ListItemButtonProps: {
779
+ onClick: () => window.open(post.link, "_blank")
744
780
  }
745
781
  }
746
782
  );
747
783
  }
748
784
 
749
785
  // src/components/panel/actions-menu/actions/set-home.tsx
750
- import * as React19 from "react";
786
+ import * as React18 from "react";
751
787
  import { HomeIcon } from "@elementor/icons";
752
788
  import { __ as __11 } from "@wordpress/i18n";
753
789
  function SetHome({ post }) {
754
- return /* @__PURE__ */ React19.createElement(
790
+ return /* @__PURE__ */ React18.createElement(
755
791
  ActionMenuItem,
756
792
  {
757
793
  title: __11("Set as homepage", "elementor"),
758
794
  icon: HomeIcon,
759
- disabled: !!post.isHome,
760
- onClick: () => null
795
+ ListItemButtonProps: {
796
+ disabled: !!post.isHome,
797
+ onClick: () => null
798
+ }
761
799
  }
762
800
  );
763
801
  }
@@ -772,11 +810,11 @@ function ListItemView({ post }) {
772
810
  disableAutoFocus: true
773
811
  });
774
812
  const isActive = activeDocument?.id === post.id;
775
- return /* @__PURE__ */ React20.createElement(React20.Fragment, null, /* @__PURE__ */ React20.createElement(
813
+ return /* @__PURE__ */ React19.createElement(React19.Fragment, null, /* @__PURE__ */ React19.createElement(
776
814
  ListItem3,
777
815
  {
778
816
  disablePadding: true,
779
- secondaryAction: /* @__PURE__ */ React20.createElement(
817
+ secondaryAction: /* @__PURE__ */ React19.createElement(
780
818
  ToggleButton,
781
819
  {
782
820
  value: true,
@@ -784,10 +822,10 @@ function ListItemView({ post }) {
784
822
  selected: popupState.isOpen,
785
823
  ...bindTrigger2(popupState)
786
824
  },
787
- /* @__PURE__ */ React20.createElement(DotsVerticalIcon, { fontSize: "small" })
825
+ /* @__PURE__ */ React19.createElement(DotsVerticalIcon, { fontSize: "small" })
788
826
  )
789
827
  },
790
- /* @__PURE__ */ React20.createElement(
828
+ /* @__PURE__ */ React19.createElement(
791
829
  ListItemButton2,
792
830
  {
793
831
  selected: isActive,
@@ -798,29 +836,29 @@ function ListItemView({ post }) {
798
836
  },
799
837
  dense: true
800
838
  },
801
- /* @__PURE__ */ React20.createElement(ListItemIcon5, null),
802
- /* @__PURE__ */ React20.createElement(
839
+ /* @__PURE__ */ React19.createElement(ListItemIcon5, null),
840
+ /* @__PURE__ */ React19.createElement(
803
841
  ListItemText3,
804
842
  {
805
843
  disableTypography: true
806
844
  },
807
- /* @__PURE__ */ React20.createElement(PageTitleAndStatus, { page: post })
845
+ /* @__PURE__ */ React19.createElement(PageTitleAndStatus, { page: post })
808
846
  ),
809
- post.isHome && /* @__PURE__ */ React20.createElement(ListItemIcon5, null, /* @__PURE__ */ React20.createElement(HomeIcon2, { color: "disabled" }))
847
+ post.isHome && /* @__PURE__ */ React19.createElement(ListItemIcon5, null, /* @__PURE__ */ React19.createElement(HomeIcon2, { color: "disabled" }))
810
848
  )
811
- ), /* @__PURE__ */ React20.createElement(
849
+ ), /* @__PURE__ */ React19.createElement(
812
850
  Menu2,
813
851
  {
814
852
  PaperProps: { sx: { mt: 4, width: 200 } },
815
853
  MenuListProps: { dense: true },
816
854
  ...bindMenu2(popupState)
817
855
  },
818
- /* @__PURE__ */ React20.createElement(Rename, { post }),
819
- /* @__PURE__ */ React20.createElement(Duplicate, { post, popupState }),
820
- /* @__PURE__ */ React20.createElement(Delete, { post }),
821
- /* @__PURE__ */ React20.createElement(View, { post }),
822
- /* @__PURE__ */ React20.createElement(Divider2, null),
823
- /* @__PURE__ */ React20.createElement(SetHome, { post })
856
+ /* @__PURE__ */ React19.createElement(Rename, { post }),
857
+ /* @__PURE__ */ React19.createElement(Duplicate, { post, popupState }),
858
+ /* @__PURE__ */ React19.createElement(Delete, { post }),
859
+ /* @__PURE__ */ React19.createElement(View, { post }),
860
+ /* @__PURE__ */ React19.createElement(Divider3, null),
861
+ /* @__PURE__ */ React19.createElement(SetHome, { post })
824
862
  ));
825
863
  }
826
864
 
@@ -828,18 +866,18 @@ function ListItemView({ post }) {
828
866
  function PostListItem2({ post }) {
829
867
  const { editMode } = usePostListContext();
830
868
  if ("rename" === editMode.mode && post?.id && post?.id === editMode.details.postId) {
831
- return /* @__PURE__ */ React21.createElement(ListItemRename, { post });
869
+ return /* @__PURE__ */ React20.createElement(ListItemRename, { post });
832
870
  }
833
871
  if ("create" === editMode.mode && !post) {
834
- return /* @__PURE__ */ React21.createElement(ListItemCreate, null);
872
+ return /* @__PURE__ */ React20.createElement(ListItemCreate, null);
835
873
  }
836
- if ("duplicate" === editMode.mode && post?.id && post?.id === editMode.details.postId) {
837
- return /* @__PURE__ */ React21.createElement(ListItemDuplicate, { post });
874
+ if ("duplicate" === editMode.mode && !post) {
875
+ return /* @__PURE__ */ React20.createElement(ListItemDuplicate, null);
838
876
  }
839
877
  if (!post) {
840
878
  return null;
841
879
  }
842
- return /* @__PURE__ */ React21.createElement(ListItemView, { post });
880
+ return /* @__PURE__ */ React20.createElement(ListItemView, { post });
843
881
  }
844
882
 
845
883
  // src/components/panel/posts-list/posts-collapsible-list.tsx
@@ -847,34 +885,34 @@ function PostsCollapsibleList({ isOpenByDefault = false }) {
847
885
  const { type, editMode } = usePostListContext();
848
886
  const { data: posts, isLoading: postsLoading } = usePosts(type);
849
887
  if (!posts || postsLoading) {
850
- return /* @__PURE__ */ React22.createElement(Box4, { spacing: 4, sx: { px: 6 } }, /* @__PURE__ */ React22.createElement(Skeleton, { variant: "text", sx: { fontSize: "2rem" } }), /* @__PURE__ */ React22.createElement(Skeleton, { variant: "rounded", width: "100%", height: "48" }));
888
+ return /* @__PURE__ */ React21.createElement(Box4, { spacing: 4, sx: { px: 6 } }, /* @__PURE__ */ React21.createElement(Skeleton, { variant: "text", sx: { fontSize: "2rem" } }), /* @__PURE__ */ React21.createElement(Skeleton, { variant: "rounded", width: "100%", height: "48" }));
851
889
  }
852
890
  const label = `${postTypesMap[type].labels.plural_name} (${posts.length.toString()})`;
853
- return /* @__PURE__ */ React22.createElement(List2, { dense: true }, /* @__PURE__ */ React22.createElement(
891
+ return /* @__PURE__ */ React21.createElement(List2, { dense: true }, /* @__PURE__ */ React21.createElement(
854
892
  CollapsibleList,
855
893
  {
856
894
  label,
857
895
  Icon: PageTypeIcon2,
858
896
  isOpenByDefault: isOpenByDefault || false
859
897
  },
860
- posts.map((post) => /* @__PURE__ */ React22.createElement(PostListItem2, { key: post.id, post })),
861
- ["duplicate", "create"].includes(editMode.mode) && /* @__PURE__ */ React22.createElement(PostListItem2, null)
898
+ posts.map((post) => /* @__PURE__ */ React21.createElement(PostListItem2, { key: post.id, post })),
899
+ ["duplicate", "create"].includes(editMode.mode) && /* @__PURE__ */ React21.createElement(PostListItem2, null)
862
900
  ));
863
901
  }
864
902
 
865
903
  // src/components/panel/add-new-button.tsx
866
- import * as React23 from "react";
867
- import { Button as Button2 } from "@elementor/ui";
904
+ import * as React22 from "react";
905
+ import { Button as Button3 } from "@elementor/ui";
868
906
  import { PlusIcon as PlusIcon2 } from "@elementor/icons";
869
907
  import { __ as __12 } from "@wordpress/i18n";
870
908
  function AddNewButton() {
871
909
  const { setEditMode } = usePostListContext();
872
- return /* @__PURE__ */ React23.createElement(
873
- Button2,
910
+ return /* @__PURE__ */ React22.createElement(
911
+ Button3,
874
912
  {
875
913
  size: "small",
876
914
  sx: { mt: 4, mb: 4, mr: 5 },
877
- startIcon: /* @__PURE__ */ React23.createElement(PlusIcon2, null),
915
+ startIcon: /* @__PURE__ */ React22.createElement(PlusIcon2, null),
878
916
  onClick: () => {
879
917
  setEditMode({ mode: "create", details: {} });
880
918
  }
@@ -885,15 +923,15 @@ function AddNewButton() {
885
923
 
886
924
  // src/components/panel/shell.tsx
887
925
  var Shell = () => {
888
- return /* @__PURE__ */ React24.createElement(Panel, null, /* @__PURE__ */ React24.createElement(PanelHeader, null, /* @__PURE__ */ React24.createElement(PanelHeaderTitle, null, __13("Pages", "elementor"))), /* @__PURE__ */ React24.createElement(PanelBody, null, /* @__PURE__ */ React24.createElement(PostListContextProvider, { type: "page" }, /* @__PURE__ */ React24.createElement(
926
+ return /* @__PURE__ */ React23.createElement(Panel, null, /* @__PURE__ */ React23.createElement(PanelHeader, null, /* @__PURE__ */ React23.createElement(PanelHeaderTitle, null, __13("Pages", "elementor"))), /* @__PURE__ */ React23.createElement(PanelBody, null, /* @__PURE__ */ React23.createElement(PostListContextProvider, { type: "page" }, /* @__PURE__ */ React23.createElement(
889
927
  Box5,
890
928
  {
891
929
  display: "flex",
892
930
  justifyContent: "flex-end",
893
931
  alignItems: "center"
894
932
  },
895
- /* @__PURE__ */ React24.createElement(AddNewButton, null)
896
- ), /* @__PURE__ */ React24.createElement(PostsCollapsibleList, { isOpenByDefault: true }))));
933
+ /* @__PURE__ */ React23.createElement(AddNewButton, null)
934
+ ), /* @__PURE__ */ React23.createElement(PostsCollapsibleList, { isOpenByDefault: true }))));
897
935
  };
898
936
  var shell_default = Shell;
899
937
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elementor/editor-site-navigation",
3
- "version": "0.14.0",
3
+ "version": "0.16.0",
4
4
  "private": false,
5
5
  "author": "Elementor Team",
6
6
  "homepage": "https://elementor.com/",
@@ -49,5 +49,5 @@
49
49
  "elementor": {
50
50
  "type": "extension"
51
51
  },
52
- "gitHead": "025f7ec0942da99205377c41e713afe1e8f7898d"
52
+ "gitHead": "673479dfda4fe5feae87a229e7b371b8fb19c0ee"
53
53
  }
@@ -1,11 +1,26 @@
1
1
  import * as React from 'react';
2
- import ActionListItem, { Props as ActionListItemProps } from './action-list-item';
3
- import { MenuItem } from '@elementor/ui';
2
+ import { ListItemButton, ListItemIcon, ListItemText, MenuItem, ListItemButtonProps as ListItemButtonPropsType } from '@elementor/ui';
3
+ import { ComponentType } from 'react';
4
4
 
5
- export default function ActionMenuItem( props: ActionListItemProps ) {
5
+ export type Props = {
6
+ title: string;
7
+ icon: ComponentType;
8
+ ListItemButtonProps: ListItemButtonPropsType;
9
+ }
10
+
11
+ export default function ActionMenuItem( { title, icon: Icon, ListItemButtonProps }: Props ) {
6
12
  return (
7
13
  <MenuItem disableGutters>
8
- <ActionListItem { ...props } />
14
+ <ListItemButton
15
+ { ...ListItemButtonProps }
16
+ >
17
+ <ListItemIcon>
18
+ <Icon />
19
+ </ListItemIcon>
20
+ <ListItemText>
21
+ { title }
22
+ </ListItemText>
23
+ </ListItemButton>
9
24
  </MenuItem>
10
25
  );
11
26
  }
@@ -0,0 +1,82 @@
1
+ import { fireEvent, render, screen } from '@testing-library/react';
2
+ import * as React from 'react';
3
+ import { Post } from '../../../../../types';
4
+ import Delete from '../delete';
5
+
6
+ const mockMutateAsync = jest.fn();
7
+ jest.mock( '../../../../../hooks/use-posts-actions', () => ( {
8
+ usePostActions: () => ( {
9
+ deletePost: {
10
+ mutateAsync: mockMutateAsync,
11
+ isLoading: false,
12
+ },
13
+ } ),
14
+ } ) );
15
+
16
+ jest.mock( '@elementor/editor-documents', () => ( {
17
+ useActiveDocument: jest.fn(),
18
+ } ) );
19
+
20
+ describe( '@elementor/editor-site-navigation/pages-panel-actions - Delete', () => {
21
+ afterAll( () => {
22
+ jest.clearAllMocks();
23
+ } );
24
+
25
+ it( 'should render Delete, display the modal and run the delete action', () => {
26
+ // Arrange.
27
+ const post: Post = {
28
+ id: 1,
29
+ title: {
30
+ rendered: 'Test Page',
31
+ },
32
+ status: 'publish',
33
+ type: 'page',
34
+ link: 'https://example.local/test-page',
35
+ isHome: false,
36
+ };
37
+
38
+ // Act.
39
+ render( <Delete post={ post } /> );
40
+
41
+ // Assert.
42
+ const button = screen.getByRole( 'button' );
43
+ expect( button ).not.toHaveAttribute( 'aria-disabled' );
44
+
45
+ // Open the modal.
46
+ fireEvent.click( button );
47
+
48
+ const modal = screen.getByText( 'Delete “Test Page”?' );
49
+ expect( modal ).toBeInTheDocument();
50
+
51
+ const modalButtons = screen.getAllByRole( 'button' );
52
+ expect( modalButtons[ 0 ] ).toHaveTextContent( 'Cancel' );
53
+ expect( modalButtons[ 1 ] ).toHaveTextContent( 'Delete' );
54
+
55
+ // Click the delete button.
56
+ fireEvent.click( modalButtons[ 1 ] );
57
+
58
+ expect( mockMutateAsync ).toHaveBeenCalledTimes( 1 );
59
+ expect( mockMutateAsync ).toHaveBeenCalledWith( post.id );
60
+ } );
61
+
62
+ it( 'should render Delete disabled when post is homepage', () => {
63
+ // Arrange.
64
+ const post: Post = {
65
+ id: 1,
66
+ title: {
67
+ rendered: 'Test Page',
68
+ },
69
+ status: 'draft',
70
+ type: 'page',
71
+ link: 'https://example.local/test-page',
72
+ isHome: true,
73
+ };
74
+
75
+ // Act.
76
+ render( <Delete post={ post } /> );
77
+
78
+ // Assert.
79
+ const button = screen.getByRole( 'button' );
80
+ expect( button ).toHaveAttribute( 'aria-disabled', 'true' );
81
+ } );
82
+ } );
@@ -1,21 +1,94 @@
1
1
  import * as React from 'react';
2
2
  import { TrashIcon } from '@elementor/icons';
3
3
  import { Post } from '../../../../types';
4
- import { useActiveDocument } from '@elementor/editor-documents';
5
- import { __ } from '@wordpress/i18n';
4
+ import { __, sprintf } from '@wordpress/i18n';
6
5
  import ActionMenuItem from '../action-menu-item';
6
+ import { usePostActions } from '../../../../hooks/use-posts-actions';
7
+ import {
8
+ Button,
9
+ CircularProgress,
10
+ Dialog,
11
+ DialogActions,
12
+ DialogContent,
13
+ DialogContentText,
14
+ DialogTitle,
15
+ Divider,
16
+ } from '@elementor/ui';
17
+ import { usePostListContext } from '../../../../contexts/post-list-context';
18
+ import { useState } from 'react';
19
+ import { useActiveDocument } from '@elementor/editor-documents';
7
20
 
8
21
  export default function Delete( { post }: { post: Post } ) {
22
+ const [ isDialogOpen, setIsDialogOpen ] = useState( false );
9
23
  const activeDocument = useActiveDocument();
10
24
 
11
- const isActive = activeDocument?.id === post.id;
25
+ const isPostActive = activeDocument?.id === post.id;
26
+
27
+ return (
28
+ <>
29
+ <ActionMenuItem
30
+ title={ __( 'Delete', 'elementor' ) }
31
+ icon={ TrashIcon }
32
+ ListItemButtonProps={
33
+ {
34
+ disabled: post.isHome || isPostActive,
35
+ onClick: () => setIsDialogOpen( true ),
36
+ sx: { '&:hover': { color: 'error.main' } },
37
+ }
38
+ }
39
+ />
40
+
41
+ {
42
+ isDialogOpen && (
43
+ <DeleteDialog post={ post } setIsDialogOpen={ setIsDialogOpen } />
44
+ )
45
+ }
46
+ </>
47
+ );
48
+ }
49
+
50
+ function DeleteDialog( { post, setIsDialogOpen }: { post: Post, setIsDialogOpen: React.Dispatch<React.SetStateAction<boolean>> } ) {
51
+ const { type } = usePostListContext();
52
+ const { deletePost } = usePostActions( type );
53
+
54
+ /* translators: %s: Post title. */
55
+ const dialogTitle = sprintf( __( 'Delete “%s”?', 'elementor' ), post.title.rendered );
56
+
57
+ const deletePage = async () => {
58
+ await deletePost.mutateAsync( post.id );
59
+ };
60
+
61
+ const handleCancel = () => {
62
+ if ( deletePost.isLoading ) {
63
+ return;
64
+ }
65
+
66
+ setIsDialogOpen( false );
67
+ };
12
68
 
13
69
  return (
14
- <ActionMenuItem
15
- title={ __( 'Delete', 'elementor' ) }
16
- icon={ TrashIcon }
17
- disabled={ post.isHome || isActive }
18
- onClick={ () => null }
19
- />
70
+ <Dialog
71
+ open={ true }
72
+ onClose={ handleCancel }
73
+ aria-labelledby="delete-dialog"
74
+ >
75
+ <DialogTitle>
76
+ { dialogTitle }
77
+ </DialogTitle>
78
+ <Divider />
79
+ <DialogContent>
80
+ <DialogContentText>
81
+ { __( 'The page and its content will be deleted forever and we won’t be able to recover them.', 'elementor' ) }
82
+ </DialogContentText>
83
+ </DialogContent>
84
+ <DialogActions>
85
+ <Button variant="contained" color="secondary" onClick={ handleCancel } disabled={ deletePost.isLoading }>
86
+ { __( 'Cancel', 'elementor' ) }
87
+ </Button>
88
+ <Button variant="contained" color="error" onClick={ deletePage } disabled={ deletePost.isLoading } >
89
+ { ! deletePost.isLoading ? __( 'Delete', 'elementor' ) : <CircularProgress /> }
90
+ </Button>
91
+ </DialogActions>
92
+ </Dialog>
20
93
  );
21
94
  }
@@ -9,21 +9,27 @@ import { Post } from '../../../../types';
9
9
  export default function Duplicate( { post, popupState }: { post: Post, popupState: PopupState } ) {
10
10
  const { setEditMode } = usePostListContext();
11
11
 
12
+ const onClick = () => {
13
+ popupState.close();
14
+
15
+ setEditMode( {
16
+ mode: 'duplicate',
17
+ details: {
18
+ postId: post.id,
19
+ title: post.title.rendered,
20
+ },
21
+ } );
22
+ };
23
+
12
24
  return (
13
25
  <ActionMenuItem
14
26
  title={ __( 'Duplicate', 'elementor' ) }
15
27
  icon={ CopyIcon }
16
- onClick={ () => {
17
- popupState.close();
18
-
19
- setEditMode( {
20
- mode: 'duplicate',
21
- details: {
22
- postId: post.id,
23
- title: post.title.rendered,
24
- },
25
- } );
26
- } }
28
+ ListItemButtonProps={
29
+ {
30
+ onClick,
31
+ }
32
+ }
27
33
  />
28
34
  );
29
35
  }
@@ -12,14 +12,18 @@ export default function Rename( { post }: { post: Post } ) {
12
12
  <ActionMenuItem
13
13
  title={ __( 'Rename', 'elementor' ) }
14
14
  icon={ EraseIcon }
15
- onClick={ () => {
16
- setEditMode( {
17
- mode: 'rename',
18
- details: {
19
- postId: post.id,
15
+ ListItemButtonProps={
16
+ {
17
+ onClick: () => {
18
+ setEditMode( {
19
+ mode: 'rename',
20
+ details: {
21
+ postId: post.id,
22
+ },
23
+ } );
20
24
  },
21
- } );
22
- } }
25
+ }
26
+ }
23
27
  />
24
28
  );
25
29
  }
@@ -9,8 +9,12 @@ export default function SetHome( { post }: { post: Post } ) {
9
9
  <ActionMenuItem
10
10
  title={ __( 'Set as homepage', 'elementor' ) }
11
11
  icon={ HomeIcon }
12
- disabled={ !! post.isHome }
13
- onClick={ () => null }
12
+ ListItemButtonProps={
13
+ {
14
+ disabled: !! post.isHome,
15
+ onClick: () => null,
16
+ }
17
+ }
14
18
  />
15
19
  );
16
20
  }
@@ -16,9 +16,11 @@ export default function View( { post }: { post: Post } ) {
16
16
  <ActionMenuItem
17
17
  title={ title }
18
18
  icon={ EyeIcon }
19
- onClick={ () => {
20
- window.open( post.link, '_blank' );
21
- } }
19
+ ListItemButtonProps={
20
+ {
21
+ onClick: () => window.open( post.link, '_blank' ),
22
+ }
23
+ }
22
24
  />
23
25
  );
24
26
  }
@@ -3,13 +3,8 @@ import { __ } from '@wordpress/i18n';
3
3
  import { usePostListContext } from '../../../../contexts/post-list-context';
4
4
  import { usePostActions } from '../../../../hooks/use-posts-actions';
5
5
  import EditModeTemplate from './edit-mode-template';
6
- import { Post } from '../../../../types';
7
6
 
8
- type Props = {
9
- post: Post,
10
- }
11
-
12
- export default function ListItemDuplicate( { post }: Props ) {
7
+ export default function ListItemDuplicate() {
13
8
  const { type, editMode, resetEditMode } = usePostListContext();
14
9
  const { duplicatePost } = usePostActions( type );
15
10
 
@@ -19,7 +14,7 @@ export default function ListItemDuplicate( { post }: Props ) {
19
14
 
20
15
  const duplicatePostCallback = ( inputValue: string ) => {
21
16
  duplicatePost.mutateAsync( {
22
- id: post.id,
17
+ id: editMode.details.postId,
23
18
  title: inputValue,
24
19
  }, {
25
20
  onSuccess: () => {
@@ -17,8 +17,8 @@ export default function PostListItem( { post }: { post?: Post } ) {
17
17
  return <ListItemCreate />;
18
18
  }
19
19
 
20
- if ( 'duplicate' === editMode.mode && post?.id && post?.id === editMode.details.postId ) {
21
- return <ListItemDuplicate post={ post } />;
20
+ if ( 'duplicate' === editMode.mode && ! post ) {
21
+ return <ListItemDuplicate />;
22
22
  }
23
23
 
24
24
  if ( ! post ) {
@@ -1,27 +0,0 @@
1
- import * as React from 'react';
2
- import { ComponentType } from 'react';
3
- import { ListItemButton, ListItemIcon, ListItemText } from '@elementor/ui';
4
- import { Post } from '../../../types';
5
-
6
- export type Props = {
7
- title: string;
8
- icon: ComponentType;
9
- disabled?: boolean;
10
- onClick: ( post: Post ) => void;
11
- }
12
-
13
- export default function ActionListItem( { title, icon: Icon, disabled, onClick }: Props ) {
14
- return (
15
- <ListItemButton
16
- disabled={ disabled }
17
- onClick={ onClick }
18
- >
19
- <ListItemIcon>
20
- <Icon />
21
- </ListItemIcon>
22
- <ListItemText>
23
- { title }
24
- </ListItemText>
25
- </ListItemButton>
26
- );
27
- }