@elementor/editor-site-navigation 0.19.8 → 0.19.10

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 (37) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/dist/index.js +288 -167
  3. package/dist/index.mjs +278 -158
  4. package/package.json +3 -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 +3 -3
  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 +49 -32
  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 +12 -9
  25. package/src/components/panel/posts-list/list-items/list-item-view.tsx +5 -12
  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 +2 -0
  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 +22 -10
  31. package/src/components/top-bar/post-list-item.tsx +2 -2
  32. package/src/components/top-bar/recently-edited.tsx +21 -2
  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/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,12 +219,26 @@ 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"
234
233
  });
235
- const documentTitle = useReverseHtmlEntities(document2?.title);
234
+ const getCurrentDocumentFromRecentPosts = () => {
235
+ if (!document2) {
236
+ return null;
237
+ }
238
+ return data?.find((post) => post.id === document2.id);
239
+ };
240
+ const currentDocumentFromRecentPosts = getCurrentDocumentFromRecentPosts();
241
+ const documentTitle = useReverseHtmlEntities(currentDocumentFromRecentPosts ? currentDocumentFromRecentPosts.title : document2?.title);
236
242
  if (!document2) {
237
243
  return null;
238
244
  }
@@ -280,24 +286,24 @@ function RecentlyEdited() {
280
286
  import { injectIntoPageIndication, toolsMenu } from "@elementor/editor-app-bar";
281
287
 
282
288
  // src/hooks/use-toggle-button-props.ts
283
- import { __ as __15 } from "@wordpress/i18n";
289
+ import { __ as __16 } from "@wordpress/i18n";
284
290
  import { PagesIcon } from "@elementor/icons";
285
291
 
286
292
  // src/components/panel/panel.ts
287
293
  import { __createPanel } from "@elementor/editor-panels";
288
294
 
289
295
  // src/components/panel/shell.tsx
290
- import * as React23 from "react";
296
+ import * as React25 from "react";
291
297
  import { Panel, PanelBody, PanelHeader, PanelHeaderTitle } from "@elementor/editor-panels";
292
- import { __ as __14 } from "@wordpress/i18n";
298
+ import { __ as __15 } from "@wordpress/i18n";
293
299
 
294
300
  // src/components/panel/posts-list/posts-collapsible-list.tsx
295
- import * as React22 from "react";
301
+ import * as React23 from "react";
296
302
  import { PageTypeIcon as PageTypeIcon2 } from "@elementor/icons";
297
- import { Skeleton, Box as Box3, List as List2 } from "@elementor/ui";
303
+ import { Skeleton, Box as Box4, List as List2 } from "@elementor/ui";
298
304
 
299
305
  // src/hooks/use-posts.ts
300
- import { useQuery } from "@elementor/query";
306
+ import { useQuery as useQuery2 } from "@elementor/query";
301
307
 
302
308
  // src/api/post.ts
303
309
  import apiFetch3 from "@wordpress/api-fetch";
@@ -311,7 +317,7 @@ var postTypesMap = {
311
317
  rest_base: "pages"
312
318
  }
313
319
  };
314
- var getRequest = (postTypeSlug) => {
320
+ var getRequest2 = (postTypeSlug) => {
315
321
  const baseUri = `/wp/v2/${postTypesMap[postTypeSlug].rest_base}`;
316
322
  const keys = ["id", "type", "title", "link", "status"];
317
323
  const queryParams = new URLSearchParams({
@@ -362,27 +368,29 @@ var duplicateRequest = (originalPost) => {
362
368
  // src/hooks/use-posts.ts
363
369
  var postsQueryKey = (postTypeSlug) => ["site-navigation", "posts", postTypeSlug];
364
370
  function usePosts(postTypeSlug) {
365
- return useQuery({
371
+ return useQuery2({
366
372
  queryKey: postsQueryKey(postTypeSlug),
367
- queryFn: () => getRequest(postTypeSlug)
373
+ queryFn: () => getRequest2(postTypeSlug)
368
374
  });
369
375
  }
370
376
 
371
377
  // src/contexts/post-list-context.tsx
372
378
  import * as React6 from "react";
373
- import { useState as useState3, useContext, createContext } from "react";
379
+ import { useState as useState2, useContext, createContext } from "react";
374
380
  var defaultValues = {
375
381
  type: "page",
376
382
  editMode: { mode: "none", details: {} },
377
383
  setEditMode: () => null,
378
- resetEditMode: () => null
384
+ resetEditMode: () => null,
385
+ setError: () => null
379
386
  };
380
387
  var PostListContext = createContext(defaultValues);
381
388
  var PostListContextProvider = ({
382
389
  type,
390
+ setError,
383
391
  children
384
392
  }) => {
385
- const [editMode, setEditMode] = useState3(defaultValues.editMode);
393
+ const [editMode, setEditMode] = useState2(defaultValues.editMode);
386
394
  const resetEditMode = () => {
387
395
  setEditMode(defaultValues.editMode);
388
396
  };
@@ -390,7 +398,8 @@ var PostListContextProvider = ({
390
398
  type,
391
399
  editMode,
392
400
  setEditMode,
393
- resetEditMode
401
+ resetEditMode,
402
+ setError
394
403
  } }, children);
395
404
  };
396
405
  function usePostListContext() {
@@ -403,7 +412,7 @@ function usePostListContext() {
403
412
 
404
413
  // src/components/panel/posts-list/collapsible-list.tsx
405
414
  import * as React7 from "react";
406
- import { useState as useState4 } from "react";
415
+ import { useState as useState3 } from "react";
407
416
  import { Collapse, IconButton, List, ListItem, ListItemIcon as ListItemIcon2, ListItemText as ListItemText4, styled, Divider as Divider2 } from "@elementor/ui";
408
417
  import { ChevronDownIcon as ChevronDownIcon2 } from "@elementor/icons";
409
418
  var RotateIcon = styled(ChevronDownIcon2, {
@@ -414,22 +423,38 @@ var RotateIcon = styled(ChevronDownIcon2, {
414
423
  duration: theme.transitions.duration.standard
415
424
  })
416
425
  }));
426
+ var StyledListItemIcon = styled(ListItemIcon2)(({ theme }) => ({
427
+ minWidth: theme.spacing(4)
428
+ }));
417
429
  function CollapsibleList({
418
430
  label,
419
431
  Icon,
420
432
  isOpenByDefault = false,
421
433
  children
422
434
  }) {
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(
435
+ const [isOpen, setIsOpen] = useState3(isOpenByDefault);
436
+ return /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(ListItem, null, /* @__PURE__ */ React7.createElement(StyledListItemIcon, { sx: {
437
+ color: "text.secondary"
438
+ } }, /* @__PURE__ */ React7.createElement(
425
439
  IconButton,
426
440
  {
427
441
  onClick: () => setIsOpen((prev) => !prev),
428
- sx: { color: "inherit" },
429
- size: "small"
442
+ size: "small",
443
+ sx: {
444
+ color: "inherit"
445
+ }
430
446
  },
431
447
  /* @__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(
448
+ )), /* @__PURE__ */ React7.createElement(
449
+ StyledListItemIcon,
450
+ {
451
+ size: "small",
452
+ sx: {
453
+ color: "inherit"
454
+ }
455
+ },
456
+ /* @__PURE__ */ React7.createElement(Icon, { fontSize: "small" })
457
+ ), /* @__PURE__ */ React7.createElement(ListItemText4, { primaryTypographyProps: { variant: "subtitle2", component: "span" }, primary: label })), /* @__PURE__ */ React7.createElement(
433
458
  Collapse,
434
459
  {
435
460
  in: isOpen,
@@ -478,25 +503,28 @@ function useInvalidatePosts(postTypeSlug) {
478
503
  const queryClient = useQueryClient();
479
504
  return (options = {}) => {
480
505
  const queryKey = postsQueryKey(postTypeSlug);
506
+ queryClient.invalidateQueries({ queryKey: recentPostsQueryKey }, options);
481
507
  return queryClient.invalidateQueries({ queryKey }, options);
482
508
  };
483
509
  }
484
510
 
485
511
  // src/components/panel/posts-list/list-items/edit-mode-template.tsx
486
512
  import * as React8 from "react";
487
- import { useState as useState5, useRef } from "react";
513
+ import { useState as useState4, useRef } from "react";
488
514
  import {
489
515
  Box,
490
516
  ListItem as ListItem2,
491
517
  TextField,
492
518
  IconButton as IconButton2,
493
- CircularProgress as CircularProgress2
519
+ CircularProgress as CircularProgress2,
520
+ ListItemText as ListItemText5
494
521
  } from "@elementor/ui";
495
522
  import { XIcon } from "@elementor/icons";
496
523
  import { __ as __4 } from "@wordpress/i18n";
497
524
  function EditModeTemplate({ postTitle, isLoading, callback }) {
498
- const inputRef = useRef();
499
- const [inputError, setInputError] = useState5("");
525
+ const [title, setTitle] = useState4(postTitle);
526
+ const [touched, setTouched] = useState4(false);
527
+ const [inputError, setInputError] = useState4(null);
500
528
  const closeButton = useRef();
501
529
  const onBlur = (e) => {
502
530
  if (closeButton.current === e.relatedTarget) {
@@ -508,43 +536,48 @@ function EditModeTemplate({ postTitle, isLoading, callback }) {
508
536
  e.preventDefault();
509
537
  runCallback();
510
538
  };
511
- const validateInput = () => {
512
- let isValid = true;
513
- if (inputRef.current?.value === "") {
514
- isValid = false;
515
- setInputError(__4("Name is required", "elementor"));
516
- }
517
- return isValid;
539
+ const validateInput = (input) => {
540
+ return input.trim() !== "";
518
541
  };
519
542
  const runCallback = () => {
520
- if (!validateInput()) {
543
+ if (!validateInput(title)) {
521
544
  return;
522
545
  }
523
- callback(inputRef.current?.value || "");
546
+ callback(title);
524
547
  };
525
- return /* @__PURE__ */ React8.createElement(
548
+ const onChange = (e) => {
549
+ if (!touched) {
550
+ setTouched(true);
551
+ }
552
+ const value = e.target.value;
553
+ if (!validateInput(value)) {
554
+ setInputError(__4("Name is required", "elementor"));
555
+ } else {
556
+ setInputError(null);
557
+ }
558
+ setTitle(value);
559
+ };
560
+ return /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(
526
561
  ListItem2,
527
562
  {
528
- sx: { pt: 1, pl: 0 },
529
563
  secondaryAction: /* @__PURE__ */ React8.createElement(CloseButton, { isLoading, closeButton })
530
564
  },
531
- /* @__PURE__ */ React8.createElement(Box, { width: "100%", sx: { ml: 4, pr: 3 }, component: "form", onSubmit: onFormSubmit }, /* @__PURE__ */ React8.createElement(
565
+ /* @__PURE__ */ React8.createElement(Box, { width: "100%", component: "form", onSubmit: onFormSubmit }, /* @__PURE__ */ React8.createElement(
532
566
  TextField,
533
567
  {
534
568
  autoFocus: true,
535
569
  fullWidth: true,
536
- ref: inputRef,
537
- defaultValue: postTitle,
570
+ value: title,
571
+ onChange,
538
572
  disabled: isLoading,
539
573
  error: !!inputError,
540
574
  onBlur,
541
575
  variant: "outlined",
542
576
  color: "secondary",
543
- size: "small",
544
- margin: "dense"
577
+ size: "small"
545
578
  }
546
579
  ))
547
- );
580
+ ), inputError && /* @__PURE__ */ React8.createElement(ListItem2, null, /* @__PURE__ */ React8.createElement(ListItemText5, { sx: { color: "error.main" } }, inputError)));
548
581
  }
549
582
  function CloseButton({ isLoading, closeButton }) {
550
583
  const { resetEditMode } = usePostListContext();
@@ -565,18 +598,21 @@ function CloseButton({ isLoading, closeButton }) {
565
598
  function ListItemRename({ post }) {
566
599
  const { type, resetEditMode } = usePostListContext();
567
600
  const { updatePost } = usePostActions(type);
568
- const renamePostCallback = (inputValue) => {
601
+ const { setError } = usePostListContext();
602
+ const renamePostCallback = async (inputValue) => {
569
603
  if (inputValue === post.title.rendered) {
570
604
  resetEditMode();
571
605
  }
572
- updatePost.mutateAsync({
573
- id: post.id,
574
- title: inputValue
575
- }, {
576
- onSuccess: () => {
577
- resetEditMode();
578
- }
579
- });
606
+ try {
607
+ await updatePost.mutateAsync({
608
+ id: post.id,
609
+ title: inputValue
610
+ });
611
+ } catch (e) {
612
+ setError();
613
+ } finally {
614
+ resetEditMode();
615
+ }
580
616
  };
581
617
  return /* @__PURE__ */ React9.createElement(EditModeTemplate, { postTitle: post.title.rendered, isLoading: updatePost.isPending, callback: renamePostCallback });
582
618
  }
@@ -589,16 +625,19 @@ function ListItemCreate() {
589
625
  const { type, resetEditMode } = usePostListContext();
590
626
  const { createPost } = usePostActions(type);
591
627
  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
- });
628
+ const { setError } = usePostListContext();
629
+ const createPostCallback = async (inputValue) => {
630
+ try {
631
+ const { id } = await createPost.mutateAsync({
632
+ title: inputValue,
633
+ status: "draft"
634
+ });
635
+ navigateToDocument(id);
636
+ } catch (e) {
637
+ setError();
638
+ } finally {
639
+ resetEditMode();
640
+ }
602
641
  };
603
642
  return /* @__PURE__ */ React10.createElement(EditModeTemplate, { postTitle: __5("New Page", "elementor"), isLoading: createPost.isPending, callback: createPostCallback });
604
643
  }
@@ -611,19 +650,22 @@ function ListItemDuplicate() {
611
650
  const { type, editMode, resetEditMode } = usePostListContext();
612
651
  const navigateToDocument = useNavigateToDocument4();
613
652
  const { duplicatePost } = usePostActions(type);
653
+ const { setError } = usePostListContext();
614
654
  if ("duplicate" !== editMode.mode) {
615
655
  return null;
616
656
  }
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
- });
657
+ const duplicatePostCallback = async (inputValue) => {
658
+ try {
659
+ const { post_id: postId } = await duplicatePost.mutateAsync({
660
+ id: editMode.details.postId,
661
+ title: inputValue
662
+ });
663
+ navigateToDocument(postId);
664
+ } catch (e) {
665
+ setError();
666
+ } finally {
667
+ resetEditMode();
668
+ }
627
669
  };
628
670
  return /* @__PURE__ */ React11.createElement(EditModeTemplate, { postTitle: `${editMode.details.title} ${__6("copy", "elementor")}`, isLoading: duplicatePost.isPending, callback: duplicatePostCallback });
629
671
  }
@@ -634,12 +676,11 @@ import {
634
676
  bindMenu as bindMenu2,
635
677
  bindTrigger as bindTrigger2,
636
678
  Divider as Divider4,
679
+ IconButton as IconButton3,
637
680
  ListItem as ListItem3,
638
- ListItemButton as ListItemButton2,
639
- ListItemIcon as ListItemIcon4,
640
- ListItemText as ListItemText6,
681
+ ListItemButton,
682
+ ListItemText as ListItemText7,
641
683
  Menu as Menu2,
642
- ToggleButton,
643
684
  usePopupState as usePopupState2
644
685
  } from "@elementor/ui";
645
686
  import { DotsVerticalIcon, HomeIcon as HomeIcon2 } from "@elementor/icons";
@@ -657,6 +698,7 @@ var PageStatus = ({ status }) => {
657
698
  {
658
699
  component: "span",
659
700
  variant: "body2",
701
+ color: "text.secondary",
660
702
  sx: {
661
703
  textTransform: "capitalize",
662
704
  fontStyle: "italic",
@@ -676,6 +718,7 @@ var PageTitle = ({ title }) => {
676
718
  {
677
719
  component: "span",
678
720
  variant: "body2",
721
+ color: "text.secondary",
679
722
  noWrap: true,
680
723
  sx: {
681
724
  flexBasis: "auto"
@@ -696,20 +739,14 @@ import { __ as __7 } from "@wordpress/i18n";
696
739
  // src/components/panel/actions-menu/action-menu-item.tsx
697
740
  import * as React13 from "react";
698
741
  import {
699
- ListItemButton,
700
742
  ListItemIcon as ListItemIcon3,
701
- ListItemText as ListItemText5,
743
+ ListItemText as ListItemText6,
702
744
  MenuItem as MenuItem4
703
745
  } 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
- ));
746
+ function ActionMenuItem({ title, icon: Icon, MenuItemProps: MenuItemProps3 }) {
747
+ return /* @__PURE__ */ React13.createElement(MenuItem4, { ...MenuItemProps3 }, /* @__PURE__ */ React13.createElement(ListItemIcon3, { sx: {
748
+ color: "inherit"
749
+ } }, /* @__PURE__ */ React13.createElement(Icon, null)), /* @__PURE__ */ React13.createElement(ListItemText6, { primary: title }));
713
750
  }
714
751
 
715
752
  // src/components/panel/actions-menu/actions/rename.tsx
@@ -720,7 +757,7 @@ function Rename({ post }) {
720
757
  {
721
758
  title: __7("Rename", "elementor"),
722
759
  icon: EraseIcon,
723
- ListItemButtonProps: {
760
+ MenuItemProps: {
724
761
  onClick: () => {
725
762
  setEditMode({
726
763
  mode: "rename",
@@ -755,7 +792,7 @@ function Duplicate({ post, popupState }) {
755
792
  {
756
793
  title: __8("Duplicate", "elementor"),
757
794
  icon: CopyIcon,
758
- ListItemButtonProps: {
795
+ MenuItemProps: {
759
796
  onClick
760
797
  }
761
798
  }
@@ -776,10 +813,10 @@ import {
776
813
  DialogTitle,
777
814
  Divider as Divider3
778
815
  } from "@elementor/ui";
779
- import { useState as useState6 } from "react";
816
+ import { useState as useState5 } from "react";
780
817
  import { __useActiveDocument as useActiveDocument2 } from "@elementor/editor-documents";
781
818
  function Delete({ post }) {
782
- const [isDialogOpen, setIsDialogOpen] = useState6(false);
819
+ const [isDialogOpen, setIsDialogOpen] = useState5(false);
783
820
  const activeDocument = useActiveDocument2();
784
821
  const isPostActive = activeDocument?.id === post.id;
785
822
  return /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(
@@ -787,7 +824,7 @@ function Delete({ post }) {
787
824
  {
788
825
  title: __9("Delete", "elementor"),
789
826
  icon: TrashIcon,
790
- ListItemButtonProps: {
827
+ MenuItemProps: {
791
828
  disabled: post.isHome || isPostActive,
792
829
  onClick: () => setIsDialogOpen(true),
793
830
  sx: { "&:hover": { color: "error.main" } }
@@ -798,9 +835,15 @@ function Delete({ post }) {
798
835
  function DeleteDialog({ post, setIsDialogOpen }) {
799
836
  const { type } = usePostListContext();
800
837
  const { deletePost } = usePostActions(type);
838
+ const { setError } = usePostListContext();
801
839
  const dialogTitle = sprintf(__9('Delete "%s"?', "elementor"), post.title.rendered);
802
840
  const deletePage = async () => {
803
- await deletePost.mutateAsync(post.id);
841
+ try {
842
+ await deletePost.mutateAsync(post.id);
843
+ } catch (e) {
844
+ setError();
845
+ setIsDialogOpen(false);
846
+ }
804
847
  };
805
848
  const handleCancel = () => {
806
849
  if (deletePost.isPending) {
@@ -834,7 +877,7 @@ function View({ post }) {
834
877
  {
835
878
  title,
836
879
  icon: EyeIcon,
837
- ListItemButtonProps: {
880
+ MenuItemProps: {
838
881
  onClick: () => window.open(post.link, "_blank")
839
882
  }
840
883
  }
@@ -869,10 +912,10 @@ var updateSettings = (settings) => {
869
912
  };
870
913
 
871
914
  // src/hooks/use-homepage.ts
872
- import { useQuery as useQuery2 } from "@elementor/query";
915
+ import { useQuery as useQuery3 } from "@elementor/query";
873
916
  var settingsQueryKey = () => ["site-navigation", "homepage"];
874
917
  function useHomepage() {
875
- return useQuery2({
918
+ return useQuery3({
876
919
  queryKey: settingsQueryKey(),
877
920
  queryFn: () => getSettings()
878
921
  });
@@ -898,17 +941,24 @@ function useInvalidateSettings() {
898
941
 
899
942
  // src/components/panel/actions-menu/actions/set-home.tsx
900
943
  import { CircularProgress as CircularProgress4 } from "@elementor/ui";
901
- function SetHome({ post }) {
944
+ function SetHome({ post, closeMenu }) {
902
945
  const { updateSettingsMutation } = useHomepageActions();
903
- const handleClick = () => {
904
- updateSettingsMutation.mutateAsync({ show_on_front: "page", page_on_front: post.id });
946
+ const { setError } = usePostListContext();
947
+ const handleClick = async () => {
948
+ try {
949
+ await updateSettingsMutation.mutateAsync({ show_on_front: "page", page_on_front: post.id });
950
+ } catch (error) {
951
+ setError();
952
+ } finally {
953
+ closeMenu();
954
+ }
905
955
  };
906
956
  return /* @__PURE__ */ React18.createElement(
907
957
  ActionMenuItem,
908
958
  {
909
959
  title: __11("Set as homepage", "elementor"),
910
960
  icon: !updateSettingsMutation.isPending ? HomeIcon : CircularProgress4,
911
- ListItemButtonProps: {
961
+ MenuItemProps: {
912
962
  disabled: !!post.isHome || post.status !== "publish" || updateSettingsMutation.isPending,
913
963
  onClick: handleClick
914
964
  }
@@ -932,19 +982,17 @@ function ListItemView({ post }) {
932
982
  {
933
983
  disablePadding: true,
934
984
  secondaryAction: /* @__PURE__ */ React19.createElement(
935
- ToggleButton,
985
+ IconButton3,
936
986
  {
937
987
  value: true,
938
- color: "secondary",
939
988
  size: "small",
940
- selected: popupState.isOpen,
941
989
  ...bindTrigger2(popupState)
942
990
  },
943
991
  /* @__PURE__ */ React19.createElement(DotsVerticalIcon, { fontSize: "small" })
944
992
  )
945
993
  },
946
994
  /* @__PURE__ */ React19.createElement(
947
- ListItemButton2,
995
+ ListItemButton,
948
996
  {
949
997
  selected: isActive,
950
998
  onClick: () => {
@@ -952,18 +1000,16 @@ function ListItemView({ post }) {
952
1000
  navigateToDocument(post.id);
953
1001
  }
954
1002
  },
955
- dense: true,
956
- disableGutters: true
1003
+ dense: true
957
1004
  },
958
- /* @__PURE__ */ React19.createElement(ListItemIcon4, null),
959
1005
  /* @__PURE__ */ React19.createElement(
960
- ListItemText6,
1006
+ ListItemText7,
961
1007
  {
962
1008
  disableTypography: true
963
1009
  },
964
1010
  /* @__PURE__ */ React19.createElement(PageTitleAndStatus, { page: post })
965
1011
  ),
966
- post.isHome && /* @__PURE__ */ React19.createElement(ListItemIcon4, null, /* @__PURE__ */ React19.createElement(HomeIcon2, { titleAccess: __12("Homepage", "elementor"), color: "disabled" }))
1012
+ post.isHome && /* @__PURE__ */ React19.createElement(HomeIcon2, { titleAccess: __12("Homepage", "elementor"), color: "disabled" })
967
1013
  )
968
1014
  ), /* @__PURE__ */ React19.createElement(
969
1015
  Menu2,
@@ -977,7 +1023,7 @@ function ListItemView({ post }) {
977
1023
  /* @__PURE__ */ React19.createElement(Delete, { post }),
978
1024
  /* @__PURE__ */ React19.createElement(View, { post }),
979
1025
  /* @__PURE__ */ React19.createElement(Divider4, null),
980
- /* @__PURE__ */ React19.createElement(SetHome, { post })
1026
+ /* @__PURE__ */ React19.createElement(SetHome, { post, closeMenu: () => popupState.close() })
981
1027
  ));
982
1028
  }
983
1029
 
@@ -1010,61 +1056,135 @@ function AddNewButton() {
1010
1056
  Button3,
1011
1057
  {
1012
1058
  size: "small",
1013
- sx: { mt: 4, mb: 4, mr: 5 },
1014
1059
  startIcon: /* @__PURE__ */ React21.createElement(PlusIcon2, null),
1015
1060
  onClick: () => {
1016
1061
  setEditMode({ mode: "create", details: {} });
1062
+ },
1063
+ sx: {
1064
+ px: 1.5
1017
1065
  }
1018
1066
  },
1019
1067
  __13("Add New", "elementor")
1020
1068
  );
1021
1069
  }
1022
1070
 
1071
+ // src/components/panel/posts-list/error-state.tsx
1072
+ import { Error404TemplateIcon } from "@elementor/icons";
1073
+ import { Box as Box3, Link, Typography as Typography3 } from "@elementor/ui";
1074
+ import { __ as __14 } from "@wordpress/i18n";
1075
+ import * as React22 from "react";
1076
+ function ErrorState() {
1077
+ return /* @__PURE__ */ React22.createElement(Box3, { sx: {
1078
+ display: "flex",
1079
+ flexDirection: "column",
1080
+ justifyContent: "center",
1081
+ alignItems: "center",
1082
+ pt: "40px",
1083
+ gap: "16px"
1084
+ } }, /* @__PURE__ */ React22.createElement(Error404TemplateIcon, null), /* @__PURE__ */ React22.createElement(Box3, { sx: {
1085
+ display: "flex",
1086
+ flexDirection: "column",
1087
+ justifyContent: "center",
1088
+ alignItems: "center",
1089
+ gap: "8px"
1090
+ } }, /* @__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")))));
1091
+ }
1092
+
1023
1093
  // src/components/panel/posts-list/posts-collapsible-list.tsx
1024
1094
  function PostsCollapsibleList({ isOpenByDefault = false }) {
1025
1095
  const { type, editMode } = usePostListContext();
1026
- const { data: posts, isLoading: postsLoading } = usePosts(type);
1096
+ const { data: posts, isLoading: postsLoading, isError: postsError } = usePosts(type);
1027
1097
  const { data: homepageSettings } = useHomepage();
1098
+ if (postsError) {
1099
+ return /* @__PURE__ */ React23.createElement(ErrorState, null);
1100
+ }
1028
1101
  if (!posts || postsLoading) {
1029
- return /* @__PURE__ */ React22.createElement(Box3, { sx: { px: 5 } }, /* @__PURE__ */ React22.createElement(
1030
- Box3,
1102
+ return /* @__PURE__ */ React23.createElement(Box4, { sx: { px: 5 } }, /* @__PURE__ */ React23.createElement(
1103
+ Box4,
1031
1104
  {
1032
1105
  display: "flex",
1033
1106
  justifyContent: "flex-end",
1034
1107
  alignItems: "center"
1035
1108
  },
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" })));
1109
+ /* @__PURE__ */ React23.createElement(Skeleton, { sx: { my: 4 }, animation: "wave", variant: "rounded", width: "110px", height: "28px" })
1110
+ ), /* @__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
1111
  }
1039
1112
  const label = `${postTypesMap[type].labels.plural_name} (${posts.length.toString()})`;
1040
1113
  const isHomepageSet = homepageSettings?.show_on_front === "page" && !!homepageSettings?.page_on_front;
1041
1114
  const homepageId = isHomepageSet ? homepageSettings.page_on_front : null;
1042
- return /* @__PURE__ */ React22.createElement(React22.Fragment, null, /* @__PURE__ */ React22.createElement(
1043
- Box3,
1115
+ const mappedPosts = posts.map((post) => {
1116
+ if (post.id === homepageId) {
1117
+ return { ...post, isHome: true };
1118
+ }
1119
+ return post;
1120
+ });
1121
+ const sortedPosts = mappedPosts.sort((a, b) => {
1122
+ if (a.id === homepageId) {
1123
+ return -1;
1124
+ }
1125
+ if (b.id === homepageId) {
1126
+ return 1;
1127
+ }
1128
+ return 0;
1129
+ });
1130
+ return /* @__PURE__ */ React23.createElement(React23.Fragment, null, /* @__PURE__ */ React23.createElement(
1131
+ Box4,
1044
1132
  {
1045
1133
  display: "flex",
1046
1134
  justifyContent: "flex-end",
1047
- alignItems: "center"
1135
+ alignItems: "center",
1136
+ sx: {
1137
+ py: 1,
1138
+ px: 2
1139
+ }
1048
1140
  },
1049
- /* @__PURE__ */ React22.createElement(AddNewButton, null)
1050
- ), /* @__PURE__ */ React22.createElement(List2, { dense: true }, /* @__PURE__ */ React22.createElement(
1141
+ /* @__PURE__ */ React23.createElement(AddNewButton, null)
1142
+ ), /* @__PURE__ */ React23.createElement(List2, { dense: true }, /* @__PURE__ */ React23.createElement(
1051
1143
  CollapsibleList,
1052
1144
  {
1053
1145
  label,
1054
1146
  Icon: PageTypeIcon2,
1055
1147
  isOpenByDefault: isOpenByDefault || false
1056
1148
  },
1057
- posts.map((post) => {
1058
- post = { ...post, isHome: post.id === homepageId };
1059
- return /* @__PURE__ */ React22.createElement(PostListItem2, { key: post.id, post });
1149
+ sortedPosts.map((post) => {
1150
+ return /* @__PURE__ */ React23.createElement(PostListItem2, { key: post.id, post });
1060
1151
  }),
1061
- ["duplicate", "create"].includes(editMode.mode) && /* @__PURE__ */ React22.createElement(PostListItem2, null)
1152
+ ["duplicate", "create"].includes(editMode.mode) && /* @__PURE__ */ React23.createElement(PostListItem2, null)
1062
1153
  )));
1063
1154
  }
1064
1155
 
1156
+ // src/components/panel/error-snackbar.tsx
1157
+ import { Snackbar, Alert, Typography as Typography4 } from "@elementor/ui";
1158
+ import * as React24 from "react";
1159
+ var ErrorSnackbar = ({ open, onClose }) => {
1160
+ return /* @__PURE__ */ React24.createElement(
1161
+ Snackbar,
1162
+ {
1163
+ open,
1164
+ onClose,
1165
+ anchorOrigin: {
1166
+ vertical: "bottom",
1167
+ horizontal: "left"
1168
+ }
1169
+ },
1170
+ /* @__PURE__ */ React24.createElement(Alert, { onClose, severity: "error", sx: { width: "100%" } }, /* @__PURE__ */ React24.createElement(
1171
+ Typography4,
1172
+ {
1173
+ component: "span",
1174
+ sx: {
1175
+ fontWeight: "bold"
1176
+ }
1177
+ },
1178
+ "We couldn\u2019t complete the action."
1179
+ ), " ", "Please try again")
1180
+ );
1181
+ };
1182
+ var error_snackbar_default = ErrorSnackbar;
1183
+
1065
1184
  // src/components/panel/shell.tsx
1066
1185
  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 }))));
1186
+ const [isErrorSnackbarOpen, setIsErrorSnackbarOpen] = React25.useState(false);
1187
+ 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
1188
  };
1069
1189
  var shell_default = Shell;
1070
1190
 
@@ -1083,7 +1203,7 @@ function useToggleButtonProps() {
1083
1203
  const { isOpen, isBlocked } = usePanelStatus();
1084
1204
  const { open, close } = usePanelActions();
1085
1205
  return {
1086
- title: __15("Pages", "elementor"),
1206
+ title: __16("Pages", "elementor"),
1087
1207
  icon: PagesIcon,
1088
1208
  onClick: () => isOpen ? close() : open(),
1089
1209
  selected: isOpen,