@vuu-ui/vuu-context-menu 2.1.19-beta.1 → 2.1.19-beta.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.
- package/package.json +7 -8
- package/src/ContextMenu.css.js +30 -0
- package/src/ContextMenu.js +36 -0
- package/src/ContextMenuProvider.js +51 -0
- package/src/index.js +3 -0
- package/src/menu-utils.js +27 -0
- package/src/useContextMenu.js +58 -0
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.1.19-beta.
|
|
2
|
+
"version": "2.1.19-beta.2",
|
|
3
3
|
"author": "heswell",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"devDependencies": {
|
|
7
|
-
"@vuu-ui/vuu-data-types": "2.1.19-beta.
|
|
8
|
-
"@vuu-ui/vuu-protocol-types": "2.1.19-beta.
|
|
9
|
-
"@vuu-ui/vuu-table-types": "2.1.19-beta.
|
|
7
|
+
"@vuu-ui/vuu-data-types": "2.1.19-beta.2",
|
|
8
|
+
"@vuu-ui/vuu-protocol-types": "2.1.19-beta.2",
|
|
9
|
+
"@vuu-ui/vuu-table-types": "2.1.19-beta.2"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@vuu-ui/vuu-utils": "2.1.19-beta.
|
|
12
|
+
"@vuu-ui/vuu-utils": "2.1.19-beta.2",
|
|
13
13
|
"@salt-ds/core": "1.54.1",
|
|
14
14
|
"@salt-ds/styles": "0.2.1",
|
|
15
15
|
"@salt-ds/window": "0.1.1"
|
|
@@ -21,13 +21,12 @@
|
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
23
|
"README.md",
|
|
24
|
-
"
|
|
25
|
-
"cjs",
|
|
24
|
+
"src",
|
|
26
25
|
"/types"
|
|
27
26
|
],
|
|
28
27
|
"exports": {
|
|
29
28
|
".": {
|
|
30
|
-
"import": "./index.js",
|
|
29
|
+
"import": "./src/index.js",
|
|
31
30
|
"types": "./types/index.d.ts"
|
|
32
31
|
}
|
|
33
32
|
},
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const css = `
|
|
2
|
+
.vuuContextMenuPanel {
|
|
3
|
+
&:has([data-icon]) {
|
|
4
|
+
& .saltMenuItem {
|
|
5
|
+
padding-left: calc(var(--salt-spacing-400) + var(--salt-spacing-200));
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
& .saltMenuItem[data-icon]:after {
|
|
9
|
+
--vuu-icon-left: var(--salt-spacing-150);
|
|
10
|
+
--vuu-icon-top: var(--salt-spacing-150);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
& .saltMenuItem[aria-haspopup="menu"]:after {
|
|
14
|
+
content: "";
|
|
15
|
+
background-color: var(--vuu-icon-color, var(--saltIcon-color, var(--salt-content-secondary-foreground)));
|
|
16
|
+
right: var(--salt-spacing-100);
|
|
17
|
+
height: var(--vuu-icon-height, var(--vuu-icon-size, 12px));
|
|
18
|
+
mask: var(--vuu-svg-triangle-right) center center / 8px 8px;
|
|
19
|
+
top: var(--salt-spacing-200);
|
|
20
|
+
width: var(--vuu-icon-width, var(--vuu-icon-size, 12px));
|
|
21
|
+
position: absolute;
|
|
22
|
+
transform: rotate(315deg);
|
|
23
|
+
mask-repeat: no-repeat;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
`;
|
|
30
|
+
export default css;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Menu, MenuPanel } from "@salt-ds/core";
|
|
3
|
+
import { useComponentCssInjection } from "@salt-ds/styles";
|
|
4
|
+
import { useWindow } from "@salt-ds/window";
|
|
5
|
+
import { menuItemsFromMenuDescriptors } from "./menu-utils.js";
|
|
6
|
+
import ContextMenu from "./ContextMenu.css";
|
|
7
|
+
const ContextMenu_ContextMenu = ({ menuHandler, menuItemDescriptors, onOpenChange, open, x, y })=>{
|
|
8
|
+
const targetWindow = useWindow();
|
|
9
|
+
useComponentCssInjection({
|
|
10
|
+
testId: "vuu-context-menu",
|
|
11
|
+
css: ContextMenu,
|
|
12
|
+
window: targetWindow
|
|
13
|
+
});
|
|
14
|
+
const virtualElement = {
|
|
15
|
+
getBoundingClientRect: ()=>({
|
|
16
|
+
width: 0,
|
|
17
|
+
height: 0,
|
|
18
|
+
x,
|
|
19
|
+
y,
|
|
20
|
+
top: y,
|
|
21
|
+
right: x,
|
|
22
|
+
bottom: y,
|
|
23
|
+
left: x
|
|
24
|
+
})
|
|
25
|
+
};
|
|
26
|
+
return /*#__PURE__*/ jsx(Menu, {
|
|
27
|
+
getVirtualElement: ()=>virtualElement,
|
|
28
|
+
onOpenChange: onOpenChange,
|
|
29
|
+
open: open,
|
|
30
|
+
children: /*#__PURE__*/ jsx(MenuPanel, {
|
|
31
|
+
className: "vuuContextMenuPanel",
|
|
32
|
+
children: menuItemsFromMenuDescriptors(menuItemDescriptors, menuHandler)
|
|
33
|
+
})
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
export { ContextMenu_ContextMenu as ContextMenu };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useCallback, useMemo, useState } from "react";
|
|
3
|
+
const ContextMenuContext = /*#__PURE__*/ createContext(null);
|
|
4
|
+
const Provider = ({ children, context, menuActionHandler, menuBuilder })=>{
|
|
5
|
+
const [contextMenu, setContextMenu] = useState(null);
|
|
6
|
+
const showContextMenu = useMemo(()=>{
|
|
7
|
+
if (context?.showContextMenu) return context.showContextMenu;
|
|
8
|
+
return (contextMenu)=>{
|
|
9
|
+
setContextMenu(contextMenu);
|
|
10
|
+
};
|
|
11
|
+
}, [
|
|
12
|
+
context
|
|
13
|
+
]);
|
|
14
|
+
const menuBuilders = useMemo(()=>{
|
|
15
|
+
if (context?.menuBuilders && menuBuilder) return context.menuBuilders.concat(menuBuilder);
|
|
16
|
+
if (menuBuilder) return [
|
|
17
|
+
menuBuilder
|
|
18
|
+
];
|
|
19
|
+
return context?.menuBuilders || [];
|
|
20
|
+
}, [
|
|
21
|
+
context,
|
|
22
|
+
menuBuilder
|
|
23
|
+
]);
|
|
24
|
+
const handleMenuAction = useCallback((menuItemId, options)=>{
|
|
25
|
+
if (menuActionHandler?.(menuItemId, options)) return true;
|
|
26
|
+
if (context?.menuActionHandler?.(menuItemId, options)) return true;
|
|
27
|
+
}, [
|
|
28
|
+
context,
|
|
29
|
+
menuActionHandler
|
|
30
|
+
]);
|
|
31
|
+
return /*#__PURE__*/ jsxs(ContextMenuContext.Provider, {
|
|
32
|
+
value: {
|
|
33
|
+
menuActionHandler: handleMenuAction,
|
|
34
|
+
menuBuilders,
|
|
35
|
+
showContextMenu
|
|
36
|
+
},
|
|
37
|
+
children: [
|
|
38
|
+
children,
|
|
39
|
+
contextMenu
|
|
40
|
+
]
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
const ContextMenuProvider = ({ children, menuActionHandler, menuBuilder })=>/*#__PURE__*/ jsx(ContextMenuContext.Consumer, {
|
|
44
|
+
children: (parentContext)=>/*#__PURE__*/ jsx(Provider, {
|
|
45
|
+
context: parentContext,
|
|
46
|
+
menuActionHandler: menuActionHandler,
|
|
47
|
+
menuBuilder: menuBuilder,
|
|
48
|
+
children: children
|
|
49
|
+
})
|
|
50
|
+
});
|
|
51
|
+
export { ContextMenuContext, ContextMenuProvider };
|
package/src/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Menu, MenuItem, MenuPanel, MenuTrigger } from "@salt-ds/core";
|
|
3
|
+
const isGroupMenuItemDescriptor = (menuItem)=>void 0 !== menuItem && "children" in menuItem;
|
|
4
|
+
const isOpenBulkEditResponse = (rpcResponse)=>"beginEditSession" === rpcResponse.rpcName;
|
|
5
|
+
const hasShowNotificationAction = (res)=>res.action?.type === "SHOW_NOTIFICATION_ACTION";
|
|
6
|
+
const menuItemsFromMenuDescriptors = (menuDescriptors, menuActionHandler)=>{
|
|
7
|
+
const fromDescriptor = (menuItem, index)=>isGroupMenuItemDescriptor(menuItem) ? /*#__PURE__*/ jsxs(Menu, {
|
|
8
|
+
children: [
|
|
9
|
+
/*#__PURE__*/ jsx(MenuTrigger, {
|
|
10
|
+
children: /*#__PURE__*/ jsx(MenuItem, {
|
|
11
|
+
children: menuItem.label
|
|
12
|
+
})
|
|
13
|
+
}),
|
|
14
|
+
/*#__PURE__*/ jsx(MenuPanel, {
|
|
15
|
+
className: "vuuContextMenuPanel",
|
|
16
|
+
children: menuItem.children.map(fromDescriptor)
|
|
17
|
+
})
|
|
18
|
+
]
|
|
19
|
+
}, index) : /*#__PURE__*/ jsx(MenuItem, {
|
|
20
|
+
className: menuItem.className,
|
|
21
|
+
"data-icon": menuItem.icon,
|
|
22
|
+
onClick: ()=>menuActionHandler(menuItem.id, menuItem.options),
|
|
23
|
+
children: menuItem.label
|
|
24
|
+
}, index);
|
|
25
|
+
return menuDescriptors.map(fromDescriptor);
|
|
26
|
+
};
|
|
27
|
+
export { hasShowNotificationAction, isGroupMenuItemDescriptor, isOpenBulkEditResponse, menuItemsFromMenuDescriptors };
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useContext } from "react";
|
|
3
|
+
import { ContextMenu } from "./ContextMenu.js";
|
|
4
|
+
import { ContextMenuContext } from "./ContextMenuProvider.js";
|
|
5
|
+
const useContextMenu = (menuBuilder, menuActionHandler)=>{
|
|
6
|
+
const ctx = useContext(ContextMenuContext);
|
|
7
|
+
const buildMenuOptions = useCallback((menuBuilders, location, options)=>{
|
|
8
|
+
let results = [];
|
|
9
|
+
for (const menuBuilder of menuBuilders)results = results.concat(menuBuilder(location, options));
|
|
10
|
+
return results;
|
|
11
|
+
}, []);
|
|
12
|
+
const handleOpenChange = useCallback((open)=>{
|
|
13
|
+
if (!open) ctx?.showContextMenu(null);
|
|
14
|
+
}, [
|
|
15
|
+
ctx
|
|
16
|
+
]);
|
|
17
|
+
const showContextMenu = useCallback((evt, location, options, { onOpenChange, x = evt.clientX, y = evt.clientY } = {
|
|
18
|
+
x: evt.clientX,
|
|
19
|
+
y: evt.clientY
|
|
20
|
+
})=>{
|
|
21
|
+
evt.stopPropagation?.();
|
|
22
|
+
evt.preventDefault?.();
|
|
23
|
+
const menuBuilders = [];
|
|
24
|
+
if (menuBuilder) menuBuilders.push(menuBuilder);
|
|
25
|
+
if (ctx && Array.isArray(ctx?.menuBuilders) && ctx.menuBuilders.length > 0) menuBuilders.push(...ctx.menuBuilders);
|
|
26
|
+
if (menuBuilders.length > 0) {
|
|
27
|
+
const menuItemDescriptors = buildMenuOptions(menuBuilders, location, options);
|
|
28
|
+
const menuHandler = (menuItemId, options)=>{
|
|
29
|
+
if (menuActionHandler?.(menuItemId, options) === true) return true;
|
|
30
|
+
return ctx?.menuActionHandler(menuItemId, options);
|
|
31
|
+
};
|
|
32
|
+
const localOpenChange = (isOpen)=>{
|
|
33
|
+
onOpenChange?.(isOpen);
|
|
34
|
+
handleOpenChange(isOpen);
|
|
35
|
+
};
|
|
36
|
+
if (menuItemDescriptors.length) {
|
|
37
|
+
ctx?.showContextMenu(/*#__PURE__*/ jsx(ContextMenu, {
|
|
38
|
+
menuHandler: menuHandler,
|
|
39
|
+
menuItemDescriptors: menuItemDescriptors,
|
|
40
|
+
onOpenChange: localOpenChange,
|
|
41
|
+
open: true,
|
|
42
|
+
x: x,
|
|
43
|
+
y: y
|
|
44
|
+
}));
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
} else console.warn("useContextMenu, no menuBuilders configured. These should be supplied via the ContextMenuProvider(s)");
|
|
48
|
+
return false;
|
|
49
|
+
}, [
|
|
50
|
+
buildMenuOptions,
|
|
51
|
+
ctx,
|
|
52
|
+
handleOpenChange,
|
|
53
|
+
menuActionHandler,
|
|
54
|
+
menuBuilder
|
|
55
|
+
]);
|
|
56
|
+
return showContextMenu;
|
|
57
|
+
};
|
|
58
|
+
export { useContextMenu };
|