@elementor/editor-site-navigation 0.6.2 → 0.8.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 +22 -0
- package/README.md +48 -0
- package/dist/index.js +338 -0
- package/dist/index.mjs +347 -0
- package/package.json +7 -6
- package/src/components/panel/actions-menu/action-list-item.tsx +27 -0
- package/src/components/panel/actions-menu/action-menu-item.tsx +11 -0
- package/src/components/panel/actions-menu/page-actions-menu.tsx +29 -0
- package/src/components/panel/pages-actions/delete.tsx +21 -0
- package/src/components/panel/pages-actions/duplicate.tsx +14 -0
- package/src/components/panel/pages-actions/rename.tsx +14 -0
- package/src/components/panel/pages-actions/set-home.tsx +16 -0
- package/src/components/panel/pages-actions/view.tsx +14 -0
- package/src/components/panel/pages-list/__tests__/page-list-item.test.tsx +110 -0
- package/src/components/panel/pages-list/__tests__/pages-collapsible-list.test.tsx +48 -0
- package/src/components/panel/pages-list/collapsible-list.tsx +63 -0
- package/src/components/panel/pages-list/page-list-item.tsx +66 -0
- package/src/components/panel/pages-list/pages-collapsible-list.tsx +24 -0
- package/src/components/panel/shell.tsx +58 -0
- package/src/components/shared/page-title-and-status.tsx +50 -0
- package/src/hooks/types/interfaces.ts +13 -0
- package/src/hooks/use-post-types.ts +64 -0
- package/src/hooks/use-posts.ts +123 -0
- package/src/init.ts +12 -0
- package/src/types.ts +7 -0
package/dist/index.mjs
CHANGED
|
@@ -230,8 +230,349 @@ function RecentlyEdited() {
|
|
|
230
230
|
|
|
231
231
|
// src/init.ts
|
|
232
232
|
import { injectIntoPageIndication } from "@elementor/editor-app-bar";
|
|
233
|
+
import { injectIntoTop } from "@elementor/editor";
|
|
234
|
+
|
|
235
|
+
// src/components/panel/shell.tsx
|
|
236
|
+
import * as React18 from "react";
|
|
237
|
+
import { Box as Box3, Button as Button2, Divider as Divider3, Grid, List as List2, Paper, ThemeProvider, Typography as Typography4 } from "@elementor/ui";
|
|
238
|
+
import { PlusIcon as PlusIcon2 } from "@elementor/icons";
|
|
239
|
+
|
|
240
|
+
// src/components/panel/pages-list/pages-collapsible-list.tsx
|
|
241
|
+
import * as React17 from "react";
|
|
242
|
+
|
|
243
|
+
// src/components/panel/pages-list/collapsible-list.tsx
|
|
244
|
+
import * as React6 from "react";
|
|
245
|
+
import { useState as useState3 } from "react";
|
|
246
|
+
import { Collapse, IconButton, List, ListItem, ListItemIcon as ListItemIcon2, ListItemText, styled } from "@elementor/ui";
|
|
247
|
+
import { ChevronDownIcon as ChevronDownIcon2 } from "@elementor/icons";
|
|
248
|
+
var RotateIcon = styled(ChevronDownIcon2, {
|
|
249
|
+
shouldForwardProp: (prop) => prop !== "isOpen"
|
|
250
|
+
})(({ theme, isOpen }) => ({
|
|
251
|
+
transform: isOpen ? "rotate(0deg)" : "rotate(-90deg)",
|
|
252
|
+
transition: theme.transitions.create("transform", {
|
|
253
|
+
duration: theme.transitions.duration.standard
|
|
254
|
+
})
|
|
255
|
+
}));
|
|
256
|
+
function CollapsibleList({
|
|
257
|
+
label,
|
|
258
|
+
Icon,
|
|
259
|
+
isOpenByDefault = false,
|
|
260
|
+
children
|
|
261
|
+
}) {
|
|
262
|
+
const [isOpen, setIsOpen] = useState3(isOpenByDefault);
|
|
263
|
+
return /* @__PURE__ */ React6.createElement(React6.Fragment, null, /* @__PURE__ */ React6.createElement(ListItem, { disableGutters: true }, /* @__PURE__ */ React6.createElement(ListItemIcon2, null, /* @__PURE__ */ React6.createElement(
|
|
264
|
+
IconButton,
|
|
265
|
+
{
|
|
266
|
+
onClick: () => setIsOpen((prev) => !prev),
|
|
267
|
+
sx: { color: "inherit" },
|
|
268
|
+
size: "small"
|
|
269
|
+
},
|
|
270
|
+
/* @__PURE__ */ React6.createElement(RotateIcon, { fontSize: "small", isOpen })
|
|
271
|
+
)), /* @__PURE__ */ React6.createElement(ListItemIcon2, null, /* @__PURE__ */ React6.createElement(Icon, null)), /* @__PURE__ */ React6.createElement(ListItemText, null, label)), /* @__PURE__ */ React6.createElement(
|
|
272
|
+
Collapse,
|
|
273
|
+
{
|
|
274
|
+
in: isOpen,
|
|
275
|
+
timeout: "auto",
|
|
276
|
+
unmountOnExit: true
|
|
277
|
+
},
|
|
278
|
+
/* @__PURE__ */ React6.createElement(List, { dense: true }, children)
|
|
279
|
+
));
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// src/components/panel/pages-list/pages-collapsible-list.tsx
|
|
283
|
+
import { PageTypeIcon as PageTypeIcon2 } from "@elementor/icons";
|
|
284
|
+
|
|
285
|
+
// src/components/panel/pages-list/page-list-item.tsx
|
|
286
|
+
import * as React16 from "react";
|
|
287
|
+
import {
|
|
288
|
+
bindMenu as bindMenu2,
|
|
289
|
+
bindTrigger as bindTrigger2,
|
|
290
|
+
ListItem as ListItem2,
|
|
291
|
+
ListItemButton as ListItemButton2,
|
|
292
|
+
ListItemIcon as ListItemIcon4,
|
|
293
|
+
ListItemText as ListItemText3,
|
|
294
|
+
ToggleButton,
|
|
295
|
+
usePopupState as usePopupState2
|
|
296
|
+
} from "@elementor/ui";
|
|
297
|
+
import { DotsVerticalIcon, HomeIcon as HomeIcon2 } from "@elementor/icons";
|
|
298
|
+
import { useActiveDocument as useActiveDocument3, useNavigateToDocument as useNavigateToDocument3 } from "@elementor/editor-documents";
|
|
299
|
+
|
|
300
|
+
// src/components/shared/page-title-and-status.tsx
|
|
301
|
+
import * as React7 from "react";
|
|
302
|
+
import { Box as Box2, Typography as Typography3 } from "@elementor/ui";
|
|
303
|
+
var PageStatus = ({ status }) => {
|
|
304
|
+
if ("publish" === status) {
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
return /* @__PURE__ */ React7.createElement(
|
|
308
|
+
Typography3,
|
|
309
|
+
{
|
|
310
|
+
component: "span",
|
|
311
|
+
variant: "body1",
|
|
312
|
+
sx: {
|
|
313
|
+
textTransform: "capitalize",
|
|
314
|
+
fontStyle: "italic",
|
|
315
|
+
whiteSpace: "nowrap",
|
|
316
|
+
flexBasis: "content"
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
"(",
|
|
320
|
+
status,
|
|
321
|
+
")"
|
|
322
|
+
);
|
|
323
|
+
};
|
|
324
|
+
var PageTitle = ({ title }) => {
|
|
325
|
+
const modifiedTitle = useReverseHtmlEntities(title);
|
|
326
|
+
return /* @__PURE__ */ React7.createElement(
|
|
327
|
+
Typography3,
|
|
328
|
+
{
|
|
329
|
+
component: "span",
|
|
330
|
+
variant: "body1",
|
|
331
|
+
noWrap: true,
|
|
332
|
+
sx: {
|
|
333
|
+
flexBasis: "auto"
|
|
334
|
+
}
|
|
335
|
+
},
|
|
336
|
+
modifiedTitle
|
|
337
|
+
);
|
|
338
|
+
};
|
|
339
|
+
function PageTitleAndStatus({ page }) {
|
|
340
|
+
return /* @__PURE__ */ React7.createElement(Box2, { display: "flex" }, /* @__PURE__ */ React7.createElement(PageTitle, { title: page.title }), "\xA0", /* @__PURE__ */ React7.createElement(PageStatus, { status: page.status }));
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// src/components/panel/actions-menu/page-actions-menu.tsx
|
|
344
|
+
import * as React15 from "react";
|
|
345
|
+
import { Divider as Divider2, Menu as Menu2 } from "@elementor/ui";
|
|
346
|
+
|
|
347
|
+
// src/components/panel/pages-actions/rename.tsx
|
|
348
|
+
import * as React10 from "react";
|
|
349
|
+
import { EraseIcon } from "@elementor/icons";
|
|
350
|
+
import { __ as __3 } from "@wordpress/i18n";
|
|
351
|
+
|
|
352
|
+
// src/components/panel/actions-menu/action-menu-item.tsx
|
|
353
|
+
import * as React9 from "react";
|
|
354
|
+
|
|
355
|
+
// src/components/panel/actions-menu/action-list-item.tsx
|
|
356
|
+
import * as React8 from "react";
|
|
357
|
+
import { ListItemButton, ListItemIcon as ListItemIcon3, ListItemText as ListItemText2 } from "@elementor/ui";
|
|
358
|
+
function ActionListItem({ title, icon: Icon, disabled, onClick }) {
|
|
359
|
+
return /* @__PURE__ */ React8.createElement(
|
|
360
|
+
ListItemButton,
|
|
361
|
+
{
|
|
362
|
+
disabled,
|
|
363
|
+
onClick
|
|
364
|
+
},
|
|
365
|
+
/* @__PURE__ */ React8.createElement(ListItemIcon3, null, /* @__PURE__ */ React8.createElement(Icon, null)),
|
|
366
|
+
/* @__PURE__ */ React8.createElement(ListItemText2, null, title)
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// src/components/panel/actions-menu/action-menu-item.tsx
|
|
371
|
+
import { MenuItem as MenuItem3 } from "@elementor/ui";
|
|
372
|
+
function ActionMenuItem(props) {
|
|
373
|
+
return /* @__PURE__ */ React9.createElement(MenuItem3, { disableGutters: true }, /* @__PURE__ */ React9.createElement(ActionListItem, { ...props }));
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// src/components/panel/pages-actions/rename.tsx
|
|
377
|
+
function Rename() {
|
|
378
|
+
return /* @__PURE__ */ React10.createElement(
|
|
379
|
+
ActionMenuItem,
|
|
380
|
+
{
|
|
381
|
+
title: __3("Rename", "elementor"),
|
|
382
|
+
icon: EraseIcon,
|
|
383
|
+
onClick: () => null
|
|
384
|
+
}
|
|
385
|
+
);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// src/components/panel/pages-actions/duplicate.tsx
|
|
389
|
+
import * as React11 from "react";
|
|
390
|
+
import { __ as __4 } from "@wordpress/i18n";
|
|
391
|
+
import { CopyIcon } from "@elementor/icons";
|
|
392
|
+
function Duplicate() {
|
|
393
|
+
return /* @__PURE__ */ React11.createElement(
|
|
394
|
+
ActionMenuItem,
|
|
395
|
+
{
|
|
396
|
+
title: __4("Duplicate", "elementor"),
|
|
397
|
+
icon: CopyIcon,
|
|
398
|
+
onClick: () => null
|
|
399
|
+
}
|
|
400
|
+
);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// src/components/panel/pages-actions/delete.tsx
|
|
404
|
+
import * as React12 from "react";
|
|
405
|
+
import { TrashIcon } from "@elementor/icons";
|
|
406
|
+
import { useActiveDocument as useActiveDocument2 } from "@elementor/editor-documents";
|
|
407
|
+
import { __ as __5 } from "@wordpress/i18n";
|
|
408
|
+
function Delete({ page }) {
|
|
409
|
+
const activeDocument = useActiveDocument2();
|
|
410
|
+
const isActive = activeDocument?.id === page.id;
|
|
411
|
+
return /* @__PURE__ */ React12.createElement(
|
|
412
|
+
ActionMenuItem,
|
|
413
|
+
{
|
|
414
|
+
title: __5("Delete", "elementor"),
|
|
415
|
+
icon: TrashIcon,
|
|
416
|
+
disabled: page.isHome || isActive,
|
|
417
|
+
onClick: () => null
|
|
418
|
+
}
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// src/components/panel/pages-actions/view.tsx
|
|
423
|
+
import * as React13 from "react";
|
|
424
|
+
import { EyeIcon } from "@elementor/icons";
|
|
425
|
+
import { __ as __6 } from "@wordpress/i18n";
|
|
426
|
+
function View() {
|
|
427
|
+
return /* @__PURE__ */ React13.createElement(
|
|
428
|
+
ActionMenuItem,
|
|
429
|
+
{
|
|
430
|
+
title: __6("View Page", "elementor"),
|
|
431
|
+
icon: EyeIcon,
|
|
432
|
+
onClick: () => null
|
|
433
|
+
}
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// src/components/panel/pages-actions/set-home.tsx
|
|
438
|
+
import * as React14 from "react";
|
|
439
|
+
import { HomeIcon } from "@elementor/icons";
|
|
440
|
+
import { __ as __7 } from "@wordpress/i18n";
|
|
441
|
+
function SetHome({ page }) {
|
|
442
|
+
return /* @__PURE__ */ React14.createElement(
|
|
443
|
+
ActionMenuItem,
|
|
444
|
+
{
|
|
445
|
+
title: __7("Set as homepage", "elementor"),
|
|
446
|
+
icon: HomeIcon,
|
|
447
|
+
disabled: !!page.isHome,
|
|
448
|
+
onClick: () => null
|
|
449
|
+
}
|
|
450
|
+
);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// src/components/panel/actions-menu/page-actions-menu.tsx
|
|
454
|
+
function PageActionsMenu({ page, ...props }) {
|
|
455
|
+
return /* @__PURE__ */ React15.createElement(
|
|
456
|
+
Menu2,
|
|
457
|
+
{
|
|
458
|
+
PaperProps: { sx: { mt: 4, width: 200 } },
|
|
459
|
+
MenuListProps: { dense: true },
|
|
460
|
+
...props
|
|
461
|
+
},
|
|
462
|
+
/* @__PURE__ */ React15.createElement(Rename, null),
|
|
463
|
+
/* @__PURE__ */ React15.createElement(Duplicate, null),
|
|
464
|
+
/* @__PURE__ */ React15.createElement(Delete, { page }),
|
|
465
|
+
/* @__PURE__ */ React15.createElement(View, null),
|
|
466
|
+
/* @__PURE__ */ React15.createElement(Divider2, null),
|
|
467
|
+
/* @__PURE__ */ React15.createElement(SetHome, { page })
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
// src/components/panel/pages-list/page-list-item.tsx
|
|
472
|
+
function PageListItem({ page }) {
|
|
473
|
+
const popupState = usePopupState2({
|
|
474
|
+
variant: "popover",
|
|
475
|
+
popupId: "page-actions"
|
|
476
|
+
});
|
|
477
|
+
const activeDocument = useActiveDocument3();
|
|
478
|
+
const navigateToDocument = useNavigateToDocument3();
|
|
479
|
+
const isActive = activeDocument?.id === page.id;
|
|
480
|
+
return /* @__PURE__ */ React16.createElement(React16.Fragment, null, /* @__PURE__ */ React16.createElement(
|
|
481
|
+
ListItem2,
|
|
482
|
+
{
|
|
483
|
+
disablePadding: true,
|
|
484
|
+
secondaryAction: /* @__PURE__ */ React16.createElement(
|
|
485
|
+
ToggleButton,
|
|
486
|
+
{
|
|
487
|
+
value: true,
|
|
488
|
+
color: "secondary",
|
|
489
|
+
size: "small",
|
|
490
|
+
selected: popupState.isOpen,
|
|
491
|
+
...bindTrigger2(popupState)
|
|
492
|
+
},
|
|
493
|
+
/* @__PURE__ */ React16.createElement(DotsVerticalIcon, { fontSize: "small" })
|
|
494
|
+
)
|
|
495
|
+
},
|
|
496
|
+
/* @__PURE__ */ React16.createElement(
|
|
497
|
+
ListItemButton2,
|
|
498
|
+
{
|
|
499
|
+
selected: isActive,
|
|
500
|
+
onClick: () => navigateToDocument(page.id),
|
|
501
|
+
dense: true
|
|
502
|
+
},
|
|
503
|
+
/* @__PURE__ */ React16.createElement(ListItemIcon4, null),
|
|
504
|
+
/* @__PURE__ */ React16.createElement(
|
|
505
|
+
ListItemText3,
|
|
506
|
+
{
|
|
507
|
+
disableTypography: true
|
|
508
|
+
},
|
|
509
|
+
/* @__PURE__ */ React16.createElement(PageTitleAndStatus, { page })
|
|
510
|
+
),
|
|
511
|
+
page.isHome && /* @__PURE__ */ React16.createElement(ListItemIcon4, null, /* @__PURE__ */ React16.createElement(HomeIcon2, { color: "disabled" }))
|
|
512
|
+
)
|
|
513
|
+
), /* @__PURE__ */ React16.createElement(PageActionsMenu, { page, ...bindMenu2(popupState) }));
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// src/components/panel/pages-list/pages-collapsible-list.tsx
|
|
517
|
+
function PagesCollapsibleList({ pages, isOpenByDefault = false }) {
|
|
518
|
+
const label = `Pages (${pages.length})`;
|
|
519
|
+
return /* @__PURE__ */ React17.createElement(
|
|
520
|
+
CollapsibleList,
|
|
521
|
+
{
|
|
522
|
+
label,
|
|
523
|
+
Icon: PageTypeIcon2,
|
|
524
|
+
isOpenByDefault
|
|
525
|
+
},
|
|
526
|
+
pages.map((page) => /* @__PURE__ */ React17.createElement(PageListItem, { key: page.id, page }))
|
|
527
|
+
);
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// src/components/panel/shell.tsx
|
|
531
|
+
var mockPages = [
|
|
532
|
+
{
|
|
533
|
+
id: 1,
|
|
534
|
+
type: "page",
|
|
535
|
+
title: "This is a very long title that somebody wrote, a very very long line",
|
|
536
|
+
status: "pending approval"
|
|
537
|
+
},
|
|
538
|
+
{ id: 2, type: "page", title: "About", status: "publish" },
|
|
539
|
+
{ id: 3, type: "page", title: "Services", status: "publish", isHome: true },
|
|
540
|
+
{ id: 4, type: "page", title: "Contact", status: "draft" },
|
|
541
|
+
{ id: 5, type: "page", title: "FAQ", status: "publish" }
|
|
542
|
+
];
|
|
543
|
+
var Shell = () => {
|
|
544
|
+
return /* @__PURE__ */ React18.createElement(ThemeProvider, { colorScheme: "light" }, /* @__PURE__ */ React18.createElement(Box3, { sx: { width: "100%", maxWidth: 360 } }, /* @__PURE__ */ React18.createElement(Paper, null, /* @__PURE__ */ React18.createElement(
|
|
545
|
+
Grid,
|
|
546
|
+
{
|
|
547
|
+
container: true,
|
|
548
|
+
justifyContent: "center",
|
|
549
|
+
alignItems: "center",
|
|
550
|
+
sx: { height: 51 }
|
|
551
|
+
},
|
|
552
|
+
/* @__PURE__ */ React18.createElement(Typography4, { variant: "h6" }, "Pages")
|
|
553
|
+
), /* @__PURE__ */ React18.createElement(Divider3, null), /* @__PURE__ */ React18.createElement(
|
|
554
|
+
Box3,
|
|
555
|
+
{
|
|
556
|
+
display: "flex",
|
|
557
|
+
justifyContent: "flex-end",
|
|
558
|
+
alignItems: "center"
|
|
559
|
+
},
|
|
560
|
+
/* @__PURE__ */ React18.createElement(
|
|
561
|
+
Button2,
|
|
562
|
+
{
|
|
563
|
+
sx: { mt: 4, mb: 4, mr: 5 },
|
|
564
|
+
startIcon: /* @__PURE__ */ React18.createElement(PlusIcon2, null)
|
|
565
|
+
},
|
|
566
|
+
"Add New"
|
|
567
|
+
)
|
|
568
|
+
), /* @__PURE__ */ React18.createElement(Box3, { sx: { width: "100%", maxWidth: 360 } }, /* @__PURE__ */ React18.createElement(List2, { dense: true }, /* @__PURE__ */ React18.createElement(PagesCollapsibleList, { pages: mockPages, isOpenByDefault: true }))), /* @__PURE__ */ React18.createElement(Divider3, null))));
|
|
569
|
+
};
|
|
570
|
+
var shell_default = Shell;
|
|
571
|
+
|
|
572
|
+
// src/init.ts
|
|
233
573
|
function init() {
|
|
234
574
|
registerTopBarMenuItems();
|
|
575
|
+
registerPanel();
|
|
235
576
|
}
|
|
236
577
|
function registerTopBarMenuItems() {
|
|
237
578
|
injectIntoPageIndication({
|
|
@@ -239,6 +580,12 @@ function registerTopBarMenuItems() {
|
|
|
239
580
|
filler: RecentlyEdited
|
|
240
581
|
});
|
|
241
582
|
}
|
|
583
|
+
function registerPanel() {
|
|
584
|
+
injectIntoTop({
|
|
585
|
+
id: "navigation-panel",
|
|
586
|
+
filler: shell_default
|
|
587
|
+
});
|
|
588
|
+
}
|
|
242
589
|
|
|
243
590
|
// src/index.ts
|
|
244
591
|
init();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-site-navigation",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Elementor Team",
|
|
6
6
|
"homepage": "https://elementor.com/",
|
|
@@ -32,10 +32,11 @@
|
|
|
32
32
|
"dev": "tsup --config=../../tsup.dev.ts"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@elementor/editor
|
|
36
|
-
"@elementor/editor-
|
|
37
|
-
"@elementor/
|
|
38
|
-
"@elementor/
|
|
35
|
+
"@elementor/editor": "^0.6.1",
|
|
36
|
+
"@elementor/editor-app-bar": "^0.6.3",
|
|
37
|
+
"@elementor/editor-documents": "^0.8.2",
|
|
38
|
+
"@elementor/icons": "^0.5.0",
|
|
39
|
+
"@elementor/ui": "^1.4.53",
|
|
39
40
|
"@wordpress/api-fetch": "^6.27.0",
|
|
40
41
|
"@wordpress/i18n": "^4.31.0",
|
|
41
42
|
"@wordpress/url": "^3.31.0"
|
|
@@ -46,5 +47,5 @@
|
|
|
46
47
|
"elementor": {
|
|
47
48
|
"type": "extension"
|
|
48
49
|
},
|
|
49
|
-
"gitHead": "
|
|
50
|
+
"gitHead": "d15192c0e60703e9831f7813d0a32d5943fe6c28"
|
|
50
51
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ComponentType } from 'react';
|
|
3
|
+
import { ListItemButton, ListItemIcon, ListItemText } from '@elementor/ui';
|
|
4
|
+
import { Page } from '../../../types';
|
|
5
|
+
|
|
6
|
+
export type Props = {
|
|
7
|
+
title: string;
|
|
8
|
+
icon: ComponentType;
|
|
9
|
+
disabled?: boolean;
|
|
10
|
+
onClick: ( page: Page ) => 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
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import ActionListItem, { Props as ActionListItemProps } from './action-list-item';
|
|
3
|
+
import { MenuItem } from '@elementor/ui';
|
|
4
|
+
|
|
5
|
+
export default function ActionMenuItem( props: ActionListItemProps ) {
|
|
6
|
+
return (
|
|
7
|
+
<MenuItem disableGutters>
|
|
8
|
+
<ActionListItem { ...props } />
|
|
9
|
+
</MenuItem>
|
|
10
|
+
);
|
|
11
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Divider, Menu, MenuProps } from '@elementor/ui';
|
|
3
|
+
import Rename from '../pages-actions/rename';
|
|
4
|
+
import Duplicate from '../pages-actions/duplicate';
|
|
5
|
+
import Delete from '../pages-actions/delete';
|
|
6
|
+
import { Page } from '../../../types';
|
|
7
|
+
import View from '../pages-actions/view';
|
|
8
|
+
import SetHome from '../pages-actions/set-home';
|
|
9
|
+
|
|
10
|
+
type Props = MenuProps & {
|
|
11
|
+
page: Page
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default function PageActionsMenu( { page, ...props }: Props ) {
|
|
15
|
+
return (
|
|
16
|
+
<Menu
|
|
17
|
+
PaperProps={ { sx: { mt: 4, width: 200 } } }
|
|
18
|
+
MenuListProps={ { dense: true } }
|
|
19
|
+
{ ...props }
|
|
20
|
+
>
|
|
21
|
+
<Rename />
|
|
22
|
+
<Duplicate />
|
|
23
|
+
<Delete page={ page } />
|
|
24
|
+
<View />
|
|
25
|
+
<Divider />
|
|
26
|
+
<SetHome page={ page } />
|
|
27
|
+
</Menu>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { TrashIcon } from '@elementor/icons';
|
|
3
|
+
import { Page } from '../../../types';
|
|
4
|
+
import { useActiveDocument } from '@elementor/editor-documents';
|
|
5
|
+
import { __ } from '@wordpress/i18n';
|
|
6
|
+
import ActionMenuItem from '../actions-menu/action-menu-item';
|
|
7
|
+
|
|
8
|
+
export default function Delete( { page }: { page: Page } ) {
|
|
9
|
+
const activeDocument = useActiveDocument();
|
|
10
|
+
|
|
11
|
+
const isActive = activeDocument?.id === page.id;
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<ActionMenuItem
|
|
15
|
+
title={ __( 'Delete', 'elementor' ) }
|
|
16
|
+
icon={ TrashIcon }
|
|
17
|
+
disabled={ page.isHome || isActive }
|
|
18
|
+
onClick={ () => null }
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { __ } from '@wordpress/i18n';
|
|
3
|
+
import { CopyIcon } from '@elementor/icons';
|
|
4
|
+
import ActionMenuItem from '../actions-menu/action-menu-item';
|
|
5
|
+
|
|
6
|
+
export default function Duplicate() {
|
|
7
|
+
return (
|
|
8
|
+
<ActionMenuItem
|
|
9
|
+
title={ __( 'Duplicate', 'elementor' ) }
|
|
10
|
+
icon={ CopyIcon }
|
|
11
|
+
onClick={ () => null }
|
|
12
|
+
/>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { EraseIcon } from '@elementor/icons';
|
|
3
|
+
import { __ } from '@wordpress/i18n';
|
|
4
|
+
import ActionMenuItem from '../actions-menu/action-menu-item';
|
|
5
|
+
|
|
6
|
+
export default function Rename() {
|
|
7
|
+
return (
|
|
8
|
+
<ActionMenuItem
|
|
9
|
+
title={ __( 'Rename', 'elementor' ) }
|
|
10
|
+
icon={ EraseIcon }
|
|
11
|
+
onClick={ () => null }
|
|
12
|
+
/>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Page } from '../../../types';
|
|
3
|
+
import { HomeIcon } from '@elementor/icons';
|
|
4
|
+
import { __ } from '@wordpress/i18n';
|
|
5
|
+
import ActionMenuItem from '../actions-menu/action-menu-item';
|
|
6
|
+
|
|
7
|
+
export default function SetHome( { page }: { page: Page } ) {
|
|
8
|
+
return (
|
|
9
|
+
<ActionMenuItem
|
|
10
|
+
title={ __( 'Set as homepage', 'elementor' ) }
|
|
11
|
+
icon={ HomeIcon }
|
|
12
|
+
disabled={ !! page.isHome }
|
|
13
|
+
onClick={ () => null }
|
|
14
|
+
/>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { EyeIcon } from '@elementor/icons';
|
|
3
|
+
import { __ } from '@wordpress/i18n';
|
|
4
|
+
import ActionMenuItem from '../actions-menu/action-menu-item';
|
|
5
|
+
|
|
6
|
+
export default function View() {
|
|
7
|
+
return (
|
|
8
|
+
<ActionMenuItem
|
|
9
|
+
title={ __( 'View Page', 'elementor' ) } // TODO 21/06/2023 : post label should come from post type
|
|
10
|
+
icon={ EyeIcon }
|
|
11
|
+
onClick={ () => null }
|
|
12
|
+
/>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { act, render } from '@testing-library/react';
|
|
3
|
+
import { Page } from '../../../../types';
|
|
4
|
+
import PageListItem from '../page-list-item';
|
|
5
|
+
import { useNavigateToDocument } from '@elementor/editor-documents';
|
|
6
|
+
|
|
7
|
+
jest.mock( '@elementor/editor-documents', () => ( {
|
|
8
|
+
useActiveDocument: jest.fn(),
|
|
9
|
+
useNavigateToDocument: jest.fn(),
|
|
10
|
+
} ) );
|
|
11
|
+
|
|
12
|
+
describe( '@elementor/editor-site-navigation - PageListItem', () => {
|
|
13
|
+
afterAll( () => {
|
|
14
|
+
jest.clearAllMocks();
|
|
15
|
+
} );
|
|
16
|
+
|
|
17
|
+
it( 'should render a published post', () => {
|
|
18
|
+
// Arrange.
|
|
19
|
+
const page: Page = {
|
|
20
|
+
id: 1,
|
|
21
|
+
title: 'Test Post',
|
|
22
|
+
status: 'publish',
|
|
23
|
+
type: 'page',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Act.
|
|
27
|
+
const { getByText, queryByText } = render( <PageListItem page={ page } /> );
|
|
28
|
+
|
|
29
|
+
// Assert.
|
|
30
|
+
const label = getByText( 'Test Post' );
|
|
31
|
+
const publishedLabel = queryByText( 'publish', { exact: false } );
|
|
32
|
+
|
|
33
|
+
expect( label ).toBeInTheDocument();
|
|
34
|
+
expect( publishedLabel ).toBeNull();
|
|
35
|
+
} );
|
|
36
|
+
|
|
37
|
+
it( 'should show the post status for non-published posts', () => {
|
|
38
|
+
// Arrange.
|
|
39
|
+
const page: Page = {
|
|
40
|
+
id: 1,
|
|
41
|
+
title: 'Test Post',
|
|
42
|
+
status: 'draft',
|
|
43
|
+
type: 'page',
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// Act.
|
|
47
|
+
const { getByText } = render( <PageListItem page={ page } /> );
|
|
48
|
+
|
|
49
|
+
// Assert.
|
|
50
|
+
const label = getByText( 'draft', { exact: false } );
|
|
51
|
+
expect( label ).toBeInTheDocument();
|
|
52
|
+
} );
|
|
53
|
+
|
|
54
|
+
it( 'should render actions menu', () => {
|
|
55
|
+
// Arrange.
|
|
56
|
+
const page: Page = {
|
|
57
|
+
id: 1,
|
|
58
|
+
title: 'Test Post',
|
|
59
|
+
status: 'draft',
|
|
60
|
+
type: 'page',
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const actions = [ 'View Page', 'Rename', 'Duplicate', 'Delete', 'Set as homepage' ];
|
|
64
|
+
|
|
65
|
+
// Act.
|
|
66
|
+
const { getByText, getAllByRole } = render( <PageListItem page={ page } /> );
|
|
67
|
+
const buttons = getAllByRole( 'button' );
|
|
68
|
+
// Button to open menu
|
|
69
|
+
const button = buttons[ 1 ];
|
|
70
|
+
|
|
71
|
+
act( () => {
|
|
72
|
+
// Open menu
|
|
73
|
+
button.click();
|
|
74
|
+
} );
|
|
75
|
+
|
|
76
|
+
// Assert.
|
|
77
|
+
actions.forEach( ( action ) => {
|
|
78
|
+
const label = getByText( action );
|
|
79
|
+
expect( label ).toBeInTheDocument();
|
|
80
|
+
} );
|
|
81
|
+
} );
|
|
82
|
+
|
|
83
|
+
it( 'should navigate to document on click', () => {
|
|
84
|
+
// Arrange.
|
|
85
|
+
const navigateToDocument = jest.fn();
|
|
86
|
+
jest.mocked( useNavigateToDocument ).mockReturnValue( navigateToDocument );
|
|
87
|
+
|
|
88
|
+
const id = 10;
|
|
89
|
+
|
|
90
|
+
const page: Page = {
|
|
91
|
+
id,
|
|
92
|
+
title: 'Test Post',
|
|
93
|
+
status: 'draft',
|
|
94
|
+
type: 'page',
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// Act.
|
|
98
|
+
const { getAllByRole } = render( <PageListItem page={ page } /> );
|
|
99
|
+
const buttons = getAllByRole( 'button' );
|
|
100
|
+
const button = buttons[ 0 ];
|
|
101
|
+
|
|
102
|
+
act( () => {
|
|
103
|
+
button.click();
|
|
104
|
+
} );
|
|
105
|
+
|
|
106
|
+
// Assert.
|
|
107
|
+
expect( navigateToDocument ).toHaveBeenCalledTimes( 1 );
|
|
108
|
+
expect( navigateToDocument ).toHaveBeenCalledWith( id );
|
|
109
|
+
} );
|
|
110
|
+
} );
|