@elementor/menus 4.0.0-manual → 4.0.1
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/dist/index.js +38 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +39 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/create-menu.ts +23 -4
- package/src/create-register-item.tsx +4 -1
- package/src/create-use-menu-items.ts +28 -17
package/dist/index.js
CHANGED
|
@@ -41,7 +41,7 @@ var import_utils = require("@elementor/utils");
|
|
|
41
41
|
|
|
42
42
|
// src/create-register-item.tsx
|
|
43
43
|
var React = __toESM(require("react"));
|
|
44
|
-
function createRegisterItem(locations, component) {
|
|
44
|
+
function createRegisterItem(locations, component, notify) {
|
|
45
45
|
return ({ id, group = "default", priority = 10, overwrite = false, props: _props, useProps: _useProps }) => {
|
|
46
46
|
if (!(group in locations)) {
|
|
47
47
|
return;
|
|
@@ -60,36 +60,55 @@ function createRegisterItem(locations, component) {
|
|
|
60
60
|
overwrite
|
|
61
61
|
}
|
|
62
62
|
});
|
|
63
|
+
notify();
|
|
63
64
|
};
|
|
64
65
|
}
|
|
65
66
|
|
|
66
67
|
// src/create-use-menu-items.ts
|
|
67
68
|
var import_react = require("react");
|
|
68
|
-
function createUseMenuItems(locations) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
69
|
+
function createUseMenuItems(locations, subscribe) {
|
|
70
|
+
let snapshot = null;
|
|
71
|
+
subscribe(() => {
|
|
72
|
+
snapshot = null;
|
|
73
|
+
});
|
|
74
|
+
const getMenuItems = () => {
|
|
75
|
+
if (snapshot) {
|
|
76
|
+
return snapshot;
|
|
77
|
+
}
|
|
78
|
+
snapshot = Object.entries(locations).reduce((carry, [groupName, location]) => {
|
|
79
|
+
const items = location.getInjections().map((injection) => ({
|
|
80
|
+
id: injection.id,
|
|
81
|
+
MenuItem: injection.component
|
|
82
|
+
}));
|
|
83
|
+
return {
|
|
84
|
+
...carry,
|
|
85
|
+
[groupName]: items
|
|
86
|
+
};
|
|
87
|
+
}, {});
|
|
88
|
+
return snapshot;
|
|
82
89
|
};
|
|
90
|
+
return () => (0, import_react.useSyncExternalStore)(subscribe, getMenuItems);
|
|
83
91
|
}
|
|
84
92
|
|
|
85
93
|
// src/create-menu.ts
|
|
94
|
+
function createSubscription() {
|
|
95
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
96
|
+
return {
|
|
97
|
+
subscribe: (listener) => {
|
|
98
|
+
listeners.add(listener);
|
|
99
|
+
return () => listeners.delete(listener);
|
|
100
|
+
},
|
|
101
|
+
notify: () => listeners.forEach((listener) => listener())
|
|
102
|
+
};
|
|
103
|
+
}
|
|
86
104
|
function createMenu({
|
|
87
105
|
groups = [],
|
|
88
106
|
components
|
|
89
107
|
}) {
|
|
90
108
|
const locations = createLocations([...groups, "default"]);
|
|
91
|
-
const
|
|
92
|
-
const
|
|
109
|
+
const { subscribe, notify } = createSubscription();
|
|
110
|
+
const registerFns = createRegisterFns(locations, components, notify);
|
|
111
|
+
const useMenuItems = createUseMenuItems(locations, subscribe);
|
|
93
112
|
return {
|
|
94
113
|
useMenuItems,
|
|
95
114
|
...registerFns
|
|
@@ -101,13 +120,13 @@ function createLocations(groups) {
|
|
|
101
120
|
return acc;
|
|
102
121
|
}, {});
|
|
103
122
|
}
|
|
104
|
-
function createRegisterFns(locations, components) {
|
|
123
|
+
function createRegisterFns(locations, components, notify) {
|
|
105
124
|
return Object.entries(components).reduce(
|
|
106
125
|
(acc, [key, component]) => {
|
|
107
126
|
const name = `register${(0, import_utils.capitalize)(key)}`;
|
|
108
127
|
return {
|
|
109
128
|
...acc,
|
|
110
|
-
[name]: createRegisterItem(locations, component)
|
|
129
|
+
[name]: createRegisterItem(locations, component, notify)
|
|
111
130
|
};
|
|
112
131
|
},
|
|
113
132
|
{}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/create-menu.ts","../src/create-register-item.tsx","../src/create-use-menu-items.ts","../src/controls-actions.ts","../src/action.tsx"],"sourcesContent":["export { createMenu, type Menu } from './create-menu';\nexport { type Components } from './types';\nexport { controlActionsMenu } from './controls-actions';\n","import { createLocation } from '@elementor/locations';\nimport { capitalize } from '@elementor/utils';\n\nimport { createRegisterItem, type RegisterItem } from './create-register-item';\nimport { createUseMenuItems, type UseMenuItems } from './create-use-menu-items';\nimport { type Components, type LocationsMap, type MenuGroups } from './types';\n\nexport type Menu< TComponents extends Components, TGroups extends string > = {\n\tuseMenuItems: UseMenuItems< TGroups >;\n} & RegisterFns< TGroups, TComponents >;\n\nexport function createMenu< TComponents extends Components, TGroups extends string = 'default' >( {\n\tgroups = [],\n\tcomponents,\n}: {\n\tgroups?: TGroups[];\n\tcomponents: TComponents;\n} ): Menu< TComponents, TGroups > {\n\tconst locations = createLocations< MenuGroups< TGroups > >( [ ...groups, 'default' ] );\n\n\tconst registerFns = createRegisterFns( locations, components );\n\tconst useMenuItems = createUseMenuItems( locations );\n\n\treturn {\n\t\tuseMenuItems,\n\t\t...registerFns,\n\t};\n}\n\nfunction createLocations< TGroups extends string >( groups: TGroups[] ) {\n\treturn groups.reduce( ( acc, group ) => {\n\t\tacc[ group ] = createLocation();\n\n\t\treturn acc;\n\t}, {} as LocationsMap< TGroups > );\n}\n\ntype RegisterFns< TGroups extends string, TComponents extends Components > = {\n\t[ K in keyof TComponents as `register${ Capitalize< K & string > }` ]: RegisterItem< TGroups, TComponents[ K ] >;\n};\n\nfunction createRegisterFns< TGroups extends string, TComponents extends Components >(\n\tlocations: LocationsMap< MenuGroups< TGroups > >,\n\tcomponents: TComponents\n) {\n\treturn Object.entries( components ).reduce(\n\t\t( acc, [ key, component ] ) => {\n\t\t\tconst name = `register${ capitalize( key ) }`;\n\n\t\t\treturn {\n\t\t\t\t...acc,\n\t\t\t\t[ name ]: createRegisterItem( locations, component ),\n\t\t\t};\n\t\t},\n\t\t{} as RegisterFns< TGroups, TComponents >\n\t);\n}\n","import * as React from 'react';\nimport { type ComponentPropsWithoutRef, type ComponentType } from 'react';\n\nimport { type LocationsMap, type MenuGroups } from './types';\n\nexport type RegisterItem< TGroups extends string, TComponent extends ComponentType > = (\n\targs: {\n\t\tid: string;\n\t\tgroup?: MenuGroups< TGroups >;\n\t\tpriority?: number;\n\t\toverwrite?: boolean;\n\t} & Props< ComponentPropsWithoutRef< TComponent > >\n) => void;\n\ntype Props< TProps extends object > = unknown extends TProps ? NoProps : PropsOrUseProps< TProps >;\n\ntype NoProps = { props?: never; useProps?: never };\n\ntype PropsOrUseProps< TProps extends object > =\n\t| { props: TProps; useProps?: never }\n\t| {\n\t\t\tuseProps: () => TProps;\n\t\t\tprops?: never;\n\t };\n\nexport function createRegisterItem< TGroups extends string, TComponent extends ComponentType >(\n\tlocations: LocationsMap< MenuGroups< TGroups > >,\n\tcomponent: TComponent\n): RegisterItem< TGroups, TComponent > {\n\treturn ( { id, group = 'default', priority = 10, overwrite = false, props: _props, useProps: _useProps } ) => {\n\t\tif ( ! ( group in locations ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst Component = component as ComponentType;\n\t\tconst useProps = _useProps || ( () => _props );\n\n\t\tconst InjectedComponent = ( props: object ) => {\n\t\t\tconst componentProps = useProps();\n\n\t\t\treturn <Component { ...props } { ...componentProps } />;\n\t\t};\n\n\t\tlocations[ group ].inject( {\n\t\t\tid,\n\t\t\tcomponent: InjectedComponent,\n\t\t\toptions: {\n\t\t\t\tpriority,\n\t\t\t\toverwrite,\n\t\t\t},\n\t\t} );\n\t};\n}\n","import { type ComponentType,
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/create-menu.ts","../src/create-register-item.tsx","../src/create-use-menu-items.ts","../src/controls-actions.ts","../src/action.tsx"],"sourcesContent":["export { createMenu, type Menu } from './create-menu';\nexport { type Components } from './types';\nexport { controlActionsMenu } from './controls-actions';\n","import { createLocation } from '@elementor/locations';\nimport { capitalize } from '@elementor/utils';\n\nimport { createRegisterItem, type RegisterItem } from './create-register-item';\nimport { createUseMenuItems, type UseMenuItems } from './create-use-menu-items';\nimport { type Components, type LocationsMap, type MenuGroups } from './types';\n\nexport type Menu< TComponents extends Components, TGroups extends string > = {\n\tuseMenuItems: UseMenuItems< TGroups >;\n} & RegisterFns< TGroups, TComponents >;\n\ntype Subscription = {\n\tsubscribe: ( listener: () => void ) => () => void;\n\tnotify: () => void;\n};\n\nfunction createSubscription(): Subscription {\n\tconst listeners = new Set< () => void >();\n\n\treturn {\n\t\tsubscribe: ( listener ) => {\n\t\t\tlisteners.add( listener );\n\t\t\treturn () => listeners.delete( listener );\n\t\t},\n\t\tnotify: () => listeners.forEach( ( listener ) => listener() ),\n\t};\n}\n\nexport function createMenu< TComponents extends Components, TGroups extends string = 'default' >( {\n\tgroups = [],\n\tcomponents,\n}: {\n\tgroups?: TGroups[];\n\tcomponents: TComponents;\n} ): Menu< TComponents, TGroups > {\n\tconst locations = createLocations< MenuGroups< TGroups > >( [ ...groups, 'default' ] );\n\tconst { subscribe, notify } = createSubscription();\n\n\tconst registerFns = createRegisterFns( locations, components, notify );\n\tconst useMenuItems = createUseMenuItems( locations, subscribe );\n\n\treturn {\n\t\tuseMenuItems,\n\t\t...registerFns,\n\t};\n}\n\nfunction createLocations< TGroups extends string >( groups: TGroups[] ) {\n\treturn groups.reduce( ( acc, group ) => {\n\t\tacc[ group ] = createLocation();\n\n\t\treturn acc;\n\t}, {} as LocationsMap< TGroups > );\n}\n\ntype RegisterFns< TGroups extends string, TComponents extends Components > = {\n\t[ K in keyof TComponents as `register${ Capitalize< K & string > }` ]: RegisterItem< TGroups, TComponents[ K ] >;\n};\n\nfunction createRegisterFns< TGroups extends string, TComponents extends Components >(\n\tlocations: LocationsMap< MenuGroups< TGroups > >,\n\tcomponents: TComponents,\n\tnotify: () => void\n) {\n\treturn Object.entries( components ).reduce(\n\t\t( acc, [ key, component ] ) => {\n\t\t\tconst name = `register${ capitalize( key ) }`;\n\n\t\t\treturn {\n\t\t\t\t...acc,\n\t\t\t\t[ name ]: createRegisterItem( locations, component, notify ),\n\t\t\t};\n\t\t},\n\t\t{} as RegisterFns< TGroups, TComponents >\n\t);\n}\n","import * as React from 'react';\nimport { type ComponentPropsWithoutRef, type ComponentType } from 'react';\n\nimport { type LocationsMap, type MenuGroups } from './types';\n\nexport type RegisterItem< TGroups extends string, TComponent extends ComponentType > = (\n\targs: {\n\t\tid: string;\n\t\tgroup?: MenuGroups< TGroups >;\n\t\tpriority?: number;\n\t\toverwrite?: boolean;\n\t} & Props< ComponentPropsWithoutRef< TComponent > >\n) => void;\n\ntype Props< TProps extends object > = unknown extends TProps ? NoProps : PropsOrUseProps< TProps >;\n\ntype NoProps = { props?: never; useProps?: never };\n\ntype PropsOrUseProps< TProps extends object > =\n\t| { props: TProps; useProps?: never }\n\t| {\n\t\t\tuseProps: () => TProps;\n\t\t\tprops?: never;\n\t };\n\nexport function createRegisterItem< TGroups extends string, TComponent extends ComponentType >(\n\tlocations: LocationsMap< MenuGroups< TGroups > >,\n\tcomponent: TComponent,\n\tnotify: () => void\n): RegisterItem< TGroups, TComponent > {\n\treturn ( { id, group = 'default', priority = 10, overwrite = false, props: _props, useProps: _useProps } ) => {\n\t\tif ( ! ( group in locations ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst Component = component as ComponentType;\n\t\tconst useProps = _useProps || ( () => _props );\n\n\t\tconst InjectedComponent = ( props: object ) => {\n\t\t\tconst componentProps = useProps();\n\n\t\t\treturn <Component { ...props } { ...componentProps } />;\n\t\t};\n\n\t\tlocations[ group ].inject( {\n\t\t\tid,\n\t\t\tcomponent: InjectedComponent,\n\t\t\toptions: {\n\t\t\t\tpriority,\n\t\t\t\toverwrite,\n\t\t\t},\n\t\t} );\n\n\t\tnotify();\n\t};\n}\n","import { type ComponentType, useSyncExternalStore } from 'react';\n\nimport { type LocationsMap, type MenuGroups } from './types';\n\nexport type UseMenuItems< TGroups extends string > = () => GroupedMenuItems< TGroups >;\n\ntype GroupedMenuItems< TGroups extends string > = Record<\n\tMenuGroups< TGroups >,\n\tArray< {\n\t\tid: string;\n\t\tMenuItem: ComponentType;\n\t} >\n>;\n\nexport function createUseMenuItems< TGroups extends string >(\n\tlocations: LocationsMap< MenuGroups< TGroups > >,\n\tsubscribe: ( listener: () => void ) => () => void\n): UseMenuItems< TGroups > {\n\tlet snapshot: GroupedMenuItems< TGroups > | null = null;\n\n\tsubscribe( () => {\n\t\tsnapshot = null;\n\t} );\n\n\tconst getMenuItems = () => {\n\t\tif ( snapshot ) {\n\t\t\treturn snapshot;\n\t\t}\n\t\tsnapshot = Object.entries( locations ).reduce( ( carry, [ groupName, location ] ) => {\n\t\t\tconst items = location.getInjections().map( ( injection ) => ( {\n\t\t\t\tid: injection.id,\n\t\t\t\tMenuItem: injection.component,\n\t\t\t} ) );\n\n\t\t\treturn {\n\t\t\t\t...carry,\n\t\t\t\t[ groupName ]: items,\n\t\t\t};\n\t\t}, {} as GroupedMenuItems< TGroups > );\n\n\t\treturn snapshot;\n\t};\n\n\treturn () => useSyncExternalStore( subscribe, getMenuItems );\n}\n","import { PopoverAction } from '@elementor/editor-ui';\n\nimport Action from './action';\nimport { createMenu } from './create-menu';\n\nexport const controlActionsMenu = createMenu( {\n\tcomponents: {\n\t\tAction,\n\t\tPopoverAction,\n\t},\n} );\n","import * as React from 'react';\nimport { type ElementType as ReactElementType } from 'react';\nimport { IconButton, Tooltip } from '@elementor/ui';\n\nconst SIZE = 'tiny';\n\ntype ActionProps = {\n\ttitle: string;\n\tvisible?: boolean;\n\ticon: ReactElementType;\n\tonClick: () => void;\n};\n\nexport default function Action( { title, visible = true, icon: Icon, onClick }: ActionProps ) {\n\tif ( ! visible ) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<Tooltip placement=\"top\" title={ title } arrow={ true }>\n\t\t\t<IconButton aria-label={ title } size={ SIZE } onClick={ onClick }>\n\t\t\t\t<Icon fontSize={ SIZE } />\n\t\t\t</IconButton>\n\t\t</Tooltip>\n\t);\n}\n"],"mappings":"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","names":["React"]}
|
package/dist/index.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { capitalize } from "@elementor/utils";
|
|
|
4
4
|
|
|
5
5
|
// src/create-register-item.tsx
|
|
6
6
|
import * as React from "react";
|
|
7
|
-
function createRegisterItem(locations, component) {
|
|
7
|
+
function createRegisterItem(locations, component, notify) {
|
|
8
8
|
return ({ id, group = "default", priority = 10, overwrite = false, props: _props, useProps: _useProps }) => {
|
|
9
9
|
if (!(group in locations)) {
|
|
10
10
|
return;
|
|
@@ -23,36 +23,55 @@ function createRegisterItem(locations, component) {
|
|
|
23
23
|
overwrite
|
|
24
24
|
}
|
|
25
25
|
});
|
|
26
|
+
notify();
|
|
26
27
|
};
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
// src/create-use-menu-items.ts
|
|
30
|
-
import {
|
|
31
|
-
function createUseMenuItems(locations) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
31
|
+
import { useSyncExternalStore } from "react";
|
|
32
|
+
function createUseMenuItems(locations, subscribe) {
|
|
33
|
+
let snapshot = null;
|
|
34
|
+
subscribe(() => {
|
|
35
|
+
snapshot = null;
|
|
36
|
+
});
|
|
37
|
+
const getMenuItems = () => {
|
|
38
|
+
if (snapshot) {
|
|
39
|
+
return snapshot;
|
|
40
|
+
}
|
|
41
|
+
snapshot = Object.entries(locations).reduce((carry, [groupName, location]) => {
|
|
42
|
+
const items = location.getInjections().map((injection) => ({
|
|
43
|
+
id: injection.id,
|
|
44
|
+
MenuItem: injection.component
|
|
45
|
+
}));
|
|
46
|
+
return {
|
|
47
|
+
...carry,
|
|
48
|
+
[groupName]: items
|
|
49
|
+
};
|
|
50
|
+
}, {});
|
|
51
|
+
return snapshot;
|
|
45
52
|
};
|
|
53
|
+
return () => useSyncExternalStore(subscribe, getMenuItems);
|
|
46
54
|
}
|
|
47
55
|
|
|
48
56
|
// src/create-menu.ts
|
|
57
|
+
function createSubscription() {
|
|
58
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
59
|
+
return {
|
|
60
|
+
subscribe: (listener) => {
|
|
61
|
+
listeners.add(listener);
|
|
62
|
+
return () => listeners.delete(listener);
|
|
63
|
+
},
|
|
64
|
+
notify: () => listeners.forEach((listener) => listener())
|
|
65
|
+
};
|
|
66
|
+
}
|
|
49
67
|
function createMenu({
|
|
50
68
|
groups = [],
|
|
51
69
|
components
|
|
52
70
|
}) {
|
|
53
71
|
const locations = createLocations([...groups, "default"]);
|
|
54
|
-
const
|
|
55
|
-
const
|
|
72
|
+
const { subscribe, notify } = createSubscription();
|
|
73
|
+
const registerFns = createRegisterFns(locations, components, notify);
|
|
74
|
+
const useMenuItems = createUseMenuItems(locations, subscribe);
|
|
56
75
|
return {
|
|
57
76
|
useMenuItems,
|
|
58
77
|
...registerFns
|
|
@@ -64,13 +83,13 @@ function createLocations(groups) {
|
|
|
64
83
|
return acc;
|
|
65
84
|
}, {});
|
|
66
85
|
}
|
|
67
|
-
function createRegisterFns(locations, components) {
|
|
86
|
+
function createRegisterFns(locations, components, notify) {
|
|
68
87
|
return Object.entries(components).reduce(
|
|
69
88
|
(acc, [key, component]) => {
|
|
70
89
|
const name = `register${capitalize(key)}`;
|
|
71
90
|
return {
|
|
72
91
|
...acc,
|
|
73
|
-
[name]: createRegisterItem(locations, component)
|
|
92
|
+
[name]: createRegisterItem(locations, component, notify)
|
|
74
93
|
};
|
|
75
94
|
},
|
|
76
95
|
{}
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/create-menu.ts","../src/create-register-item.tsx","../src/create-use-menu-items.ts","../src/controls-actions.ts","../src/action.tsx"],"sourcesContent":["import { createLocation } from '@elementor/locations';\nimport { capitalize } from '@elementor/utils';\n\nimport { createRegisterItem, type RegisterItem } from './create-register-item';\nimport { createUseMenuItems, type UseMenuItems } from './create-use-menu-items';\nimport { type Components, type LocationsMap, type MenuGroups } from './types';\n\nexport type Menu< TComponents extends Components, TGroups extends string > = {\n\tuseMenuItems: UseMenuItems< TGroups >;\n} & RegisterFns< TGroups, TComponents >;\n\nexport function createMenu< TComponents extends Components, TGroups extends string = 'default' >( {\n\tgroups = [],\n\tcomponents,\n}: {\n\tgroups?: TGroups[];\n\tcomponents: TComponents;\n} ): Menu< TComponents, TGroups > {\n\tconst locations = createLocations< MenuGroups< TGroups > >( [ ...groups, 'default' ] );\n\n\tconst registerFns = createRegisterFns( locations, components );\n\tconst useMenuItems = createUseMenuItems( locations );\n\n\treturn {\n\t\tuseMenuItems,\n\t\t...registerFns,\n\t};\n}\n\nfunction createLocations< TGroups extends string >( groups: TGroups[] ) {\n\treturn groups.reduce( ( acc, group ) => {\n\t\tacc[ group ] = createLocation();\n\n\t\treturn acc;\n\t}, {} as LocationsMap< TGroups > );\n}\n\ntype RegisterFns< TGroups extends string, TComponents extends Components > = {\n\t[ K in keyof TComponents as `register${ Capitalize< K & string > }` ]: RegisterItem< TGroups, TComponents[ K ] >;\n};\n\nfunction createRegisterFns< TGroups extends string, TComponents extends Components >(\n\tlocations: LocationsMap< MenuGroups< TGroups > >,\n\tcomponents: TComponents\n) {\n\treturn Object.entries( components ).reduce(\n\t\t( acc, [ key, component ] ) => {\n\t\t\tconst name = `register${ capitalize( key ) }`;\n\n\t\t\treturn {\n\t\t\t\t...acc,\n\t\t\t\t[ name ]: createRegisterItem( locations, component ),\n\t\t\t};\n\t\t},\n\t\t{} as RegisterFns< TGroups, TComponents >\n\t);\n}\n","import * as React from 'react';\nimport { type ComponentPropsWithoutRef, type ComponentType } from 'react';\n\nimport { type LocationsMap, type MenuGroups } from './types';\n\nexport type RegisterItem< TGroups extends string, TComponent extends ComponentType > = (\n\targs: {\n\t\tid: string;\n\t\tgroup?: MenuGroups< TGroups >;\n\t\tpriority?: number;\n\t\toverwrite?: boolean;\n\t} & Props< ComponentPropsWithoutRef< TComponent > >\n) => void;\n\ntype Props< TProps extends object > = unknown extends TProps ? NoProps : PropsOrUseProps< TProps >;\n\ntype NoProps = { props?: never; useProps?: never };\n\ntype PropsOrUseProps< TProps extends object > =\n\t| { props: TProps; useProps?: never }\n\t| {\n\t\t\tuseProps: () => TProps;\n\t\t\tprops?: never;\n\t };\n\nexport function createRegisterItem< TGroups extends string, TComponent extends ComponentType >(\n\tlocations: LocationsMap< MenuGroups< TGroups > >,\n\tcomponent: TComponent\n): RegisterItem< TGroups, TComponent > {\n\treturn ( { id, group = 'default', priority = 10, overwrite = false, props: _props, useProps: _useProps } ) => {\n\t\tif ( ! ( group in locations ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst Component = component as ComponentType;\n\t\tconst useProps = _useProps || ( () => _props );\n\n\t\tconst InjectedComponent = ( props: object ) => {\n\t\t\tconst componentProps = useProps();\n\n\t\t\treturn <Component { ...props } { ...componentProps } />;\n\t\t};\n\n\t\tlocations[ group ].inject( {\n\t\t\tid,\n\t\t\tcomponent: InjectedComponent,\n\t\t\toptions: {\n\t\t\t\tpriority,\n\t\t\t\toverwrite,\n\t\t\t},\n\t\t} );\n\t};\n}\n","import { type ComponentType,
|
|
1
|
+
{"version":3,"sources":["../src/create-menu.ts","../src/create-register-item.tsx","../src/create-use-menu-items.ts","../src/controls-actions.ts","../src/action.tsx"],"sourcesContent":["import { createLocation } from '@elementor/locations';\nimport { capitalize } from '@elementor/utils';\n\nimport { createRegisterItem, type RegisterItem } from './create-register-item';\nimport { createUseMenuItems, type UseMenuItems } from './create-use-menu-items';\nimport { type Components, type LocationsMap, type MenuGroups } from './types';\n\nexport type Menu< TComponents extends Components, TGroups extends string > = {\n\tuseMenuItems: UseMenuItems< TGroups >;\n} & RegisterFns< TGroups, TComponents >;\n\ntype Subscription = {\n\tsubscribe: ( listener: () => void ) => () => void;\n\tnotify: () => void;\n};\n\nfunction createSubscription(): Subscription {\n\tconst listeners = new Set< () => void >();\n\n\treturn {\n\t\tsubscribe: ( listener ) => {\n\t\t\tlisteners.add( listener );\n\t\t\treturn () => listeners.delete( listener );\n\t\t},\n\t\tnotify: () => listeners.forEach( ( listener ) => listener() ),\n\t};\n}\n\nexport function createMenu< TComponents extends Components, TGroups extends string = 'default' >( {\n\tgroups = [],\n\tcomponents,\n}: {\n\tgroups?: TGroups[];\n\tcomponents: TComponents;\n} ): Menu< TComponents, TGroups > {\n\tconst locations = createLocations< MenuGroups< TGroups > >( [ ...groups, 'default' ] );\n\tconst { subscribe, notify } = createSubscription();\n\n\tconst registerFns = createRegisterFns( locations, components, notify );\n\tconst useMenuItems = createUseMenuItems( locations, subscribe );\n\n\treturn {\n\t\tuseMenuItems,\n\t\t...registerFns,\n\t};\n}\n\nfunction createLocations< TGroups extends string >( groups: TGroups[] ) {\n\treturn groups.reduce( ( acc, group ) => {\n\t\tacc[ group ] = createLocation();\n\n\t\treturn acc;\n\t}, {} as LocationsMap< TGroups > );\n}\n\ntype RegisterFns< TGroups extends string, TComponents extends Components > = {\n\t[ K in keyof TComponents as `register${ Capitalize< K & string > }` ]: RegisterItem< TGroups, TComponents[ K ] >;\n};\n\nfunction createRegisterFns< TGroups extends string, TComponents extends Components >(\n\tlocations: LocationsMap< MenuGroups< TGroups > >,\n\tcomponents: TComponents,\n\tnotify: () => void\n) {\n\treturn Object.entries( components ).reduce(\n\t\t( acc, [ key, component ] ) => {\n\t\t\tconst name = `register${ capitalize( key ) }`;\n\n\t\t\treturn {\n\t\t\t\t...acc,\n\t\t\t\t[ name ]: createRegisterItem( locations, component, notify ),\n\t\t\t};\n\t\t},\n\t\t{} as RegisterFns< TGroups, TComponents >\n\t);\n}\n","import * as React from 'react';\nimport { type ComponentPropsWithoutRef, type ComponentType } from 'react';\n\nimport { type LocationsMap, type MenuGroups } from './types';\n\nexport type RegisterItem< TGroups extends string, TComponent extends ComponentType > = (\n\targs: {\n\t\tid: string;\n\t\tgroup?: MenuGroups< TGroups >;\n\t\tpriority?: number;\n\t\toverwrite?: boolean;\n\t} & Props< ComponentPropsWithoutRef< TComponent > >\n) => void;\n\ntype Props< TProps extends object > = unknown extends TProps ? NoProps : PropsOrUseProps< TProps >;\n\ntype NoProps = { props?: never; useProps?: never };\n\ntype PropsOrUseProps< TProps extends object > =\n\t| { props: TProps; useProps?: never }\n\t| {\n\t\t\tuseProps: () => TProps;\n\t\t\tprops?: never;\n\t };\n\nexport function createRegisterItem< TGroups extends string, TComponent extends ComponentType >(\n\tlocations: LocationsMap< MenuGroups< TGroups > >,\n\tcomponent: TComponent,\n\tnotify: () => void\n): RegisterItem< TGroups, TComponent > {\n\treturn ( { id, group = 'default', priority = 10, overwrite = false, props: _props, useProps: _useProps } ) => {\n\t\tif ( ! ( group in locations ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst Component = component as ComponentType;\n\t\tconst useProps = _useProps || ( () => _props );\n\n\t\tconst InjectedComponent = ( props: object ) => {\n\t\t\tconst componentProps = useProps();\n\n\t\t\treturn <Component { ...props } { ...componentProps } />;\n\t\t};\n\n\t\tlocations[ group ].inject( {\n\t\t\tid,\n\t\t\tcomponent: InjectedComponent,\n\t\t\toptions: {\n\t\t\t\tpriority,\n\t\t\t\toverwrite,\n\t\t\t},\n\t\t} );\n\n\t\tnotify();\n\t};\n}\n","import { type ComponentType, useSyncExternalStore } from 'react';\n\nimport { type LocationsMap, type MenuGroups } from './types';\n\nexport type UseMenuItems< TGroups extends string > = () => GroupedMenuItems< TGroups >;\n\ntype GroupedMenuItems< TGroups extends string > = Record<\n\tMenuGroups< TGroups >,\n\tArray< {\n\t\tid: string;\n\t\tMenuItem: ComponentType;\n\t} >\n>;\n\nexport function createUseMenuItems< TGroups extends string >(\n\tlocations: LocationsMap< MenuGroups< TGroups > >,\n\tsubscribe: ( listener: () => void ) => () => void\n): UseMenuItems< TGroups > {\n\tlet snapshot: GroupedMenuItems< TGroups > | null = null;\n\n\tsubscribe( () => {\n\t\tsnapshot = null;\n\t} );\n\n\tconst getMenuItems = () => {\n\t\tif ( snapshot ) {\n\t\t\treturn snapshot;\n\t\t}\n\t\tsnapshot = Object.entries( locations ).reduce( ( carry, [ groupName, location ] ) => {\n\t\t\tconst items = location.getInjections().map( ( injection ) => ( {\n\t\t\t\tid: injection.id,\n\t\t\t\tMenuItem: injection.component,\n\t\t\t} ) );\n\n\t\t\treturn {\n\t\t\t\t...carry,\n\t\t\t\t[ groupName ]: items,\n\t\t\t};\n\t\t}, {} as GroupedMenuItems< TGroups > );\n\n\t\treturn snapshot;\n\t};\n\n\treturn () => useSyncExternalStore( subscribe, getMenuItems );\n}\n","import { PopoverAction } from '@elementor/editor-ui';\n\nimport Action from './action';\nimport { createMenu } from './create-menu';\n\nexport const controlActionsMenu = createMenu( {\n\tcomponents: {\n\t\tAction,\n\t\tPopoverAction,\n\t},\n} );\n","import * as React from 'react';\nimport { type ElementType as ReactElementType } from 'react';\nimport { IconButton, Tooltip } from '@elementor/ui';\n\nconst SIZE = 'tiny';\n\ntype ActionProps = {\n\ttitle: string;\n\tvisible?: boolean;\n\ticon: ReactElementType;\n\tonClick: () => void;\n};\n\nexport default function Action( { title, visible = true, icon: Icon, onClick }: ActionProps ) {\n\tif ( ! visible ) {\n\t\treturn null;\n\t}\n\n\treturn (\n\t\t<Tooltip placement=\"top\" title={ title } arrow={ true }>\n\t\t\t<IconButton aria-label={ title } size={ SIZE } onClick={ onClick }>\n\t\t\t\t<Icon fontSize={ SIZE } />\n\t\t\t</IconButton>\n\t\t</Tooltip>\n\t);\n}\n"],"mappings":"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","names":["React"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/menus",
|
|
3
3
|
"description": "Add a menus registration mechanism for you React application",
|
|
4
|
-
"version": "4.0.
|
|
4
|
+
"version": "4.0.1",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Elementor Team",
|
|
7
7
|
"homepage": "https://elementor.com/",
|
|
@@ -40,9 +40,9 @@
|
|
|
40
40
|
"dev": "tsup --config=../../tsup.dev.ts"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@elementor/locations": "4.0.
|
|
44
|
-
"@elementor/utils": "4.0.
|
|
45
|
-
"@elementor/editor-ui": "4.0.
|
|
43
|
+
"@elementor/locations": "4.0.1",
|
|
44
|
+
"@elementor/utils": "4.0.1",
|
|
45
|
+
"@elementor/editor-ui": "4.0.1",
|
|
46
46
|
"@elementor/ui": "1.36.17"
|
|
47
47
|
},
|
|
48
48
|
"peerDependencies": {
|
package/src/create-menu.ts
CHANGED
|
@@ -9,6 +9,23 @@ export type Menu< TComponents extends Components, TGroups extends string > = {
|
|
|
9
9
|
useMenuItems: UseMenuItems< TGroups >;
|
|
10
10
|
} & RegisterFns< TGroups, TComponents >;
|
|
11
11
|
|
|
12
|
+
type Subscription = {
|
|
13
|
+
subscribe: ( listener: () => void ) => () => void;
|
|
14
|
+
notify: () => void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function createSubscription(): Subscription {
|
|
18
|
+
const listeners = new Set< () => void >();
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
subscribe: ( listener ) => {
|
|
22
|
+
listeners.add( listener );
|
|
23
|
+
return () => listeners.delete( listener );
|
|
24
|
+
},
|
|
25
|
+
notify: () => listeners.forEach( ( listener ) => listener() ),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
12
29
|
export function createMenu< TComponents extends Components, TGroups extends string = 'default' >( {
|
|
13
30
|
groups = [],
|
|
14
31
|
components,
|
|
@@ -17,9 +34,10 @@ export function createMenu< TComponents extends Components, TGroups extends stri
|
|
|
17
34
|
components: TComponents;
|
|
18
35
|
} ): Menu< TComponents, TGroups > {
|
|
19
36
|
const locations = createLocations< MenuGroups< TGroups > >( [ ...groups, 'default' ] );
|
|
37
|
+
const { subscribe, notify } = createSubscription();
|
|
20
38
|
|
|
21
|
-
const registerFns = createRegisterFns( locations, components );
|
|
22
|
-
const useMenuItems = createUseMenuItems( locations );
|
|
39
|
+
const registerFns = createRegisterFns( locations, components, notify );
|
|
40
|
+
const useMenuItems = createUseMenuItems( locations, subscribe );
|
|
23
41
|
|
|
24
42
|
return {
|
|
25
43
|
useMenuItems,
|
|
@@ -41,7 +59,8 @@ type RegisterFns< TGroups extends string, TComponents extends Components > = {
|
|
|
41
59
|
|
|
42
60
|
function createRegisterFns< TGroups extends string, TComponents extends Components >(
|
|
43
61
|
locations: LocationsMap< MenuGroups< TGroups > >,
|
|
44
|
-
components: TComponents
|
|
62
|
+
components: TComponents,
|
|
63
|
+
notify: () => void
|
|
45
64
|
) {
|
|
46
65
|
return Object.entries( components ).reduce(
|
|
47
66
|
( acc, [ key, component ] ) => {
|
|
@@ -49,7 +68,7 @@ function createRegisterFns< TGroups extends string, TComponents extends Componen
|
|
|
49
68
|
|
|
50
69
|
return {
|
|
51
70
|
...acc,
|
|
52
|
-
[ name ]: createRegisterItem( locations, component ),
|
|
71
|
+
[ name ]: createRegisterItem( locations, component, notify ),
|
|
53
72
|
};
|
|
54
73
|
},
|
|
55
74
|
{} as RegisterFns< TGroups, TComponents >
|
|
@@ -25,7 +25,8 @@ type PropsOrUseProps< TProps extends object > =
|
|
|
25
25
|
|
|
26
26
|
export function createRegisterItem< TGroups extends string, TComponent extends ComponentType >(
|
|
27
27
|
locations: LocationsMap< MenuGroups< TGroups > >,
|
|
28
|
-
component: TComponent
|
|
28
|
+
component: TComponent,
|
|
29
|
+
notify: () => void
|
|
29
30
|
): RegisterItem< TGroups, TComponent > {
|
|
30
31
|
return ( { id, group = 'default', priority = 10, overwrite = false, props: _props, useProps: _useProps } ) => {
|
|
31
32
|
if ( ! ( group in locations ) ) {
|
|
@@ -49,5 +50,7 @@ export function createRegisterItem< TGroups extends string, TComponent extends C
|
|
|
49
50
|
overwrite,
|
|
50
51
|
},
|
|
51
52
|
} );
|
|
53
|
+
|
|
54
|
+
notify();
|
|
52
55
|
};
|
|
53
56
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ComponentType,
|
|
1
|
+
import { type ComponentType, useSyncExternalStore } from 'react';
|
|
2
2
|
|
|
3
3
|
import { type LocationsMap, type MenuGroups } from './types';
|
|
4
4
|
|
|
@@ -13,22 +13,33 @@ type GroupedMenuItems< TGroups extends string > = Record<
|
|
|
13
13
|
>;
|
|
14
14
|
|
|
15
15
|
export function createUseMenuItems< TGroups extends string >(
|
|
16
|
-
locations: LocationsMap< MenuGroups< TGroups >
|
|
16
|
+
locations: LocationsMap< MenuGroups< TGroups > >,
|
|
17
|
+
subscribe: ( listener: () => void ) => () => void
|
|
17
18
|
): UseMenuItems< TGroups > {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
19
|
+
let snapshot: GroupedMenuItems< TGroups > | null = null;
|
|
20
|
+
|
|
21
|
+
subscribe( () => {
|
|
22
|
+
snapshot = null;
|
|
23
|
+
} );
|
|
24
|
+
|
|
25
|
+
const getMenuItems = () => {
|
|
26
|
+
if ( snapshot ) {
|
|
27
|
+
return snapshot;
|
|
28
|
+
}
|
|
29
|
+
snapshot = Object.entries( locations ).reduce( ( carry, [ groupName, location ] ) => {
|
|
30
|
+
const items = location.getInjections().map( ( injection ) => ( {
|
|
31
|
+
id: injection.id,
|
|
32
|
+
MenuItem: injection.component,
|
|
33
|
+
} ) );
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
...carry,
|
|
37
|
+
[ groupName ]: items,
|
|
38
|
+
};
|
|
39
|
+
}, {} as GroupedMenuItems< TGroups > );
|
|
40
|
+
|
|
41
|
+
return snapshot;
|
|
33
42
|
};
|
|
43
|
+
|
|
44
|
+
return () => useSyncExternalStore( subscribe, getMenuItems );
|
|
34
45
|
}
|