@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 CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
- "version": "2.1.19-beta.1",
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.1",
8
- "@vuu-ui/vuu-protocol-types": "2.1.19-beta.1",
9
- "@vuu-ui/vuu-table-types": "2.1.19-beta.1"
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.1",
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
- "esm",
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,3 @@
1
+ export { ContextMenuProvider } from "./ContextMenuProvider.js";
2
+ export { hasShowNotificationAction, isGroupMenuItemDescriptor, isOpenBulkEditResponse } from "./menu-utils.js";
3
+ export { useContextMenu } from "./useContextMenu.js";
@@ -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 };