@elementor/editor-app-bar 0.14.0 → 0.14.2

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 (61) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/index.d.mts +78 -196
  3. package/dist/index.d.ts +78 -196
  4. package/dist/index.js +774 -201
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.mjs +734 -162
  7. package/dist/index.mjs.map +1 -1
  8. package/package.json +9 -8
  9. package/src/components/__tests__/app-bar.test.tsx +23 -0
  10. package/src/components/actions/action.tsx +33 -0
  11. package/src/components/actions/actions-group.tsx +69 -0
  12. package/src/components/actions/link.tsx +33 -0
  13. package/src/components/actions/toggle-action.tsx +35 -0
  14. package/src/components/app-bar.tsx +42 -0
  15. package/src/components/locations/__tests__/locations-components.test.tsx +37 -0
  16. package/src/components/locations/__tests__/menus.test.tsx +158 -0
  17. package/src/components/locations/integrations-menu-location.tsx +44 -0
  18. package/src/components/locations/main-menu-location.tsx +57 -0
  19. package/src/components/locations/page-indication-location.tsx +8 -0
  20. package/src/components/locations/primary-action-location.tsx +8 -0
  21. package/src/components/locations/responsive-location.tsx +8 -0
  22. package/src/components/locations/tools-menu-location.tsx +28 -0
  23. package/src/components/locations/utilities-menu-location.tsx +35 -0
  24. package/src/components/ui/popover-menu-item.tsx +47 -0
  25. package/src/components/ui/popover-menu.tsx +26 -0
  26. package/src/components/ui/popover-sub-menu.tsx +29 -0
  27. package/src/components/ui/toolbar-logo.tsx +84 -0
  28. package/src/components/ui/toolbar-menu-item.tsx +45 -0
  29. package/src/components/ui/toolbar-menu-more.tsx +29 -0
  30. package/src/components/ui/toolbar-menu-toggle-item.tsx +34 -0
  31. package/src/components/ui/toolbar-menu.tsx +15 -0
  32. package/src/contexts/menu-context.tsx +24 -0
  33. package/src/extensions/documents-indicator/index.ts +1 -1
  34. package/src/extensions/documents-preview/index.ts +1 -1
  35. package/src/extensions/documents-save/components/primary-action-menu.tsx +1 -1
  36. package/src/extensions/documents-save/hooks/use-document-copy-and-share-props.ts +1 -1
  37. package/src/extensions/documents-save/hooks/use-document-save-draft-props.ts +1 -1
  38. package/src/extensions/documents-save/hooks/use-document-save-template-props.ts +1 -1
  39. package/src/extensions/documents-save/index.ts +1 -1
  40. package/src/extensions/documents-save/locations.ts +1 -1
  41. package/src/extensions/elements/index.ts +1 -1
  42. package/src/extensions/finder/index.ts +1 -1
  43. package/src/extensions/help/index.ts +1 -1
  44. package/src/extensions/history/index.ts +1 -1
  45. package/src/extensions/keyboard-shortcuts/hooks/use-action-props.ts +1 -2
  46. package/src/extensions/keyboard-shortcuts/index.ts +1 -1
  47. package/src/extensions/site-settings/hooks/use-action-props.ts +1 -2
  48. package/src/extensions/site-settings/index.ts +1 -1
  49. package/src/extensions/structure/hooks/use-action-props.ts +1 -2
  50. package/src/extensions/structure/index.ts +1 -1
  51. package/src/extensions/theme-builder/hooks/use-action-props.ts +1 -2
  52. package/src/extensions/theme-builder/index.ts +1 -1
  53. package/src/extensions/user-preferences/hooks/use-action-props.ts +1 -2
  54. package/src/extensions/user-preferences/index.ts +1 -1
  55. package/src/extensions/wordpress/index.ts +1 -1
  56. package/src/index.ts +14 -10
  57. package/src/init.ts +1 -1
  58. package/src/locations/__tests__/menus.test.tsx +212 -0
  59. package/src/locations/index.ts +27 -0
  60. package/src/locations/menus.tsx +172 -0
  61. package/src/types.ts +4 -0
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+ import { PropsWithChildren } from 'react';
3
+ import { bindMenu, bindTrigger, usePopupState } from '@elementor/ui';
4
+ import ToolbarMenuItem from './toolbar-menu-item';
5
+ import { __ } from '@wordpress/i18n';
6
+ import { DotsVerticalIcon } from '@elementor/icons';
7
+ import PopoverMenu from './popover-menu';
8
+
9
+ export type ToolbarMenuMoreProps = PropsWithChildren<{
10
+ id: string;
11
+ }>
12
+
13
+ export default function ToolbarMenuMore( { children, id }: ToolbarMenuMoreProps ) {
14
+ const popupState = usePopupState( {
15
+ variant: 'popover',
16
+ popupId: id,
17
+ } );
18
+
19
+ return (
20
+ <>
21
+ <ToolbarMenuItem { ...bindTrigger( popupState ) } title={ __( 'More', 'elementor' ) }>
22
+ <DotsVerticalIcon />
23
+ </ToolbarMenuItem>
24
+ <PopoverMenu onClick={ popupState.close } { ...bindMenu( popupState ) }>
25
+ { children }
26
+ </PopoverMenu>
27
+ </>
28
+ );
29
+ }
@@ -0,0 +1,34 @@
1
+ import * as React from 'react';
2
+ import { Box, ToggleButton, ToggleButtonProps, Tooltip } from '@elementor/ui';
3
+
4
+ export type ToolbarMenuToggleItemProps = Omit<ToggleButtonProps, 'onChange'> & {
5
+ title?: string;
6
+ onClick?: () => void;
7
+ }
8
+
9
+ export default function ToolbarMenuToggleItem( { title, onClick, ...props }: ToolbarMenuToggleItemProps ) {
10
+ return (
11
+ <Tooltip title={ title }>
12
+ { /* @see https://mui.com/material-ui/react-tooltip/#disabled-elements */ }
13
+ <Box component="span" aria-label={ undefined }>
14
+ <ToggleButton
15
+ { ...props }
16
+ onChange={ onClick }
17
+ aria-label={ title }
18
+ size="small"
19
+ sx={ {
20
+ border: 0, // Temp fix until the style of the ToggleButton component will be decided.
21
+ '&.Mui-disabled': {
22
+ border: 0, // Temp fix until the style of the ToggleButton component will be decided.
23
+ },
24
+ '& svg': {
25
+ fontSize: '1.25rem',
26
+ height: '1em',
27
+ width: '1em',
28
+ },
29
+ } }
30
+ />
31
+ </Box>
32
+ </Tooltip>
33
+ );
34
+ }
@@ -0,0 +1,15 @@
1
+ import * as React from 'react';
2
+ import { Stack, StackProps } from '@elementor/ui';
3
+ import { MenuContextProvider } from '../../contexts/menu-context';
4
+
5
+ export type ToolbarMenuProps = StackProps;
6
+
7
+ export default function ToolbarMenu( { children, ...props }: ToolbarMenuProps ) {
8
+ return (
9
+ <MenuContextProvider type={ 'toolbar' }>
10
+ <Stack sx={ { px: 1.5 } } spacing={ 1.5 } direction="row" alignItems="center" { ...props }>
11
+ { children }
12
+ </Stack>
13
+ </MenuContextProvider>
14
+ );
15
+ }
@@ -0,0 +1,24 @@
1
+ import * as React from 'react';
2
+ import { createContext, PropsWithChildren, useContext } from 'react';
3
+ import { PopupState } from '@elementor/ui';
4
+
5
+ type MenuContextValue = {
6
+ type: 'toolbar' | 'popover';
7
+ popupState?: PopupState;
8
+ }
9
+
10
+ const MenuContext = createContext<MenuContextValue>( {
11
+ type: 'toolbar',
12
+ } );
13
+
14
+ export function MenuContextProvider( { type, popupState, children }: PropsWithChildren<MenuContextValue> ) {
15
+ return (
16
+ <MenuContext.Provider value={ { type, popupState } }>
17
+ { children }
18
+ </MenuContext.Provider>
19
+ );
20
+ }
21
+
22
+ export function useMenuContext() {
23
+ return useContext( MenuContext );
24
+ }
@@ -1,4 +1,4 @@
1
- import { __privateInjectIntoPageIndication as injectIntoPageIndication } from '@elementor/editor-app-bar-ui';
1
+ import { injectIntoPageIndication } from '../../locations';
2
2
  import SettingsButton from './components/settings-button';
3
3
 
4
4
  export function init() {
@@ -1,4 +1,4 @@
1
- import { __privateUtilitiesMenu as utilitiesMenu } from '@elementor/editor-app-bar-ui';
1
+ import { utilitiesMenu } from '../../locations';
2
2
  import useDocumentPreviewProps from './hooks/use-action-props';
3
3
 
4
4
  export function init() {
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { Divider, styled } from '@elementor/ui';
3
- import { __privatePopoverMenu as PopoverMenu, PopoverMenuProps } from '@elementor/editor-app-bar-ui';
3
+ import { default as PopoverMenu, PopoverMenuProps } from '../../../components/ui/popover-menu';
4
4
  import { documentOptionsMenu } from '../locations';
5
5
 
6
6
  const { useMenuItems } = documentOptionsMenu;
@@ -1,5 +1,5 @@
1
1
  import { __ } from '@wordpress/i18n';
2
- import { ActionProps } from '@elementor/editor-app-bar-ui';
2
+ import { ActionProps } from '../../../types';
3
3
  import { LinkIcon } from '@elementor/icons';
4
4
  import { __useActiveDocument as useActiveDocument, __useActiveDocumentActions as useActiveDocumentActions } from '@elementor/editor-documents';
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { __ } from '@wordpress/i18n';
2
- import { ActionProps } from '@elementor/editor-app-bar-ui';
2
+ import { ActionProps } from '../../../types';
3
3
  import { FileReportIcon } from '@elementor/icons';
4
4
  import { __useActiveDocument as useActiveDocument, __useActiveDocumentActions as useActiveDocumentActions } from '@elementor/editor-documents';
5
5
 
@@ -1,5 +1,5 @@
1
1
  import { __ } from '@wordpress/i18n';
2
- import { ActionProps } from '@elementor/editor-app-bar-ui';
2
+ import { ActionProps } from '../../../types';
3
3
  import { FolderIcon } from '@elementor/icons';
4
4
  import { __useActiveDocumentActions as useActiveDocumentActions } from '@elementor/editor-documents';
5
5
 
@@ -1,4 +1,4 @@
1
- import { __privateInjectIntoPrimaryAction as injectIntoPrimaryAction } from '@elementor/editor-app-bar-ui';
1
+ import { injectIntoPrimaryAction } from '../../locations';
2
2
  import useDocumentSaveDraftProps from './hooks/use-document-save-draft-props';
3
3
  import useDocumentSaveTemplateProps from './hooks/use-document-save-template-props';
4
4
  import useDocumentViewPageProps from './hooks/use-document-view-page-props';
@@ -1,3 +1,3 @@
1
- import { __privateCreateMenu as createMenu } from '@elementor/editor-app-bar-ui';
1
+ import { createMenu } from '../../locations';
2
2
 
3
3
  export const documentOptionsMenu = createMenu( [ 'save' ] );
@@ -1,5 +1,5 @@
1
1
  import syncPanelTitle from './sync/sync-panel-title';
2
- import { __privateToolsMenu as toolsMenu } from '@elementor/editor-app-bar-ui';
2
+ import { toolsMenu } from '../../locations';
3
3
  import useActionProps from './hooks/use-action-props';
4
4
 
5
5
  export function init() {
@@ -1,4 +1,4 @@
1
- import { __privateUtilitiesMenu as utilitiesMenu } from '@elementor/editor-app-bar-ui';
1
+ import { utilitiesMenu } from '../../locations';
2
2
  import useActionProps from './hooks/use-action-props';
3
3
 
4
4
  export function init() {
@@ -1,4 +1,4 @@
1
- import { __privateUtilitiesMenu as utilitiesMenu } from '@elementor/editor-app-bar-ui';
1
+ import { utilitiesMenu } from '../../locations';
2
2
  import { __ } from '@wordpress/i18n';
3
3
  import { HelpIcon } from '@elementor/icons';
4
4
  import { ExtendedWindow } from '../../types';
@@ -1,4 +1,4 @@
1
- import { __privateMainMenu as mainMenu } from '@elementor/editor-app-bar-ui';
1
+ import { mainMenu } from '../../locations';
2
2
  import useActionProps from './hooks/use-action-props';
3
3
 
4
4
  export function init() {
@@ -1,8 +1,7 @@
1
1
  import { __ } from '@wordpress/i18n';
2
- import { ActionProps } from '@elementor/editor-app-bar-ui';
3
2
  import { KeyboardIcon } from '@elementor/icons';
4
3
  import { __privateRunCommand as runCommand } from '@elementor/editor-v1-adapters';
5
- import { ExtendedWindow } from '../../../types';
4
+ import { ExtendedWindow, ActionProps } from '../../../types';
6
5
 
7
6
  export default function useActionProps(): ActionProps {
8
7
  return {
@@ -1,4 +1,4 @@
1
- import { __privateMainMenu as mainMenu } from '@elementor/editor-app-bar-ui';
1
+ import { mainMenu } from '../../locations';
2
2
  import useActionProps from './hooks/use-action-props';
3
3
 
4
4
  export function init() {
@@ -1,8 +1,7 @@
1
1
  import { __ } from '@wordpress/i18n';
2
2
  import { __privateRunCommand as runCommand, __privateUseRouteStatus as useRouteStatus } from '@elementor/editor-v1-adapters';
3
- import { ToggleActionProps } from '@elementor/editor-app-bar-ui';
4
3
  import { AdjustmentsHorizontalIcon } from '@elementor/icons';
5
- import { ExtendedWindow } from '../../../types';
4
+ import { ExtendedWindow, ToggleActionProps } from '../../../types';
6
5
 
7
6
  export default function useActionProps(): ToggleActionProps {
8
7
  const { isActive, isBlocked } = useRouteStatus( 'panel/global', {
@@ -1,6 +1,6 @@
1
1
  import { injectIntoTop } from '@elementor/editor';
2
2
  import PortalledPrimaryAction from './components/portalled-primary-action';
3
- import { __privateToolsMenu as toolsMenu } from '@elementor/editor-app-bar-ui';
3
+ import { toolsMenu } from '../../locations';
4
4
  import useActionProps from './hooks/use-action-props';
5
5
 
6
6
  export function init() {
@@ -1,8 +1,7 @@
1
1
  import { __ } from '@wordpress/i18n';
2
2
  import { __privateRunCommand as runCommand, __privateUseRouteStatus as useRouteStatus } from '@elementor/editor-v1-adapters';
3
3
  import { StructureIcon } from '@elementor/icons';
4
- import { ToggleActionProps } from '@elementor/editor-app-bar-ui';
5
- import { ExtendedWindow } from '../../../types';
4
+ import { ExtendedWindow, ToggleActionProps } from '../../../types';
6
5
 
7
6
  export default function useActionProps(): ToggleActionProps {
8
7
  const { isActive, isBlocked } = useRouteStatus( 'navigator' );
@@ -1,4 +1,4 @@
1
- import { __privateToolsMenu as toolsMenu } from '@elementor/editor-app-bar-ui';
1
+ import { toolsMenu } from '../../locations';
2
2
  import useActionProps from './hooks/use-action-props';
3
3
 
4
4
  export function init() {
@@ -1,8 +1,7 @@
1
1
  import { __ } from '@wordpress/i18n';
2
2
  import { ThemeBuilderIcon } from '@elementor/icons';
3
3
  import { __privateRunCommand as runCommand } from '@elementor/editor-v1-adapters';
4
- import { ActionProps } from '@elementor/editor-app-bar-ui';
5
- import { ExtendedWindow } from '../../../types';
4
+ import { ExtendedWindow, ActionProps } from '../../../types';
6
5
 
7
6
  export default function useActionProps(): ActionProps {
8
7
  return {
@@ -1,4 +1,4 @@
1
- import { __privateMainMenu as mainMenu } from '@elementor/editor-app-bar-ui';
1
+ import { mainMenu } from '../../locations';
2
2
  import useThemeBuilderActionProps from './hooks/use-action-props';
3
3
 
4
4
  export function init() {
@@ -1,8 +1,7 @@
1
1
  import { __ } from '@wordpress/i18n';
2
- import { ToggleActionProps } from '@elementor/editor-app-bar-ui';
3
2
  import { ToggleRightIcon } from '@elementor/icons';
4
3
  import { __privateOpenRoute as openRoute, __privateUseRouteStatus as useRouteStatus } from '@elementor/editor-v1-adapters';
5
- import { ExtendedWindow } from '../../../types';
4
+ import { ExtendedWindow, ToggleActionProps } from '../../../types';
6
5
 
7
6
  export default function useActionProps(): ToggleActionProps {
8
7
  const { isActive, isBlocked } = useRouteStatus( 'panel/editor-preferences' );
@@ -1,4 +1,4 @@
1
- import { __privateMainMenu as mainMenu } from '@elementor/editor-app-bar-ui';
1
+ import { mainMenu } from '../../locations';
2
2
  import useActionProps from './hooks/use-action-props';
3
3
 
4
4
  export function init() {
@@ -1,4 +1,4 @@
1
- import { __privateMainMenu as mainMenu } from '@elementor/editor-app-bar-ui';
1
+ import { mainMenu } from '../../locations';
2
2
  import { __ } from '@wordpress/i18n';
3
3
  import { WordpressIcon } from '@elementor/icons';
4
4
  import { __useActiveDocument as useActiveDocument } from '@elementor/editor-documents';
package/src/index.ts CHANGED
@@ -1,17 +1,21 @@
1
- // Re-exporting the menus & locations from `@elementor/editor-app-bar-ui`
2
- // to expose the API for other packages to use.
3
1
  export {
4
- __privateMainMenu as mainMenu,
5
- __privateToolsMenu as toolsMenu,
6
- __privateUtilitiesMenu as utilitiesMenu,
7
- __privateIntegrationsMenu as integrationsMenu,
8
- __privateInjectIntoPageIndication as injectIntoPageIndication,
9
- __privateInjectIntoResponsive as injectIntoResponsive,
10
- __privateInjectIntoPrimaryAction as injectIntoPrimaryAction,
11
- } from '@elementor/editor-app-bar-ui';
2
+ mainMenu,
3
+ toolsMenu,
4
+ utilitiesMenu,
5
+ integrationsMenu,
6
+ injectIntoPageIndication,
7
+ injectIntoResponsive,
8
+ injectIntoPrimaryAction,
9
+ } from './locations';
12
10
 
13
11
  export { documentOptionsMenu } from './extensions/documents-save/locations';
14
12
 
13
+ export type {
14
+ ActionProps,
15
+ LinkProps,
16
+ ToggleActionProps,
17
+ } from './types';
18
+
15
19
  import init from './init';
16
20
 
17
21
  init();
package/src/init.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { __privateAppBar as AppBar } from '@elementor/editor-app-bar-ui';
1
+ import AppBar from './components/app-bar';
2
2
  import { injectIntoTop } from '@elementor/editor';
3
3
  import redirectOldMenus from './sync/redirect-old-menus';
4
4
  import { init as initExtensions } from './extensions';
@@ -0,0 +1,212 @@
1
+ import * as React from 'react';
2
+ import { createMenu } from '../menus';
3
+ import { fireEvent, render, screen } from '@testing-library/react';
4
+ import { createMockMenuAction, createMockMenuLink, createMockMenuToggleAction } from 'test-utils';
5
+
6
+ describe( 'Menus API', () => {
7
+ it( 'should create a menu with default group when not provided', () => {
8
+ // Act.
9
+ const menu = createMenu();
10
+
11
+ menu.registerAction( createMockMenuAction() );
12
+
13
+ renderMenu( menu );
14
+
15
+ // Assert.
16
+ expect( screen.getByRole( 'button' ) ).toBeInTheDocument();
17
+ } );
18
+
19
+ it( 'should create a menu with groups and append a default group', () => {
20
+ // Act.
21
+ const menu = createMenu( [ 'testGroup' ] );
22
+
23
+ menu.registerAction( {
24
+ ...createMockMenuAction(),
25
+ id: 'test',
26
+ } );
27
+
28
+ menu.registerLink( {
29
+ ...createMockMenuLink(),
30
+ id: 'test1',
31
+ group: 'testGroup',
32
+ } );
33
+
34
+ renderMenu( menu );
35
+
36
+ // Assert.
37
+ expect( screen.getByRole( 'button' ) ).toBeInTheDocument();
38
+ expect( screen.getByRole( 'link' ) ).toBeInTheDocument();
39
+ } );
40
+
41
+ it( 'should register an action', () => {
42
+ // Arrange.
43
+ const onClick = jest.fn();
44
+
45
+ // Act.
46
+ const menu = createMenu();
47
+
48
+ menu.registerAction( createMockMenuAction( { onClick } ) );
49
+
50
+ renderMenu( menu );
51
+
52
+ // Assert.
53
+ const action = screen.getByRole( 'button' );
54
+
55
+ expect( action ).toBeInTheDocument();
56
+ expect( action ).toHaveAttribute( 'aria-label', 'Test' );
57
+
58
+ // Act.
59
+ fireEvent.click( action );
60
+
61
+ // Assert.
62
+ expect( onClick ).toHaveBeenCalled();
63
+ } );
64
+
65
+ it( 'should register a toggle action', () => {
66
+ // Act.
67
+ const menu = createMenu();
68
+
69
+ menu.registerToggleAction( createMockMenuToggleAction() );
70
+
71
+ renderMenu( menu );
72
+
73
+ // Assert.
74
+ const toggleAction = screen.getByRole( 'button' );
75
+
76
+ expect( toggleAction ).toHaveAttribute( 'aria-pressed', 'false' );
77
+ expect( toggleAction ).toHaveValue( 'test-value' );
78
+
79
+ // Act.
80
+ fireEvent.click( toggleAction );
81
+
82
+ // Assert.
83
+ expect( toggleAction ).toHaveAttribute( 'aria-pressed', 'true' );
84
+
85
+ // Act.
86
+ fireEvent.click( toggleAction );
87
+
88
+ // Assert.
89
+ expect( toggleAction ).toHaveAttribute( 'aria-pressed', 'false' );
90
+ expect( toggleAction ).toBeDisabled();
91
+ } );
92
+
93
+ it( 'should register a link', () => {
94
+ // Act.
95
+ const menu = createMenu();
96
+
97
+ menu.registerLink( createMockMenuLink() );
98
+
99
+ renderMenu( menu );
100
+
101
+ // Assert.
102
+ const link = screen.getByRole( 'link' );
103
+
104
+ expect( link ).toBeInTheDocument();
105
+ expect( link ).toHaveAttribute( 'href', 'https://elementor.com' );
106
+ expect( link ).toHaveAttribute( 'target', '_blank' );
107
+ expect( link ).toHaveAttribute( 'aria-label', 'Test' );
108
+ } );
109
+
110
+ it( 'should not register an action when passing a non-existing group', () => {
111
+ // Act.
112
+ const menu = createMenu();
113
+
114
+ menu.registerLink( {
115
+ ...createMockMenuLink(),
116
+ group: 'non-existing-group' as 'default', // Emulate a runtime error.
117
+ } );
118
+
119
+ renderMenu( menu );
120
+
121
+ // Assert.
122
+ expect( screen.queryByRole( 'link' ) ).not.toBeInTheDocument();
123
+ } );
124
+
125
+ it( 'should register an action tooltip', async () => {
126
+ // Arrange.
127
+ const menu = createMenu();
128
+
129
+ // Act.
130
+ menu.registerAction( createMockMenuAction() );
131
+
132
+ // Assert.
133
+ renderMenu( menu );
134
+
135
+ const button = screen.getByLabelText( 'Test' );
136
+
137
+ expect( screen.queryByRole( 'tooltip' ) ).not.toBeInTheDocument();
138
+
139
+ // Act.
140
+ fireEvent.mouseOver(
141
+ button,
142
+ { bubbles: true },
143
+ );
144
+
145
+ // Assert.
146
+ expect( await screen.findByRole( 'tooltip' ) ).toHaveTextContent( 'Test' );
147
+ } );
148
+
149
+ it( 'should register an action icon', () => {
150
+ // Arrange.
151
+ const menu = createMenu();
152
+
153
+ // Act.
154
+ menu.registerAction( createMockMenuAction() );
155
+
156
+ // Assert.
157
+ renderMenu( menu );
158
+
159
+ const icon = screen.queryByText( 'a' );
160
+
161
+ expect( icon ).toBeInTheDocument();
162
+ expect( icon ).toHaveTextContent( 'a' );
163
+ } );
164
+
165
+ it.each( [
166
+ {
167
+ type: 'action',
168
+ action: 'registerAction',
169
+ },
170
+ {
171
+ type: 'toggle action',
172
+ action: 'registerToggleAction',
173
+ },
174
+ {
175
+ type: 'link',
176
+ action: 'registerLink',
177
+ },
178
+ ] as const )( 'should register a hidden $type', ( { type, action } ) => {
179
+ // Arrange.
180
+ const menu = createMenu();
181
+
182
+ // Act.
183
+ menu[ action ]( {
184
+ id: 'hidden',
185
+ useProps: () => ( {
186
+ title: `hidden-${ type }`,
187
+ icon: () => <div />,
188
+ visible: false,
189
+ } ),
190
+ } );
191
+
192
+ // Assert.
193
+ renderMenu( menu );
194
+
195
+ expect( screen.queryByLabelText( `hidden-${ type }` ) ).not.toBeInTheDocument();
196
+ } );
197
+ } );
198
+
199
+ function renderMenu<TGroup extends string>( menu: ReturnType<typeof createMenu<TGroup>> ) {
200
+ const MenuComponent = () => {
201
+ const groupedItems = menu.useMenuItems();
202
+ const allItems = Object.values( groupedItems ).flat();
203
+
204
+ return (
205
+ <div>
206
+ { allItems.map( ( { MenuItem, id } ) => <MenuItem key={ id } /> ) }
207
+ </div>
208
+ );
209
+ };
210
+
211
+ return render( <MenuComponent /> );
212
+ }
@@ -0,0 +1,27 @@
1
+ import { createMenu } from './menus';
2
+ import { createLocation } from '@elementor/locations';
3
+
4
+ export { createMenu } from './menus';
5
+
6
+ export const {
7
+ inject: injectIntoPageIndication,
8
+ Slot: PageIndicationSlot,
9
+ } = createLocation();
10
+
11
+ export const {
12
+ inject: injectIntoResponsive,
13
+ Slot: ResponsiveSlot,
14
+ } = createLocation();
15
+
16
+ export const {
17
+ inject: injectIntoPrimaryAction,
18
+ Slot: PrimaryActionSlot,
19
+ } = createLocation();
20
+
21
+ export const mainMenu = createMenu( [ 'exits' ] );
22
+
23
+ export const toolsMenu = createMenu();
24
+
25
+ export const utilitiesMenu = createMenu();
26
+
27
+ export const integrationsMenu = createMenu();