@vuu-ui/vuu-context-menu 0.13.7 → 0.13.8
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/cjs/index.js +213 -6
- package/cjs/index.js.map +1 -1
- package/esm/index.js +214 -3
- package/esm/index.js.map +1 -1
- package/package.json +5 -5
- package/cjs/ContextMenu.css.js +0 -6
- package/cjs/ContextMenu.css.js.map +0 -1
- package/cjs/ContextMenu.js +0 -48
- package/cjs/ContextMenu.js.map +0 -1
- package/cjs/ContextMenuProvider.js +0 -78
- package/cjs/ContextMenuProvider.js.map +0 -1
- package/cjs/menu-utils.js +0 -26
- package/cjs/menu-utils.js.map +0 -1
- package/cjs/useContextMenu.js +0 -89
- package/cjs/useContextMenu.js.map +0 -1
- package/esm/ContextMenu.css.js +0 -4
- package/esm/ContextMenu.css.js.map +0 -1
- package/esm/ContextMenu.js +0 -46
- package/esm/ContextMenu.js.map +0 -1
- package/esm/ContextMenuProvider.js +0 -75
- package/esm/ContextMenuProvider.js.map +0 -1
- package/esm/menu-utils.js +0 -23
- package/esm/menu-utils.js.map +0 -1
- package/esm/useContextMenu.js +0 -87
- package/esm/useContextMenu.js.map +0 -1
package/cjs/index.js
CHANGED
|
@@ -1,12 +1,219 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
var
|
|
5
|
-
var
|
|
3
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var core = require('@salt-ds/core');
|
|
6
|
+
var styles = require('@salt-ds/styles');
|
|
7
|
+
var window = require('@salt-ds/window');
|
|
6
8
|
|
|
9
|
+
const ContextMenuContext = react.createContext(
|
|
10
|
+
null
|
|
11
|
+
);
|
|
12
|
+
const Provider = ({
|
|
13
|
+
children,
|
|
14
|
+
context,
|
|
15
|
+
menuActionHandler,
|
|
16
|
+
menuBuilder
|
|
17
|
+
}) => {
|
|
18
|
+
const [contextMenu, setContextMenu] = react.useState(null);
|
|
19
|
+
const showContextMenu = react.useMemo(() => {
|
|
20
|
+
if (context?.showContextMenu) {
|
|
21
|
+
return context.showContextMenu;
|
|
22
|
+
} else {
|
|
23
|
+
return (contextMenu2) => {
|
|
24
|
+
setContextMenu(contextMenu2);
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}, [context]);
|
|
28
|
+
const menuBuilders = react.useMemo(() => {
|
|
29
|
+
if (context?.menuBuilders && menuBuilder) {
|
|
30
|
+
return context.menuBuilders.concat(menuBuilder);
|
|
31
|
+
} else if (menuBuilder) {
|
|
32
|
+
return [menuBuilder];
|
|
33
|
+
} else {
|
|
34
|
+
return context?.menuBuilders || [];
|
|
35
|
+
}
|
|
36
|
+
}, [context, menuBuilder]);
|
|
37
|
+
const handleMenuAction = react.useCallback(
|
|
38
|
+
(menuItemId, options) => {
|
|
39
|
+
if (menuActionHandler?.(menuItemId, options)) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
if (context?.menuActionHandler?.(menuItemId, options)) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
[context, menuActionHandler]
|
|
47
|
+
);
|
|
48
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
49
|
+
ContextMenuContext.Provider,
|
|
50
|
+
{
|
|
51
|
+
value: {
|
|
52
|
+
menuActionHandler: handleMenuAction,
|
|
53
|
+
menuBuilders,
|
|
54
|
+
showContextMenu
|
|
55
|
+
},
|
|
56
|
+
children: [
|
|
57
|
+
children,
|
|
58
|
+
contextMenu
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
};
|
|
63
|
+
const ContextMenuProvider = ({
|
|
64
|
+
children,
|
|
65
|
+
menuActionHandler,
|
|
66
|
+
menuBuilder
|
|
67
|
+
}) => {
|
|
68
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ContextMenuContext.Consumer, { children: (parentContext) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
69
|
+
Provider,
|
|
70
|
+
{
|
|
71
|
+
context: parentContext,
|
|
72
|
+
menuActionHandler,
|
|
73
|
+
menuBuilder,
|
|
74
|
+
children
|
|
75
|
+
}
|
|
76
|
+
) });
|
|
77
|
+
};
|
|
7
78
|
|
|
79
|
+
const isGroupMenuItemDescriptor = (menuItem) => menuItem !== void 0 && "children" in menuItem;
|
|
80
|
+
const menuItemsFromMenuDescriptors = (menuDescriptors, menuActionHandler) => {
|
|
81
|
+
const fromDescriptor = (menuItem, index) => isGroupMenuItemDescriptor(menuItem) ? /* @__PURE__ */ jsxRuntime.jsxs(core.Menu, { children: [
|
|
82
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.MenuTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx(core.MenuItem, { children: menuItem.label }) }),
|
|
83
|
+
/* @__PURE__ */ jsxRuntime.jsx(core.MenuPanel, { className: "vuuContextMenuPanel", children: menuItem.children.map(fromDescriptor) })
|
|
84
|
+
] }, index) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
85
|
+
core.MenuItem,
|
|
86
|
+
{
|
|
87
|
+
className: menuItem.className,
|
|
88
|
+
"data-icon": menuItem.icon,
|
|
89
|
+
onClick: () => menuActionHandler(menuItem.id, menuItem.options),
|
|
90
|
+
children: menuItem.label
|
|
91
|
+
},
|
|
92
|
+
index
|
|
93
|
+
);
|
|
94
|
+
return menuDescriptors.map(fromDescriptor);
|
|
95
|
+
};
|
|
8
96
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
97
|
+
var contextMenuCss = ".vuuContextMenuPanel {\n &:has([data-icon]) {\n .saltMenuItem {\n padding-left: calc(var(--salt-spacing-400) + var(--salt-spacing-200));\n }\n .saltMenuItem[data-icon]:after {\n --vuu-icon-left: var(--salt-spacing-150);\n --vuu-icon-top: var(--salt-spacing-150);\n }\n .saltMenuItem[aria-haspopup=\"menu\"]:after {\n content: \"\";\n background-color: var(--vuu-icon-color, var(--saltIcon-color, var(--salt-content-secondary-foreground)));\n right: var(--salt-spacing-100);\n height: var(--vuu-icon-height, var(--vuu-icon-size, 12px));\n mask: var(--vuu-svg-triangle-right) center center / 8px 8px;\n mask-repeat: no-repeat;\n position: absolute;\n transform: rotate(315deg);\n top: var(--salt-spacing-200);\n width: var(--vuu-icon-width, var(--vuu-icon-size, 12px));\n }\n }\n}";
|
|
98
|
+
|
|
99
|
+
const ContextMenu = ({
|
|
100
|
+
menuHandler,
|
|
101
|
+
menuItemDescriptors,
|
|
102
|
+
onOpenChange,
|
|
103
|
+
open,
|
|
104
|
+
x,
|
|
105
|
+
y
|
|
106
|
+
}) => {
|
|
107
|
+
const targetWindow = window.useWindow();
|
|
108
|
+
styles.useComponentCssInjection({
|
|
109
|
+
testId: "vuu-context-menu",
|
|
110
|
+
css: contextMenuCss,
|
|
111
|
+
window: targetWindow
|
|
112
|
+
});
|
|
113
|
+
const virtualElement = {
|
|
114
|
+
getBoundingClientRect: () => ({
|
|
115
|
+
width: 0,
|
|
116
|
+
height: 0,
|
|
117
|
+
x,
|
|
118
|
+
y,
|
|
119
|
+
top: y,
|
|
120
|
+
right: x,
|
|
121
|
+
bottom: y,
|
|
122
|
+
left: x
|
|
123
|
+
})
|
|
124
|
+
};
|
|
125
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
126
|
+
core.Menu,
|
|
127
|
+
{
|
|
128
|
+
getVirtualElement: () => virtualElement,
|
|
129
|
+
onOpenChange,
|
|
130
|
+
open,
|
|
131
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(core.MenuPanel, { className: "vuuContextMenuPanel", children: menuItemsFromMenuDescriptors(menuItemDescriptors, menuHandler) })
|
|
132
|
+
}
|
|
133
|
+
);
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const useContextMenu = (menuBuilder, menuActionHandler) => {
|
|
137
|
+
const ctx = react.useContext(ContextMenuContext);
|
|
138
|
+
const buildMenuOptions = react.useCallback(
|
|
139
|
+
(menuBuilders, location, options) => {
|
|
140
|
+
let results = [];
|
|
141
|
+
for (const menuBuilder2 of menuBuilders) {
|
|
142
|
+
results = results.concat(menuBuilder2(location, options));
|
|
143
|
+
}
|
|
144
|
+
return results;
|
|
145
|
+
},
|
|
146
|
+
[]
|
|
147
|
+
);
|
|
148
|
+
const handleOpenChange = react.useCallback(
|
|
149
|
+
(open) => {
|
|
150
|
+
if (!open) {
|
|
151
|
+
ctx?.showContextMenu(null);
|
|
152
|
+
}
|
|
153
|
+
},
|
|
154
|
+
[ctx]
|
|
155
|
+
);
|
|
156
|
+
const showContextMenu = react.useCallback(
|
|
157
|
+
(evt, location, options, { onOpenChange, x = evt.clientX, y = evt.clientY } = {
|
|
158
|
+
x: evt.clientX,
|
|
159
|
+
y: evt.clientY
|
|
160
|
+
}) => {
|
|
161
|
+
evt.stopPropagation?.();
|
|
162
|
+
evt.preventDefault?.();
|
|
163
|
+
console.log(
|
|
164
|
+
`showContextMenu at ${evt.clientX} ${evt.clientY} location ${location}`
|
|
165
|
+
);
|
|
166
|
+
const menuBuilders = [];
|
|
167
|
+
if (menuBuilder) {
|
|
168
|
+
menuBuilders.push(menuBuilder);
|
|
169
|
+
}
|
|
170
|
+
if (ctx && Array.isArray(ctx?.menuBuilders) && ctx.menuBuilders.length > 0) {
|
|
171
|
+
menuBuilders.push(...ctx.menuBuilders);
|
|
172
|
+
}
|
|
173
|
+
if (menuBuilders.length > 0) {
|
|
174
|
+
const menuItemDescriptors = buildMenuOptions(
|
|
175
|
+
menuBuilders,
|
|
176
|
+
location,
|
|
177
|
+
options
|
|
178
|
+
);
|
|
179
|
+
const menuHandler = (menuItemId, options2) => {
|
|
180
|
+
if (menuActionHandler?.(menuItemId, options2) === true) {
|
|
181
|
+
return true;
|
|
182
|
+
} else {
|
|
183
|
+
return ctx?.menuActionHandler(menuItemId, options2);
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
const localOpenChange = (isOpen) => {
|
|
187
|
+
onOpenChange?.(isOpen);
|
|
188
|
+
handleOpenChange(isOpen);
|
|
189
|
+
};
|
|
190
|
+
if (menuItemDescriptors.length) {
|
|
191
|
+
ctx?.showContextMenu(
|
|
192
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
193
|
+
ContextMenu,
|
|
194
|
+
{
|
|
195
|
+
menuHandler,
|
|
196
|
+
menuItemDescriptors,
|
|
197
|
+
onOpenChange: localOpenChange,
|
|
198
|
+
open: true,
|
|
199
|
+
x,
|
|
200
|
+
y
|
|
201
|
+
}
|
|
202
|
+
)
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
} else {
|
|
206
|
+
console.warn(
|
|
207
|
+
"useContextMenu, no menuBuilders configured. These should be supplied via the ContextMenuProvider(s)"
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
[buildMenuOptions, ctx, handleOpenChange, menuActionHandler, menuBuilder]
|
|
212
|
+
);
|
|
213
|
+
return showContextMenu;
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
exports.ContextMenuProvider = ContextMenuProvider;
|
|
217
|
+
exports.isGroupMenuItemDescriptor = isGroupMenuItemDescriptor;
|
|
218
|
+
exports.useContextMenu = useContextMenu;
|
|
12
219
|
//# sourceMappingURL=index.js.map
|
package/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/ContextMenuProvider.tsx","../src/menu-utils.tsx","../src/ContextMenu.tsx","../src/useContextMenu.tsx"],"sourcesContent":["import {\n createContext,\n ReactElement,\n ReactNode,\n useCallback,\n useMemo,\n useState,\n} from \"react\";\n\nimport { ContextMenuItemDescriptor } from \"./menu-utils\";\n\nexport type MenuActionHandler<T extends string = string, Options = unknown> = (\n menuItemId: T,\n options?: Options,\n) => boolean | undefined;\n\nexport type MenuBuilder<Location extends string = string, Options = unknown> = (\n location: Location,\n options: Options,\n) => ContextMenuItemDescriptor[];\n\nexport interface ContextMenuContextType {\n menuBuilders: MenuBuilder[];\n menuActionHandler: MenuActionHandler;\n showContextMenu: (contextMenu: ReactElement | null) => void;\n}\n\nexport const ContextMenuContext = createContext<ContextMenuContextType | null>(\n null,\n);\n\nexport interface ContextMenuProviderProps<\n L extends string = string,\n O = unknown,\n> {\n children: ReactNode;\n menuActionHandler?: MenuActionHandler;\n menuBuilder?: MenuBuilder<L, O>;\n}\n\ninterface ProviderProps<L extends string = string, O = unknown>\n extends ContextMenuProviderProps<L, O> {\n context: ContextMenuContextType | null;\n}\n\nconst Provider = <L extends string = string, O = unknown>({\n children,\n context,\n menuActionHandler,\n menuBuilder,\n}: ProviderProps<L, O>) => {\n const [contextMenu, setContextMenu] = useState<ReactElement | null>(null);\n const showContextMenu = useMemo(() => {\n if (context?.showContextMenu) {\n return context.showContextMenu;\n } else {\n return (contextMenu: ReactElement | null) => {\n setContextMenu(contextMenu);\n };\n }\n }, [context]);\n const menuBuilders = useMemo(() => {\n if (context?.menuBuilders && menuBuilder) {\n // menuBuilder may have a narrower type than the inherited menuBuilders, discard this\n return context.menuBuilders.concat(menuBuilder as MenuBuilder);\n } else if (menuBuilder) {\n return [menuBuilder as MenuBuilder];\n } else {\n return context?.menuBuilders || [];\n }\n }, [context, menuBuilder]);\n\n const handleMenuAction = useCallback<MenuActionHandler>(\n (menuItemId, options) => {\n if (menuActionHandler?.(menuItemId, options)) {\n return true;\n }\n\n if (context?.menuActionHandler?.(menuItemId, options)) {\n return true;\n }\n },\n [context, menuActionHandler],\n );\n\n return (\n <ContextMenuContext.Provider\n value={{\n menuActionHandler: handleMenuAction,\n menuBuilders,\n showContextMenu,\n }}\n >\n {children}\n {contextMenu}\n </ContextMenuContext.Provider>\n );\n};\n\nexport const ContextMenuProvider = <L extends string = string, O = unknown>({\n children,\n menuActionHandler,\n menuBuilder,\n}: ContextMenuProviderProps<L, O>) => {\n return (\n <ContextMenuContext.Consumer>\n {(parentContext) => (\n <Provider<L, O>\n context={parentContext}\n menuActionHandler={menuActionHandler}\n menuBuilder={menuBuilder}\n >\n {children}\n </Provider>\n )}\n </ContextMenuContext.Consumer>\n );\n};\n","import { Menu, MenuItem, MenuPanel, MenuTrigger } from \"@salt-ds/core\";\nimport { MenuActionHandler } from \"./ContextMenuProvider\";\n\nexport interface ContextMenuItemBase {\n className?: string;\n icon?: string;\n label: string;\n location?: string;\n}\n\nexport interface ContextMenuLeafItemDescriptor extends ContextMenuItemBase {\n id: string;\n options?: unknown;\n}\n\nexport interface ContextMenuGroupItemDescriptor extends ContextMenuItemBase {\n children: ContextMenuItemDescriptor[];\n}\n\nexport type ContextMenuItemDescriptor =\n | ContextMenuLeafItemDescriptor\n | ContextMenuGroupItemDescriptor;\n\nexport const isGroupMenuItemDescriptor = (\n menuItem?: ContextMenuItemDescriptor,\n): menuItem is ContextMenuGroupItemDescriptor =>\n menuItem !== undefined && \"children\" in menuItem;\n\nexport const menuItemsFromMenuDescriptors = (\n menuDescriptors: ContextMenuItemDescriptor[],\n menuActionHandler: MenuActionHandler,\n) => {\n const fromDescriptor = (\n menuItem: ContextMenuItemDescriptor,\n index: number,\n ) =>\n isGroupMenuItemDescriptor(menuItem) ? (\n <Menu key={index}>\n <MenuTrigger>\n <MenuItem>{menuItem.label}</MenuItem>\n </MenuTrigger>\n <MenuPanel className=\"vuuContextMenuPanel\">\n {menuItem.children.map(fromDescriptor)}\n </MenuPanel>\n </Menu>\n ) : (\n <MenuItem\n key={index}\n className={menuItem.className}\n data-icon={menuItem.icon}\n onClick={() => menuActionHandler(menuItem.id, menuItem.options)}\n >\n {menuItem.label}\n </MenuItem>\n );\n\n return menuDescriptors.map(fromDescriptor);\n};\n","import { VirtualElement } from \"@floating-ui/dom\";\nimport { Menu, MenuPanel, MenuProps } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { MenuActionHandler } from \"./ContextMenuProvider\";\nimport {\n ContextMenuItemDescriptor,\n menuItemsFromMenuDescriptors,\n} from \"./menu-utils\";\n\nimport contextMenuCss from \"./ContextMenu.css\";\n\nexport interface ContextMenuProps\n extends Pick<MenuProps, \"open\" | \"onOpenChange\"> {\n menuHandler: MenuActionHandler;\n menuItemDescriptors: ContextMenuItemDescriptor[];\n x: number;\n y: number;\n}\n\nexport const ContextMenu = ({\n menuHandler,\n menuItemDescriptors,\n onOpenChange,\n open,\n x,\n y,\n}: ContextMenuProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-context-menu\",\n css: contextMenuCss,\n window: targetWindow,\n });\n\n const virtualElement: VirtualElement = {\n getBoundingClientRect: () => ({\n width: 0,\n height: 0,\n x,\n y,\n top: y,\n right: x,\n bottom: y,\n left: x,\n }),\n };\n\n return (\n <Menu\n getVirtualElement={() => virtualElement}\n onOpenChange={onOpenChange}\n open={open}\n >\n <MenuPanel className=\"vuuContextMenuPanel\">\n {menuItemsFromMenuDescriptors(menuItemDescriptors, menuHandler)}\n </MenuPanel>\n </Menu>\n );\n};\n","import { useCallback, useContext } from \"react\";\nimport { ContextMenu, ContextMenuProps } from \"./ContextMenu\";\nimport {\n ContextMenuContext,\n MenuActionHandler,\n MenuBuilder,\n} from \"./ContextMenuProvider\";\nimport { ContextMenuItemDescriptor } from \"./menu-utils\";\n\nexport type EventLike = {\n clientX: number;\n clientY: number;\n preventDefault?: () => void;\n stopPropagation?: () => void;\n};\n\nexport type ShowContextMenu = (\n e: EventLike,\n location: string,\n options: unknown,\n contextMenuProps?: Pick<ContextMenuProps, \"onOpenChange\" | \"x\" | \"y\">,\n) => void;\n\n// The argument allows a top-level menuBuilder to operate outside the Context\nexport const useContextMenu = (\n menuBuilder?: MenuBuilder,\n menuActionHandler?: MenuActionHandler,\n): ShowContextMenu => {\n const ctx = useContext(ContextMenuContext);\n\n const buildMenuOptions = useCallback(\n (menuBuilders: MenuBuilder[], location: string, options: unknown) => {\n let results: ContextMenuItemDescriptor[] = [];\n for (const menuBuilder of menuBuilders) {\n // Maybe we should leave the concatenation to the menuBuilder, then it can control menuItem order\n results = results.concat(menuBuilder(location, options));\n }\n return results;\n },\n [],\n );\n\n const handleOpenChange = useCallback(\n (open: boolean) => {\n if (!open) {\n ctx?.showContextMenu(null);\n }\n },\n [ctx],\n );\n\n const showContextMenu = useCallback<ShowContextMenu>(\n (\n evt,\n location,\n options,\n { onOpenChange, x = evt.clientX, y = evt.clientY } = {\n x: evt.clientX,\n y: evt.clientY,\n },\n ) => {\n evt.stopPropagation?.();\n evt.preventDefault?.();\n\n console.log(\n `showContextMenu at ${evt.clientX} ${evt.clientY} location ${location}`,\n );\n\n const menuBuilders: MenuBuilder[] = [];\n if (menuBuilder) {\n menuBuilders.push(menuBuilder);\n }\n if (\n ctx &&\n Array.isArray(ctx?.menuBuilders) &&\n ctx.menuBuilders.length > 0\n ) {\n menuBuilders.push(...ctx.menuBuilders);\n }\n\n if (menuBuilders.length > 0) {\n const menuItemDescriptors = buildMenuOptions(\n menuBuilders,\n location,\n options,\n );\n\n const menuHandler: MenuActionHandler = (menuItemId, options) => {\n if (menuActionHandler?.(menuItemId, options) === true) {\n return true;\n } else {\n return ctx?.menuActionHandler(menuItemId, options);\n }\n };\n\n const localOpenChange = (isOpen: boolean) => {\n onOpenChange?.(isOpen);\n handleOpenChange(isOpen);\n };\n\n if (menuItemDescriptors.length) {\n ctx?.showContextMenu(\n <ContextMenu\n menuHandler={menuHandler}\n menuItemDescriptors={menuItemDescriptors}\n onOpenChange={localOpenChange}\n open={true}\n x={x}\n y={y}\n />,\n );\n }\n } else {\n console.warn(\n \"useContextMenu, no menuBuilders configured. These should be supplied via the ContextMenuProvider(s)\",\n );\n }\n },\n [buildMenuOptions, ctx, handleOpenChange, menuActionHandler, menuBuilder],\n );\n\n return showContextMenu;\n};\n"],"names":["createContext","useState","useMemo","contextMenu","useCallback","jsxs","jsx","Menu","MenuTrigger","MenuItem","MenuPanel","useWindow","useComponentCssInjection","useContext","menuBuilder","options"],"mappings":"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"}
|
package/esm/index.js
CHANGED
|
@@ -1,4 +1,215 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import { createContext, useState, useMemo, useCallback, useContext } from 'react';
|
|
3
|
+
import { Menu, MenuTrigger, MenuItem, MenuPanel } from '@salt-ds/core';
|
|
4
|
+
import { useComponentCssInjection } from '@salt-ds/styles';
|
|
5
|
+
import { useWindow } from '@salt-ds/window';
|
|
6
|
+
|
|
7
|
+
const ContextMenuContext = createContext(
|
|
8
|
+
null
|
|
9
|
+
);
|
|
10
|
+
const Provider = ({
|
|
11
|
+
children,
|
|
12
|
+
context,
|
|
13
|
+
menuActionHandler,
|
|
14
|
+
menuBuilder
|
|
15
|
+
}) => {
|
|
16
|
+
const [contextMenu, setContextMenu] = useState(null);
|
|
17
|
+
const showContextMenu = useMemo(() => {
|
|
18
|
+
if (context?.showContextMenu) {
|
|
19
|
+
return context.showContextMenu;
|
|
20
|
+
} else {
|
|
21
|
+
return (contextMenu2) => {
|
|
22
|
+
setContextMenu(contextMenu2);
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}, [context]);
|
|
26
|
+
const menuBuilders = useMemo(() => {
|
|
27
|
+
if (context?.menuBuilders && menuBuilder) {
|
|
28
|
+
return context.menuBuilders.concat(menuBuilder);
|
|
29
|
+
} else if (menuBuilder) {
|
|
30
|
+
return [menuBuilder];
|
|
31
|
+
} else {
|
|
32
|
+
return context?.menuBuilders || [];
|
|
33
|
+
}
|
|
34
|
+
}, [context, menuBuilder]);
|
|
35
|
+
const handleMenuAction = useCallback(
|
|
36
|
+
(menuItemId, options) => {
|
|
37
|
+
if (menuActionHandler?.(menuItemId, options)) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
if (context?.menuActionHandler?.(menuItemId, options)) {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
[context, menuActionHandler]
|
|
45
|
+
);
|
|
46
|
+
return /* @__PURE__ */ jsxs(
|
|
47
|
+
ContextMenuContext.Provider,
|
|
48
|
+
{
|
|
49
|
+
value: {
|
|
50
|
+
menuActionHandler: handleMenuAction,
|
|
51
|
+
menuBuilders,
|
|
52
|
+
showContextMenu
|
|
53
|
+
},
|
|
54
|
+
children: [
|
|
55
|
+
children,
|
|
56
|
+
contextMenu
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
};
|
|
61
|
+
const ContextMenuProvider = ({
|
|
62
|
+
children,
|
|
63
|
+
menuActionHandler,
|
|
64
|
+
menuBuilder
|
|
65
|
+
}) => {
|
|
66
|
+
return /* @__PURE__ */ jsx(ContextMenuContext.Consumer, { children: (parentContext) => /* @__PURE__ */ jsx(
|
|
67
|
+
Provider,
|
|
68
|
+
{
|
|
69
|
+
context: parentContext,
|
|
70
|
+
menuActionHandler,
|
|
71
|
+
menuBuilder,
|
|
72
|
+
children
|
|
73
|
+
}
|
|
74
|
+
) });
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const isGroupMenuItemDescriptor = (menuItem) => menuItem !== void 0 && "children" in menuItem;
|
|
78
|
+
const menuItemsFromMenuDescriptors = (menuDescriptors, menuActionHandler) => {
|
|
79
|
+
const fromDescriptor = (menuItem, index) => isGroupMenuItemDescriptor(menuItem) ? /* @__PURE__ */ jsxs(Menu, { children: [
|
|
80
|
+
/* @__PURE__ */ jsx(MenuTrigger, { children: /* @__PURE__ */ jsx(MenuItem, { children: menuItem.label }) }),
|
|
81
|
+
/* @__PURE__ */ jsx(MenuPanel, { className: "vuuContextMenuPanel", children: menuItem.children.map(fromDescriptor) })
|
|
82
|
+
] }, index) : /* @__PURE__ */ jsx(
|
|
83
|
+
MenuItem,
|
|
84
|
+
{
|
|
85
|
+
className: menuItem.className,
|
|
86
|
+
"data-icon": menuItem.icon,
|
|
87
|
+
onClick: () => menuActionHandler(menuItem.id, menuItem.options),
|
|
88
|
+
children: menuItem.label
|
|
89
|
+
},
|
|
90
|
+
index
|
|
91
|
+
);
|
|
92
|
+
return menuDescriptors.map(fromDescriptor);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
var contextMenuCss = ".vuuContextMenuPanel {\n &:has([data-icon]) {\n .saltMenuItem {\n padding-left: calc(var(--salt-spacing-400) + var(--salt-spacing-200));\n }\n .saltMenuItem[data-icon]:after {\n --vuu-icon-left: var(--salt-spacing-150);\n --vuu-icon-top: var(--salt-spacing-150);\n }\n .saltMenuItem[aria-haspopup=\"menu\"]:after {\n content: \"\";\n background-color: var(--vuu-icon-color, var(--saltIcon-color, var(--salt-content-secondary-foreground)));\n right: var(--salt-spacing-100);\n height: var(--vuu-icon-height, var(--vuu-icon-size, 12px));\n mask: var(--vuu-svg-triangle-right) center center / 8px 8px;\n mask-repeat: no-repeat;\n position: absolute;\n transform: rotate(315deg);\n top: var(--salt-spacing-200);\n width: var(--vuu-icon-width, var(--vuu-icon-size, 12px));\n }\n }\n}";
|
|
96
|
+
|
|
97
|
+
const ContextMenu = ({
|
|
98
|
+
menuHandler,
|
|
99
|
+
menuItemDescriptors,
|
|
100
|
+
onOpenChange,
|
|
101
|
+
open,
|
|
102
|
+
x,
|
|
103
|
+
y
|
|
104
|
+
}) => {
|
|
105
|
+
const targetWindow = useWindow();
|
|
106
|
+
useComponentCssInjection({
|
|
107
|
+
testId: "vuu-context-menu",
|
|
108
|
+
css: contextMenuCss,
|
|
109
|
+
window: targetWindow
|
|
110
|
+
});
|
|
111
|
+
const virtualElement = {
|
|
112
|
+
getBoundingClientRect: () => ({
|
|
113
|
+
width: 0,
|
|
114
|
+
height: 0,
|
|
115
|
+
x,
|
|
116
|
+
y,
|
|
117
|
+
top: y,
|
|
118
|
+
right: x,
|
|
119
|
+
bottom: y,
|
|
120
|
+
left: x
|
|
121
|
+
})
|
|
122
|
+
};
|
|
123
|
+
return /* @__PURE__ */ jsx(
|
|
124
|
+
Menu,
|
|
125
|
+
{
|
|
126
|
+
getVirtualElement: () => virtualElement,
|
|
127
|
+
onOpenChange,
|
|
128
|
+
open,
|
|
129
|
+
children: /* @__PURE__ */ jsx(MenuPanel, { className: "vuuContextMenuPanel", children: menuItemsFromMenuDescriptors(menuItemDescriptors, menuHandler) })
|
|
130
|
+
}
|
|
131
|
+
);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const useContextMenu = (menuBuilder, menuActionHandler) => {
|
|
135
|
+
const ctx = useContext(ContextMenuContext);
|
|
136
|
+
const buildMenuOptions = useCallback(
|
|
137
|
+
(menuBuilders, location, options) => {
|
|
138
|
+
let results = [];
|
|
139
|
+
for (const menuBuilder2 of menuBuilders) {
|
|
140
|
+
results = results.concat(menuBuilder2(location, options));
|
|
141
|
+
}
|
|
142
|
+
return results;
|
|
143
|
+
},
|
|
144
|
+
[]
|
|
145
|
+
);
|
|
146
|
+
const handleOpenChange = useCallback(
|
|
147
|
+
(open) => {
|
|
148
|
+
if (!open) {
|
|
149
|
+
ctx?.showContextMenu(null);
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
[ctx]
|
|
153
|
+
);
|
|
154
|
+
const showContextMenu = useCallback(
|
|
155
|
+
(evt, location, options, { onOpenChange, x = evt.clientX, y = evt.clientY } = {
|
|
156
|
+
x: evt.clientX,
|
|
157
|
+
y: evt.clientY
|
|
158
|
+
}) => {
|
|
159
|
+
evt.stopPropagation?.();
|
|
160
|
+
evt.preventDefault?.();
|
|
161
|
+
console.log(
|
|
162
|
+
`showContextMenu at ${evt.clientX} ${evt.clientY} location ${location}`
|
|
163
|
+
);
|
|
164
|
+
const menuBuilders = [];
|
|
165
|
+
if (menuBuilder) {
|
|
166
|
+
menuBuilders.push(menuBuilder);
|
|
167
|
+
}
|
|
168
|
+
if (ctx && Array.isArray(ctx?.menuBuilders) && ctx.menuBuilders.length > 0) {
|
|
169
|
+
menuBuilders.push(...ctx.menuBuilders);
|
|
170
|
+
}
|
|
171
|
+
if (menuBuilders.length > 0) {
|
|
172
|
+
const menuItemDescriptors = buildMenuOptions(
|
|
173
|
+
menuBuilders,
|
|
174
|
+
location,
|
|
175
|
+
options
|
|
176
|
+
);
|
|
177
|
+
const menuHandler = (menuItemId, options2) => {
|
|
178
|
+
if (menuActionHandler?.(menuItemId, options2) === true) {
|
|
179
|
+
return true;
|
|
180
|
+
} else {
|
|
181
|
+
return ctx?.menuActionHandler(menuItemId, options2);
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
const localOpenChange = (isOpen) => {
|
|
185
|
+
onOpenChange?.(isOpen);
|
|
186
|
+
handleOpenChange(isOpen);
|
|
187
|
+
};
|
|
188
|
+
if (menuItemDescriptors.length) {
|
|
189
|
+
ctx?.showContextMenu(
|
|
190
|
+
/* @__PURE__ */ jsx(
|
|
191
|
+
ContextMenu,
|
|
192
|
+
{
|
|
193
|
+
menuHandler,
|
|
194
|
+
menuItemDescriptors,
|
|
195
|
+
onOpenChange: localOpenChange,
|
|
196
|
+
open: true,
|
|
197
|
+
x,
|
|
198
|
+
y
|
|
199
|
+
}
|
|
200
|
+
)
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
} else {
|
|
204
|
+
console.warn(
|
|
205
|
+
"useContextMenu, no menuBuilders configured. These should be supplied via the ContextMenuProvider(s)"
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
[buildMenuOptions, ctx, handleOpenChange, menuActionHandler, menuBuilder]
|
|
210
|
+
);
|
|
211
|
+
return showContextMenu;
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
export { ContextMenuProvider, isGroupMenuItemDescriptor, useContextMenu };
|
|
4
215
|
//# sourceMappingURL=index.js.map
|
package/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/ContextMenuProvider.tsx","../src/menu-utils.tsx","../src/ContextMenu.tsx","../src/useContextMenu.tsx"],"sourcesContent":["import {\n createContext,\n ReactElement,\n ReactNode,\n useCallback,\n useMemo,\n useState,\n} from \"react\";\n\nimport { ContextMenuItemDescriptor } from \"./menu-utils\";\n\nexport type MenuActionHandler<T extends string = string, Options = unknown> = (\n menuItemId: T,\n options?: Options,\n) => boolean | undefined;\n\nexport type MenuBuilder<Location extends string = string, Options = unknown> = (\n location: Location,\n options: Options,\n) => ContextMenuItemDescriptor[];\n\nexport interface ContextMenuContextType {\n menuBuilders: MenuBuilder[];\n menuActionHandler: MenuActionHandler;\n showContextMenu: (contextMenu: ReactElement | null) => void;\n}\n\nexport const ContextMenuContext = createContext<ContextMenuContextType | null>(\n null,\n);\n\nexport interface ContextMenuProviderProps<\n L extends string = string,\n O = unknown,\n> {\n children: ReactNode;\n menuActionHandler?: MenuActionHandler;\n menuBuilder?: MenuBuilder<L, O>;\n}\n\ninterface ProviderProps<L extends string = string, O = unknown>\n extends ContextMenuProviderProps<L, O> {\n context: ContextMenuContextType | null;\n}\n\nconst Provider = <L extends string = string, O = unknown>({\n children,\n context,\n menuActionHandler,\n menuBuilder,\n}: ProviderProps<L, O>) => {\n const [contextMenu, setContextMenu] = useState<ReactElement | null>(null);\n const showContextMenu = useMemo(() => {\n if (context?.showContextMenu) {\n return context.showContextMenu;\n } else {\n return (contextMenu: ReactElement | null) => {\n setContextMenu(contextMenu);\n };\n }\n }, [context]);\n const menuBuilders = useMemo(() => {\n if (context?.menuBuilders && menuBuilder) {\n // menuBuilder may have a narrower type than the inherited menuBuilders, discard this\n return context.menuBuilders.concat(menuBuilder as MenuBuilder);\n } else if (menuBuilder) {\n return [menuBuilder as MenuBuilder];\n } else {\n return context?.menuBuilders || [];\n }\n }, [context, menuBuilder]);\n\n const handleMenuAction = useCallback<MenuActionHandler>(\n (menuItemId, options) => {\n if (menuActionHandler?.(menuItemId, options)) {\n return true;\n }\n\n if (context?.menuActionHandler?.(menuItemId, options)) {\n return true;\n }\n },\n [context, menuActionHandler],\n );\n\n return (\n <ContextMenuContext.Provider\n value={{\n menuActionHandler: handleMenuAction,\n menuBuilders,\n showContextMenu,\n }}\n >\n {children}\n {contextMenu}\n </ContextMenuContext.Provider>\n );\n};\n\nexport const ContextMenuProvider = <L extends string = string, O = unknown>({\n children,\n menuActionHandler,\n menuBuilder,\n}: ContextMenuProviderProps<L, O>) => {\n return (\n <ContextMenuContext.Consumer>\n {(parentContext) => (\n <Provider<L, O>\n context={parentContext}\n menuActionHandler={menuActionHandler}\n menuBuilder={menuBuilder}\n >\n {children}\n </Provider>\n )}\n </ContextMenuContext.Consumer>\n );\n};\n","import { Menu, MenuItem, MenuPanel, MenuTrigger } from \"@salt-ds/core\";\nimport { MenuActionHandler } from \"./ContextMenuProvider\";\n\nexport interface ContextMenuItemBase {\n className?: string;\n icon?: string;\n label: string;\n location?: string;\n}\n\nexport interface ContextMenuLeafItemDescriptor extends ContextMenuItemBase {\n id: string;\n options?: unknown;\n}\n\nexport interface ContextMenuGroupItemDescriptor extends ContextMenuItemBase {\n children: ContextMenuItemDescriptor[];\n}\n\nexport type ContextMenuItemDescriptor =\n | ContextMenuLeafItemDescriptor\n | ContextMenuGroupItemDescriptor;\n\nexport const isGroupMenuItemDescriptor = (\n menuItem?: ContextMenuItemDescriptor,\n): menuItem is ContextMenuGroupItemDescriptor =>\n menuItem !== undefined && \"children\" in menuItem;\n\nexport const menuItemsFromMenuDescriptors = (\n menuDescriptors: ContextMenuItemDescriptor[],\n menuActionHandler: MenuActionHandler,\n) => {\n const fromDescriptor = (\n menuItem: ContextMenuItemDescriptor,\n index: number,\n ) =>\n isGroupMenuItemDescriptor(menuItem) ? (\n <Menu key={index}>\n <MenuTrigger>\n <MenuItem>{menuItem.label}</MenuItem>\n </MenuTrigger>\n <MenuPanel className=\"vuuContextMenuPanel\">\n {menuItem.children.map(fromDescriptor)}\n </MenuPanel>\n </Menu>\n ) : (\n <MenuItem\n key={index}\n className={menuItem.className}\n data-icon={menuItem.icon}\n onClick={() => menuActionHandler(menuItem.id, menuItem.options)}\n >\n {menuItem.label}\n </MenuItem>\n );\n\n return menuDescriptors.map(fromDescriptor);\n};\n","import { VirtualElement } from \"@floating-ui/dom\";\nimport { Menu, MenuPanel, MenuProps } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { MenuActionHandler } from \"./ContextMenuProvider\";\nimport {\n ContextMenuItemDescriptor,\n menuItemsFromMenuDescriptors,\n} from \"./menu-utils\";\n\nimport contextMenuCss from \"./ContextMenu.css\";\n\nexport interface ContextMenuProps\n extends Pick<MenuProps, \"open\" | \"onOpenChange\"> {\n menuHandler: MenuActionHandler;\n menuItemDescriptors: ContextMenuItemDescriptor[];\n x: number;\n y: number;\n}\n\nexport const ContextMenu = ({\n menuHandler,\n menuItemDescriptors,\n onOpenChange,\n open,\n x,\n y,\n}: ContextMenuProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-context-menu\",\n css: contextMenuCss,\n window: targetWindow,\n });\n\n const virtualElement: VirtualElement = {\n getBoundingClientRect: () => ({\n width: 0,\n height: 0,\n x,\n y,\n top: y,\n right: x,\n bottom: y,\n left: x,\n }),\n };\n\n return (\n <Menu\n getVirtualElement={() => virtualElement}\n onOpenChange={onOpenChange}\n open={open}\n >\n <MenuPanel className=\"vuuContextMenuPanel\">\n {menuItemsFromMenuDescriptors(menuItemDescriptors, menuHandler)}\n </MenuPanel>\n </Menu>\n );\n};\n","import { useCallback, useContext } from \"react\";\nimport { ContextMenu, ContextMenuProps } from \"./ContextMenu\";\nimport {\n ContextMenuContext,\n MenuActionHandler,\n MenuBuilder,\n} from \"./ContextMenuProvider\";\nimport { ContextMenuItemDescriptor } from \"./menu-utils\";\n\nexport type EventLike = {\n clientX: number;\n clientY: number;\n preventDefault?: () => void;\n stopPropagation?: () => void;\n};\n\nexport type ShowContextMenu = (\n e: EventLike,\n location: string,\n options: unknown,\n contextMenuProps?: Pick<ContextMenuProps, \"onOpenChange\" | \"x\" | \"y\">,\n) => void;\n\n// The argument allows a top-level menuBuilder to operate outside the Context\nexport const useContextMenu = (\n menuBuilder?: MenuBuilder,\n menuActionHandler?: MenuActionHandler,\n): ShowContextMenu => {\n const ctx = useContext(ContextMenuContext);\n\n const buildMenuOptions = useCallback(\n (menuBuilders: MenuBuilder[], location: string, options: unknown) => {\n let results: ContextMenuItemDescriptor[] = [];\n for (const menuBuilder of menuBuilders) {\n // Maybe we should leave the concatenation to the menuBuilder, then it can control menuItem order\n results = results.concat(menuBuilder(location, options));\n }\n return results;\n },\n [],\n );\n\n const handleOpenChange = useCallback(\n (open: boolean) => {\n if (!open) {\n ctx?.showContextMenu(null);\n }\n },\n [ctx],\n );\n\n const showContextMenu = useCallback<ShowContextMenu>(\n (\n evt,\n location,\n options,\n { onOpenChange, x = evt.clientX, y = evt.clientY } = {\n x: evt.clientX,\n y: evt.clientY,\n },\n ) => {\n evt.stopPropagation?.();\n evt.preventDefault?.();\n\n console.log(\n `showContextMenu at ${evt.clientX} ${evt.clientY} location ${location}`,\n );\n\n const menuBuilders: MenuBuilder[] = [];\n if (menuBuilder) {\n menuBuilders.push(menuBuilder);\n }\n if (\n ctx &&\n Array.isArray(ctx?.menuBuilders) &&\n ctx.menuBuilders.length > 0\n ) {\n menuBuilders.push(...ctx.menuBuilders);\n }\n\n if (menuBuilders.length > 0) {\n const menuItemDescriptors = buildMenuOptions(\n menuBuilders,\n location,\n options,\n );\n\n const menuHandler: MenuActionHandler = (menuItemId, options) => {\n if (menuActionHandler?.(menuItemId, options) === true) {\n return true;\n } else {\n return ctx?.menuActionHandler(menuItemId, options);\n }\n };\n\n const localOpenChange = (isOpen: boolean) => {\n onOpenChange?.(isOpen);\n handleOpenChange(isOpen);\n };\n\n if (menuItemDescriptors.length) {\n ctx?.showContextMenu(\n <ContextMenu\n menuHandler={menuHandler}\n menuItemDescriptors={menuItemDescriptors}\n onOpenChange={localOpenChange}\n open={true}\n x={x}\n y={y}\n />,\n );\n }\n } else {\n console.warn(\n \"useContextMenu, no menuBuilders configured. These should be supplied via the ContextMenuProvider(s)\",\n );\n }\n },\n [buildMenuOptions, ctx, handleOpenChange, menuActionHandler, menuBuilder],\n );\n\n return showContextMenu;\n};\n"],"names":["contextMenu","menuBuilder","options"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.13.
|
|
2
|
+
"version": "0.13.8",
|
|
3
3
|
"author": "heswell",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"devDependencies": {
|
|
6
|
-
"@vuu-ui/vuu-data-types": "0.13.
|
|
7
|
-
"@vuu-ui/vuu-protocol-types": "0.13.
|
|
8
|
-
"@vuu-ui/vuu-table-types": "0.13.
|
|
6
|
+
"@vuu-ui/vuu-data-types": "0.13.8",
|
|
7
|
+
"@vuu-ui/vuu-protocol-types": "0.13.8",
|
|
8
|
+
"@vuu-ui/vuu-table-types": "0.13.8"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@vuu-ui/vuu-utils": "0.13.
|
|
11
|
+
"@vuu-ui/vuu-utils": "0.13.8",
|
|
12
12
|
"@salt-ds/core": "1.43.0",
|
|
13
13
|
"@salt-ds/styles": "0.2.1",
|
|
14
14
|
"@salt-ds/window": "0.1.1"
|
package/cjs/ContextMenu.css.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var contextMenuCss = ".vuuContextMenuPanel {\n &:has([data-icon]) {\n .saltMenuItem {\n padding-left: calc(var(--salt-spacing-400) + var(--salt-spacing-200));\n }\n .saltMenuItem[data-icon]:after {\n --vuu-icon-left: var(--salt-spacing-150);\n --vuu-icon-top: var(--salt-spacing-150);\n }\n .saltMenuItem[aria-haspopup=\"menu\"]:after {\n content: \"\";\n background-color: var(--vuu-icon-color, var(--saltIcon-color, var(--salt-content-secondary-foreground)));\n right: var(--salt-spacing-100);\n height: var(--vuu-icon-height, var(--vuu-icon-size, 12px));\n mask: var(--vuu-svg-triangle-right) center center / 8px 8px;\n mask-repeat: no-repeat;\n position: absolute;\n transform: rotate(315deg);\n top: var(--salt-spacing-200);\n width: var(--vuu-icon-width, var(--vuu-icon-size, 12px));\n }\n }\n}";
|
|
4
|
-
|
|
5
|
-
module.exports = contextMenuCss;
|
|
6
|
-
//# sourceMappingURL=ContextMenu.css.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ContextMenu.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
|
package/cjs/ContextMenu.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
-
var core = require('@salt-ds/core');
|
|
5
|
-
var styles = require('@salt-ds/styles');
|
|
6
|
-
var window = require('@salt-ds/window');
|
|
7
|
-
var menuUtils = require('./menu-utils.js');
|
|
8
|
-
var ContextMenu$1 = require('./ContextMenu.css.js');
|
|
9
|
-
|
|
10
|
-
const ContextMenu = ({
|
|
11
|
-
menuHandler,
|
|
12
|
-
menuItemDescriptors,
|
|
13
|
-
onOpenChange,
|
|
14
|
-
open,
|
|
15
|
-
x,
|
|
16
|
-
y
|
|
17
|
-
}) => {
|
|
18
|
-
const targetWindow = window.useWindow();
|
|
19
|
-
styles.useComponentCssInjection({
|
|
20
|
-
testId: "vuu-context-menu",
|
|
21
|
-
css: ContextMenu$1,
|
|
22
|
-
window: targetWindow
|
|
23
|
-
});
|
|
24
|
-
const virtualElement = {
|
|
25
|
-
getBoundingClientRect: () => ({
|
|
26
|
-
width: 0,
|
|
27
|
-
height: 0,
|
|
28
|
-
x,
|
|
29
|
-
y,
|
|
30
|
-
top: y,
|
|
31
|
-
right: x,
|
|
32
|
-
bottom: y,
|
|
33
|
-
left: x
|
|
34
|
-
})
|
|
35
|
-
};
|
|
36
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
37
|
-
core.Menu,
|
|
38
|
-
{
|
|
39
|
-
getVirtualElement: () => virtualElement,
|
|
40
|
-
onOpenChange,
|
|
41
|
-
open,
|
|
42
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(core.MenuPanel, { className: "vuuContextMenuPanel", children: menuUtils.menuItemsFromMenuDescriptors(menuItemDescriptors, menuHandler) })
|
|
43
|
-
}
|
|
44
|
-
);
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
exports.ContextMenu = ContextMenu;
|
|
48
|
-
//# sourceMappingURL=ContextMenu.js.map
|
package/cjs/ContextMenu.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ContextMenu.js","sources":["../src/ContextMenu.tsx"],"sourcesContent":["import { VirtualElement } from \"@floating-ui/dom\";\nimport { Menu, MenuPanel, MenuProps } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { MenuActionHandler } from \"./ContextMenuProvider\";\nimport {\n ContextMenuItemDescriptor,\n menuItemsFromMenuDescriptors,\n} from \"./menu-utils\";\n\nimport contextMenuCss from \"./ContextMenu.css\";\n\nexport interface ContextMenuProps\n extends Pick<MenuProps, \"open\" | \"onOpenChange\"> {\n menuHandler: MenuActionHandler;\n menuItemDescriptors: ContextMenuItemDescriptor[];\n x: number;\n y: number;\n}\n\nexport const ContextMenu = ({\n menuHandler,\n menuItemDescriptors,\n onOpenChange,\n open,\n x,\n y,\n}: ContextMenuProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-context-menu\",\n css: contextMenuCss,\n window: targetWindow,\n });\n\n const virtualElement: VirtualElement = {\n getBoundingClientRect: () => ({\n width: 0,\n height: 0,\n x,\n y,\n top: y,\n right: x,\n bottom: y,\n left: x,\n }),\n };\n\n return (\n <Menu\n getVirtualElement={() => virtualElement}\n onOpenChange={onOpenChange}\n open={open}\n >\n <MenuPanel className=\"vuuContextMenuPanel\">\n {menuItemsFromMenuDescriptors(menuItemDescriptors, menuHandler)}\n </MenuPanel>\n </Menu>\n );\n};\n"],"names":["useWindow","useComponentCssInjection","contextMenuCss","jsx","Menu","MenuPanel","menuItemsFromMenuDescriptors"],"mappings":";;;;;;;;;AAoBO,MAAM,cAAc,CAAC;AAAA,EAC1B,WAAA;AAAA,EACA,mBAAA;AAAA,EACA,YAAA;AAAA,EACA,IAAA;AAAA,EACA,CAAA;AAAA,EACA;AACF,CAAwB,KAAA;AACtB,EAAA,MAAM,eAAeA,gBAAU,EAAA;AAC/B,EAAyBC,+BAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,kBAAA;AAAA,IACR,GAAK,EAAAC,aAAA;AAAA,IACL,MAAQ,EAAA;AAAA,GACT,CAAA;AAED,EAAA,MAAM,cAAiC,GAAA;AAAA,IACrC,uBAAuB,OAAO;AAAA,MAC5B,KAAO,EAAA,CAAA;AAAA,MACP,MAAQ,EAAA,CAAA;AAAA,MACR,CAAA;AAAA,MACA,CAAA;AAAA,MACA,GAAK,EAAA,CAAA;AAAA,MACL,KAAO,EAAA,CAAA;AAAA,MACP,MAAQ,EAAA,CAAA;AAAA,MACR,IAAM,EAAA;AAAA,KACR;AAAA,GACF;AAEA,EACE,uBAAAC,cAAA;AAAA,IAACC,SAAA;AAAA,IAAA;AAAA,MACC,mBAAmB,MAAM,cAAA;AAAA,MACzB,YAAA;AAAA,MACA,IAAA;AAAA,MAEA,yCAACC,cAAU,EAAA,EAAA,SAAA,EAAU,uBAClB,QAA6B,EAAAC,sCAAA,CAAA,mBAAA,EAAqB,WAAW,CAChE,EAAA;AAAA;AAAA,GACF;AAEJ;;;;"}
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
-
var react = require('react');
|
|
5
|
-
|
|
6
|
-
const ContextMenuContext = react.createContext(
|
|
7
|
-
null
|
|
8
|
-
);
|
|
9
|
-
const Provider = ({
|
|
10
|
-
children,
|
|
11
|
-
context,
|
|
12
|
-
menuActionHandler,
|
|
13
|
-
menuBuilder
|
|
14
|
-
}) => {
|
|
15
|
-
const [contextMenu, setContextMenu] = react.useState(null);
|
|
16
|
-
const showContextMenu = react.useMemo(() => {
|
|
17
|
-
if (context?.showContextMenu) {
|
|
18
|
-
return context.showContextMenu;
|
|
19
|
-
} else {
|
|
20
|
-
return (contextMenu2) => {
|
|
21
|
-
setContextMenu(contextMenu2);
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
}, [context]);
|
|
25
|
-
const menuBuilders = react.useMemo(() => {
|
|
26
|
-
if (context?.menuBuilders && menuBuilder) {
|
|
27
|
-
return context.menuBuilders.concat(menuBuilder);
|
|
28
|
-
} else if (menuBuilder) {
|
|
29
|
-
return [menuBuilder];
|
|
30
|
-
} else {
|
|
31
|
-
return context?.menuBuilders || [];
|
|
32
|
-
}
|
|
33
|
-
}, [context, menuBuilder]);
|
|
34
|
-
const handleMenuAction = react.useCallback(
|
|
35
|
-
(menuItemId, options) => {
|
|
36
|
-
if (menuActionHandler?.(menuItemId, options)) {
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
if (context?.menuActionHandler?.(menuItemId, options)) {
|
|
40
|
-
return true;
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
[context, menuActionHandler]
|
|
44
|
-
);
|
|
45
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
46
|
-
ContextMenuContext.Provider,
|
|
47
|
-
{
|
|
48
|
-
value: {
|
|
49
|
-
menuActionHandler: handleMenuAction,
|
|
50
|
-
menuBuilders,
|
|
51
|
-
showContextMenu
|
|
52
|
-
},
|
|
53
|
-
children: [
|
|
54
|
-
children,
|
|
55
|
-
contextMenu
|
|
56
|
-
]
|
|
57
|
-
}
|
|
58
|
-
);
|
|
59
|
-
};
|
|
60
|
-
const ContextMenuProvider = ({
|
|
61
|
-
children,
|
|
62
|
-
menuActionHandler,
|
|
63
|
-
menuBuilder
|
|
64
|
-
}) => {
|
|
65
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ContextMenuContext.Consumer, { children: (parentContext) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
66
|
-
Provider,
|
|
67
|
-
{
|
|
68
|
-
context: parentContext,
|
|
69
|
-
menuActionHandler,
|
|
70
|
-
menuBuilder,
|
|
71
|
-
children
|
|
72
|
-
}
|
|
73
|
-
) });
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
exports.ContextMenuContext = ContextMenuContext;
|
|
77
|
-
exports.ContextMenuProvider = ContextMenuProvider;
|
|
78
|
-
//# sourceMappingURL=ContextMenuProvider.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ContextMenuProvider.js","sources":["../src/ContextMenuProvider.tsx"],"sourcesContent":["import {\n createContext,\n ReactElement,\n ReactNode,\n useCallback,\n useMemo,\n useState,\n} from \"react\";\n\nimport { ContextMenuItemDescriptor } from \"./menu-utils\";\n\nexport type MenuActionHandler<T extends string = string, Options = unknown> = (\n menuItemId: T,\n options?: Options,\n) => boolean | undefined;\n\nexport type MenuBuilder<Location extends string = string, Options = unknown> = (\n location: Location,\n options: Options,\n) => ContextMenuItemDescriptor[];\n\nexport interface ContextMenuContextType {\n menuBuilders: MenuBuilder[];\n menuActionHandler: MenuActionHandler;\n showContextMenu: (contextMenu: ReactElement | null) => void;\n}\n\nexport const ContextMenuContext = createContext<ContextMenuContextType | null>(\n null,\n);\n\nexport interface ContextMenuProviderProps<\n L extends string = string,\n O = unknown,\n> {\n children: ReactNode;\n menuActionHandler?: MenuActionHandler;\n menuBuilder?: MenuBuilder<L, O>;\n}\n\ninterface ProviderProps<L extends string = string, O = unknown>\n extends ContextMenuProviderProps<L, O> {\n context: ContextMenuContextType | null;\n}\n\nconst Provider = <L extends string = string, O = unknown>({\n children,\n context,\n menuActionHandler,\n menuBuilder,\n}: ProviderProps<L, O>) => {\n const [contextMenu, setContextMenu] = useState<ReactElement | null>(null);\n const showContextMenu = useMemo(() => {\n if (context?.showContextMenu) {\n return context.showContextMenu;\n } else {\n return (contextMenu: ReactElement | null) => {\n setContextMenu(contextMenu);\n };\n }\n }, [context]);\n const menuBuilders = useMemo(() => {\n if (context?.menuBuilders && menuBuilder) {\n // menuBuilder may have a narrower type than the inherited menuBuilders, discard this\n return context.menuBuilders.concat(menuBuilder as MenuBuilder);\n } else if (menuBuilder) {\n return [menuBuilder as MenuBuilder];\n } else {\n return context?.menuBuilders || [];\n }\n }, [context, menuBuilder]);\n\n const handleMenuAction = useCallback<MenuActionHandler>(\n (menuItemId, options) => {\n if (menuActionHandler?.(menuItemId, options)) {\n return true;\n }\n\n if (context?.menuActionHandler?.(menuItemId, options)) {\n return true;\n }\n },\n [context, menuActionHandler],\n );\n\n return (\n <ContextMenuContext.Provider\n value={{\n menuActionHandler: handleMenuAction,\n menuBuilders,\n showContextMenu,\n }}\n >\n {children}\n {contextMenu}\n </ContextMenuContext.Provider>\n );\n};\n\nexport const ContextMenuProvider = <L extends string = string, O = unknown>({\n children,\n menuActionHandler,\n menuBuilder,\n}: ContextMenuProviderProps<L, O>) => {\n return (\n <ContextMenuContext.Consumer>\n {(parentContext) => (\n <Provider<L, O>\n context={parentContext}\n menuActionHandler={menuActionHandler}\n menuBuilder={menuBuilder}\n >\n {children}\n </Provider>\n )}\n </ContextMenuContext.Consumer>\n );\n};\n"],"names":["createContext","useState","useMemo","contextMenu","useCallback","jsxs","jsx"],"mappings":";;;;;AA2BO,MAAM,kBAAqB,GAAAA,mBAAA;AAAA,EAChC;AACF;AAgBA,MAAM,WAAW,CAAyC;AAAA,EACxD,QAAA;AAAA,EACA,OAAA;AAAA,EACA,iBAAA;AAAA,EACA;AACF,CAA2B,KAAA;AACzB,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAIC,eAA8B,IAAI,CAAA;AACxE,EAAM,MAAA,eAAA,GAAkBC,cAAQ,MAAM;AACpC,IAAA,IAAI,SAAS,eAAiB,EAAA;AAC5B,MAAA,OAAO,OAAQ,CAAA,eAAA;AAAA,KACV,MAAA;AACL,MAAA,OAAO,CAACC,YAAqC,KAAA;AAC3C,QAAA,cAAA,CAAeA,YAAW,CAAA;AAAA,OAC5B;AAAA;AACF,GACF,EAAG,CAAC,OAAO,CAAC,CAAA;AACZ,EAAM,MAAA,YAAA,GAAeD,cAAQ,MAAM;AACjC,IAAI,IAAA,OAAA,EAAS,gBAAgB,WAAa,EAAA;AAExC,MAAO,OAAA,OAAA,CAAQ,YAAa,CAAA,MAAA,CAAO,WAA0B,CAAA;AAAA,eACpD,WAAa,EAAA;AACtB,MAAA,OAAO,CAAC,WAA0B,CAAA;AAAA,KAC7B,MAAA;AACL,MAAO,OAAA,OAAA,EAAS,gBAAgB,EAAC;AAAA;AACnC,GACC,EAAA,CAAC,OAAS,EAAA,WAAW,CAAC,CAAA;AAEzB,EAAA,MAAM,gBAAmB,GAAAE,iBAAA;AAAA,IACvB,CAAC,YAAY,OAAY,KAAA;AACvB,MAAI,IAAA,iBAAA,GAAoB,UAAY,EAAA,OAAO,CAAG,EAAA;AAC5C,QAAO,OAAA,IAAA;AAAA;AAGT,MAAA,IAAI,OAAS,EAAA,iBAAA,GAAoB,UAAY,EAAA,OAAO,CAAG,EAAA;AACrD,QAAO,OAAA,IAAA;AAAA;AACT,KACF;AAAA,IACA,CAAC,SAAS,iBAAiB;AAAA,GAC7B;AAEA,EACE,uBAAAC,eAAA;AAAA,IAAC,kBAAmB,CAAA,QAAA;AAAA,IAAnB;AAAA,MACC,KAAO,EAAA;AAAA,QACL,iBAAmB,EAAA,gBAAA;AAAA,QACnB,YAAA;AAAA,QACA;AAAA,OACF;AAAA,MAEC,QAAA,EAAA;AAAA,QAAA,QAAA;AAAA,QACA;AAAA;AAAA;AAAA,GACH;AAEJ,CAAA;AAEO,MAAM,sBAAsB,CAAyC;AAAA,EAC1E,QAAA;AAAA,EACA,iBAAA;AAAA,EACA;AACF,CAAsC,KAAA;AACpC,EAAA,uBACGC,cAAA,CAAA,kBAAA,CAAmB,QAAnB,EAAA,EACE,WAAC,aACA,qBAAAA,cAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,OAAS,EAAA,aAAA;AAAA,MACT,iBAAA;AAAA,MACA,WAAA;AAAA,MAEC;AAAA;AAAA,GAGP,EAAA,CAAA;AAEJ;;;;;"}
|
package/cjs/menu-utils.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
-
var core = require('@salt-ds/core');
|
|
5
|
-
|
|
6
|
-
const isGroupMenuItemDescriptor = (menuItem) => menuItem !== void 0 && "children" in menuItem;
|
|
7
|
-
const menuItemsFromMenuDescriptors = (menuDescriptors, menuActionHandler) => {
|
|
8
|
-
const fromDescriptor = (menuItem, index) => isGroupMenuItemDescriptor(menuItem) ? /* @__PURE__ */ jsxRuntime.jsxs(core.Menu, { children: [
|
|
9
|
-
/* @__PURE__ */ jsxRuntime.jsx(core.MenuTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx(core.MenuItem, { children: menuItem.label }) }),
|
|
10
|
-
/* @__PURE__ */ jsxRuntime.jsx(core.MenuPanel, { className: "vuuContextMenuPanel", children: menuItem.children.map(fromDescriptor) })
|
|
11
|
-
] }, index) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
12
|
-
core.MenuItem,
|
|
13
|
-
{
|
|
14
|
-
className: menuItem.className,
|
|
15
|
-
"data-icon": menuItem.icon,
|
|
16
|
-
onClick: () => menuActionHandler(menuItem.id, menuItem.options),
|
|
17
|
-
children: menuItem.label
|
|
18
|
-
},
|
|
19
|
-
index
|
|
20
|
-
);
|
|
21
|
-
return menuDescriptors.map(fromDescriptor);
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
exports.isGroupMenuItemDescriptor = isGroupMenuItemDescriptor;
|
|
25
|
-
exports.menuItemsFromMenuDescriptors = menuItemsFromMenuDescriptors;
|
|
26
|
-
//# sourceMappingURL=menu-utils.js.map
|
package/cjs/menu-utils.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"menu-utils.js","sources":["../src/menu-utils.tsx"],"sourcesContent":["import { Menu, MenuItem, MenuPanel, MenuTrigger } from \"@salt-ds/core\";\nimport { MenuActionHandler } from \"./ContextMenuProvider\";\n\nexport interface ContextMenuItemBase {\n className?: string;\n icon?: string;\n label: string;\n location?: string;\n}\n\nexport interface ContextMenuLeafItemDescriptor extends ContextMenuItemBase {\n id: string;\n options?: unknown;\n}\n\nexport interface ContextMenuGroupItemDescriptor extends ContextMenuItemBase {\n children: ContextMenuItemDescriptor[];\n}\n\nexport type ContextMenuItemDescriptor =\n | ContextMenuLeafItemDescriptor\n | ContextMenuGroupItemDescriptor;\n\nexport const isGroupMenuItemDescriptor = (\n menuItem?: ContextMenuItemDescriptor,\n): menuItem is ContextMenuGroupItemDescriptor =>\n menuItem !== undefined && \"children\" in menuItem;\n\nexport const menuItemsFromMenuDescriptors = (\n menuDescriptors: ContextMenuItemDescriptor[],\n menuActionHandler: MenuActionHandler,\n) => {\n const fromDescriptor = (\n menuItem: ContextMenuItemDescriptor,\n index: number,\n ) =>\n isGroupMenuItemDescriptor(menuItem) ? (\n <Menu key={index}>\n <MenuTrigger>\n <MenuItem>{menuItem.label}</MenuItem>\n </MenuTrigger>\n <MenuPanel className=\"vuuContextMenuPanel\">\n {menuItem.children.map(fromDescriptor)}\n </MenuPanel>\n </Menu>\n ) : (\n <MenuItem\n key={index}\n className={menuItem.className}\n data-icon={menuItem.icon}\n onClick={() => menuActionHandler(menuItem.id, menuItem.options)}\n >\n {menuItem.label}\n </MenuItem>\n );\n\n return menuDescriptors.map(fromDescriptor);\n};\n"],"names":["Menu","jsx","MenuTrigger","MenuItem","MenuPanel"],"mappings":";;;;;AAuBO,MAAM,yBAA4B,GAAA,CACvC,QAEA,KAAA,QAAA,KAAa,UAAa,UAAc,IAAA;AAE7B,MAAA,4BAAA,GAA+B,CAC1C,eAAA,EACA,iBACG,KAAA;AACH,EAAM,MAAA,cAAA,GAAiB,CACrB,QACA,EAAA,KAAA,KAEA,0BAA0B,QAAQ,CAAA,mCAC/BA,SACC,EAAA,EAAA,QAAA,EAAA;AAAA,oBAAAC,cAAA,CAACC,gBACC,EAAA,EAAA,QAAA,kBAAAD,cAAA,CAACE,aAAU,EAAA,EAAA,QAAA,EAAA,QAAA,CAAS,OAAM,CAC5B,EAAA,CAAA;AAAA,oBACAF,cAAA,CAACG,kBAAU,SAAU,EAAA,qBAAA,EAClB,mBAAS,QAAS,CAAA,GAAA,CAAI,cAAc,CACvC,EAAA;AAAA,GAAA,EAAA,EANS,KAOX,CAEA,mBAAAH,cAAA;AAAA,IAACE,aAAA;AAAA,IAAA;AAAA,MAEC,WAAW,QAAS,CAAA,SAAA;AAAA,MACpB,aAAW,QAAS,CAAA,IAAA;AAAA,MACpB,SAAS,MAAM,iBAAA,CAAkB,QAAS,CAAA,EAAA,EAAI,SAAS,OAAO,CAAA;AAAA,MAE7D,QAAS,EAAA,QAAA,CAAA;AAAA,KAAA;AAAA,IALL;AAAA,GAMP;AAGJ,EAAO,OAAA,eAAA,CAAgB,IAAI,cAAc,CAAA;AAC3C;;;;;"}
|
package/cjs/useContextMenu.js
DELETED
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
-
var react = require('react');
|
|
5
|
-
var ContextMenu = require('./ContextMenu.js');
|
|
6
|
-
var ContextMenuProvider = require('./ContextMenuProvider.js');
|
|
7
|
-
|
|
8
|
-
const useContextMenu = (menuBuilder, menuActionHandler) => {
|
|
9
|
-
const ctx = react.useContext(ContextMenuProvider.ContextMenuContext);
|
|
10
|
-
const buildMenuOptions = react.useCallback(
|
|
11
|
-
(menuBuilders, location, options) => {
|
|
12
|
-
let results = [];
|
|
13
|
-
for (const menuBuilder2 of menuBuilders) {
|
|
14
|
-
results = results.concat(menuBuilder2(location, options));
|
|
15
|
-
}
|
|
16
|
-
return results;
|
|
17
|
-
},
|
|
18
|
-
[]
|
|
19
|
-
);
|
|
20
|
-
const handleOpenChange = react.useCallback(
|
|
21
|
-
(open) => {
|
|
22
|
-
if (!open) {
|
|
23
|
-
ctx?.showContextMenu(null);
|
|
24
|
-
}
|
|
25
|
-
},
|
|
26
|
-
[ctx]
|
|
27
|
-
);
|
|
28
|
-
const showContextMenu = react.useCallback(
|
|
29
|
-
(evt, location, options, { onOpenChange, x = evt.clientX, y = evt.clientY } = {
|
|
30
|
-
x: evt.clientX,
|
|
31
|
-
y: evt.clientY
|
|
32
|
-
}) => {
|
|
33
|
-
evt.stopPropagation?.();
|
|
34
|
-
evt.preventDefault?.();
|
|
35
|
-
console.log(
|
|
36
|
-
`showContextMenu at ${evt.clientX} ${evt.clientY} location ${location}`
|
|
37
|
-
);
|
|
38
|
-
const menuBuilders = [];
|
|
39
|
-
if (menuBuilder) {
|
|
40
|
-
menuBuilders.push(menuBuilder);
|
|
41
|
-
}
|
|
42
|
-
if (ctx && Array.isArray(ctx?.menuBuilders) && ctx.menuBuilders.length > 0) {
|
|
43
|
-
menuBuilders.push(...ctx.menuBuilders);
|
|
44
|
-
}
|
|
45
|
-
if (menuBuilders.length > 0) {
|
|
46
|
-
const menuItemDescriptors = buildMenuOptions(
|
|
47
|
-
menuBuilders,
|
|
48
|
-
location,
|
|
49
|
-
options
|
|
50
|
-
);
|
|
51
|
-
const menuHandler = (menuItemId, options2) => {
|
|
52
|
-
if (menuActionHandler?.(menuItemId, options2) === true) {
|
|
53
|
-
return true;
|
|
54
|
-
} else {
|
|
55
|
-
return ctx?.menuActionHandler(menuItemId, options2);
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
const localOpenChange = (isOpen) => {
|
|
59
|
-
onOpenChange?.(isOpen);
|
|
60
|
-
handleOpenChange(isOpen);
|
|
61
|
-
};
|
|
62
|
-
if (menuItemDescriptors.length) {
|
|
63
|
-
ctx?.showContextMenu(
|
|
64
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
65
|
-
ContextMenu.ContextMenu,
|
|
66
|
-
{
|
|
67
|
-
menuHandler,
|
|
68
|
-
menuItemDescriptors,
|
|
69
|
-
onOpenChange: localOpenChange,
|
|
70
|
-
open: true,
|
|
71
|
-
x,
|
|
72
|
-
y
|
|
73
|
-
}
|
|
74
|
-
)
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
} else {
|
|
78
|
-
console.warn(
|
|
79
|
-
"useContextMenu, no menuBuilders configured. These should be supplied via the ContextMenuProvider(s)"
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
},
|
|
83
|
-
[buildMenuOptions, ctx, handleOpenChange, menuActionHandler, menuBuilder]
|
|
84
|
-
);
|
|
85
|
-
return showContextMenu;
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
exports.useContextMenu = useContextMenu;
|
|
89
|
-
//# sourceMappingURL=useContextMenu.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useContextMenu.js","sources":["../src/useContextMenu.tsx"],"sourcesContent":["import { useCallback, useContext } from \"react\";\nimport { ContextMenu, ContextMenuProps } from \"./ContextMenu\";\nimport {\n ContextMenuContext,\n MenuActionHandler,\n MenuBuilder,\n} from \"./ContextMenuProvider\";\nimport { ContextMenuItemDescriptor } from \"./menu-utils\";\n\nexport type EventLike = {\n clientX: number;\n clientY: number;\n preventDefault?: () => void;\n stopPropagation?: () => void;\n};\n\nexport type ShowContextMenu = (\n e: EventLike,\n location: string,\n options: unknown,\n contextMenuProps?: Pick<ContextMenuProps, \"onOpenChange\" | \"x\" | \"y\">,\n) => void;\n\n// The argument allows a top-level menuBuilder to operate outside the Context\nexport const useContextMenu = (\n menuBuilder?: MenuBuilder,\n menuActionHandler?: MenuActionHandler,\n): ShowContextMenu => {\n const ctx = useContext(ContextMenuContext);\n\n const buildMenuOptions = useCallback(\n (menuBuilders: MenuBuilder[], location: string, options: unknown) => {\n let results: ContextMenuItemDescriptor[] = [];\n for (const menuBuilder of menuBuilders) {\n // Maybe we should leave the concatenation to the menuBuilder, then it can control menuItem order\n results = results.concat(menuBuilder(location, options));\n }\n return results;\n },\n [],\n );\n\n const handleOpenChange = useCallback(\n (open: boolean) => {\n if (!open) {\n ctx?.showContextMenu(null);\n }\n },\n [ctx],\n );\n\n const showContextMenu = useCallback<ShowContextMenu>(\n (\n evt,\n location,\n options,\n { onOpenChange, x = evt.clientX, y = evt.clientY } = {\n x: evt.clientX,\n y: evt.clientY,\n },\n ) => {\n evt.stopPropagation?.();\n evt.preventDefault?.();\n\n console.log(\n `showContextMenu at ${evt.clientX} ${evt.clientY} location ${location}`,\n );\n\n const menuBuilders: MenuBuilder[] = [];\n if (menuBuilder) {\n menuBuilders.push(menuBuilder);\n }\n if (\n ctx &&\n Array.isArray(ctx?.menuBuilders) &&\n ctx.menuBuilders.length > 0\n ) {\n menuBuilders.push(...ctx.menuBuilders);\n }\n\n if (menuBuilders.length > 0) {\n const menuItemDescriptors = buildMenuOptions(\n menuBuilders,\n location,\n options,\n );\n\n const menuHandler: MenuActionHandler = (menuItemId, options) => {\n if (menuActionHandler?.(menuItemId, options) === true) {\n return true;\n } else {\n return ctx?.menuActionHandler(menuItemId, options);\n }\n };\n\n const localOpenChange = (isOpen: boolean) => {\n onOpenChange?.(isOpen);\n handleOpenChange(isOpen);\n };\n\n if (menuItemDescriptors.length) {\n ctx?.showContextMenu(\n <ContextMenu\n menuHandler={menuHandler}\n menuItemDescriptors={menuItemDescriptors}\n onOpenChange={localOpenChange}\n open={true}\n x={x}\n y={y}\n />,\n );\n }\n } else {\n console.warn(\n \"useContextMenu, no menuBuilders configured. These should be supplied via the ContextMenuProvider(s)\",\n );\n }\n },\n [buildMenuOptions, ctx, handleOpenChange, menuActionHandler, menuBuilder],\n );\n\n return showContextMenu;\n};\n"],"names":["useContext","ContextMenuContext","useCallback","menuBuilder","options","jsx","ContextMenu"],"mappings":"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"}
|
package/esm/ContextMenu.css.js
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
var contextMenuCss = ".vuuContextMenuPanel {\n &:has([data-icon]) {\n .saltMenuItem {\n padding-left: calc(var(--salt-spacing-400) + var(--salt-spacing-200));\n }\n .saltMenuItem[data-icon]:after {\n --vuu-icon-left: var(--salt-spacing-150);\n --vuu-icon-top: var(--salt-spacing-150);\n }\n .saltMenuItem[aria-haspopup=\"menu\"]:after {\n content: \"\";\n background-color: var(--vuu-icon-color, var(--saltIcon-color, var(--salt-content-secondary-foreground)));\n right: var(--salt-spacing-100);\n height: var(--vuu-icon-height, var(--vuu-icon-size, 12px));\n mask: var(--vuu-svg-triangle-right) center center / 8px 8px;\n mask-repeat: no-repeat;\n position: absolute;\n transform: rotate(315deg);\n top: var(--salt-spacing-200);\n width: var(--vuu-icon-width, var(--vuu-icon-size, 12px));\n }\n }\n}";
|
|
2
|
-
|
|
3
|
-
export { contextMenuCss as default };
|
|
4
|
-
//# sourceMappingURL=ContextMenu.css.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ContextMenu.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
|
package/esm/ContextMenu.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
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 contextMenuCss from './ContextMenu.css.js';
|
|
7
|
-
|
|
8
|
-
const ContextMenu = ({
|
|
9
|
-
menuHandler,
|
|
10
|
-
menuItemDescriptors,
|
|
11
|
-
onOpenChange,
|
|
12
|
-
open,
|
|
13
|
-
x,
|
|
14
|
-
y
|
|
15
|
-
}) => {
|
|
16
|
-
const targetWindow = useWindow();
|
|
17
|
-
useComponentCssInjection({
|
|
18
|
-
testId: "vuu-context-menu",
|
|
19
|
-
css: contextMenuCss,
|
|
20
|
-
window: targetWindow
|
|
21
|
-
});
|
|
22
|
-
const virtualElement = {
|
|
23
|
-
getBoundingClientRect: () => ({
|
|
24
|
-
width: 0,
|
|
25
|
-
height: 0,
|
|
26
|
-
x,
|
|
27
|
-
y,
|
|
28
|
-
top: y,
|
|
29
|
-
right: x,
|
|
30
|
-
bottom: y,
|
|
31
|
-
left: x
|
|
32
|
-
})
|
|
33
|
-
};
|
|
34
|
-
return /* @__PURE__ */ jsx(
|
|
35
|
-
Menu,
|
|
36
|
-
{
|
|
37
|
-
getVirtualElement: () => virtualElement,
|
|
38
|
-
onOpenChange,
|
|
39
|
-
open,
|
|
40
|
-
children: /* @__PURE__ */ jsx(MenuPanel, { className: "vuuContextMenuPanel", children: menuItemsFromMenuDescriptors(menuItemDescriptors, menuHandler) })
|
|
41
|
-
}
|
|
42
|
-
);
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export { ContextMenu };
|
|
46
|
-
//# sourceMappingURL=ContextMenu.js.map
|
package/esm/ContextMenu.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ContextMenu.js","sources":["../src/ContextMenu.tsx"],"sourcesContent":["import { VirtualElement } from \"@floating-ui/dom\";\nimport { Menu, MenuPanel, MenuProps } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { MenuActionHandler } from \"./ContextMenuProvider\";\nimport {\n ContextMenuItemDescriptor,\n menuItemsFromMenuDescriptors,\n} from \"./menu-utils\";\n\nimport contextMenuCss from \"./ContextMenu.css\";\n\nexport interface ContextMenuProps\n extends Pick<MenuProps, \"open\" | \"onOpenChange\"> {\n menuHandler: MenuActionHandler;\n menuItemDescriptors: ContextMenuItemDescriptor[];\n x: number;\n y: number;\n}\n\nexport const ContextMenu = ({\n menuHandler,\n menuItemDescriptors,\n onOpenChange,\n open,\n x,\n y,\n}: ContextMenuProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"vuu-context-menu\",\n css: contextMenuCss,\n window: targetWindow,\n });\n\n const virtualElement: VirtualElement = {\n getBoundingClientRect: () => ({\n width: 0,\n height: 0,\n x,\n y,\n top: y,\n right: x,\n bottom: y,\n left: x,\n }),\n };\n\n return (\n <Menu\n getVirtualElement={() => virtualElement}\n onOpenChange={onOpenChange}\n open={open}\n >\n <MenuPanel className=\"vuuContextMenuPanel\">\n {menuItemsFromMenuDescriptors(menuItemDescriptors, menuHandler)}\n </MenuPanel>\n </Menu>\n );\n};\n"],"names":[],"mappings":";;;;;;;AAoBO,MAAM,cAAc,CAAC;AAAA,EAC1B,WAAA;AAAA,EACA,mBAAA;AAAA,EACA,YAAA;AAAA,EACA,IAAA;AAAA,EACA,CAAA;AAAA,EACA;AACF,CAAwB,KAAA;AACtB,EAAA,MAAM,eAAe,SAAU,EAAA;AAC/B,EAAyB,wBAAA,CAAA;AAAA,IACvB,MAAQ,EAAA,kBAAA;AAAA,IACR,GAAK,EAAA,cAAA;AAAA,IACL,MAAQ,EAAA;AAAA,GACT,CAAA;AAED,EAAA,MAAM,cAAiC,GAAA;AAAA,IACrC,uBAAuB,OAAO;AAAA,MAC5B,KAAO,EAAA,CAAA;AAAA,MACP,MAAQ,EAAA,CAAA;AAAA,MACR,CAAA;AAAA,MACA,CAAA;AAAA,MACA,GAAK,EAAA,CAAA;AAAA,MACL,KAAO,EAAA,CAAA;AAAA,MACP,MAAQ,EAAA,CAAA;AAAA,MACR,IAAM,EAAA;AAAA,KACR;AAAA,GACF;AAEA,EACE,uBAAA,GAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACC,mBAAmB,MAAM,cAAA;AAAA,MACzB,YAAA;AAAA,MACA,IAAA;AAAA,MAEA,8BAAC,SAAU,EAAA,EAAA,SAAA,EAAU,uBAClB,QAA6B,EAAA,4BAAA,CAAA,mBAAA,EAAqB,WAAW,CAChE,EAAA;AAAA;AAAA,GACF;AAEJ;;;;"}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
-
import { createContext, useState, useMemo, useCallback } from 'react';
|
|
3
|
-
|
|
4
|
-
const ContextMenuContext = createContext(
|
|
5
|
-
null
|
|
6
|
-
);
|
|
7
|
-
const Provider = ({
|
|
8
|
-
children,
|
|
9
|
-
context,
|
|
10
|
-
menuActionHandler,
|
|
11
|
-
menuBuilder
|
|
12
|
-
}) => {
|
|
13
|
-
const [contextMenu, setContextMenu] = useState(null);
|
|
14
|
-
const showContextMenu = useMemo(() => {
|
|
15
|
-
if (context?.showContextMenu) {
|
|
16
|
-
return context.showContextMenu;
|
|
17
|
-
} else {
|
|
18
|
-
return (contextMenu2) => {
|
|
19
|
-
setContextMenu(contextMenu2);
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
}, [context]);
|
|
23
|
-
const menuBuilders = useMemo(() => {
|
|
24
|
-
if (context?.menuBuilders && menuBuilder) {
|
|
25
|
-
return context.menuBuilders.concat(menuBuilder);
|
|
26
|
-
} else if (menuBuilder) {
|
|
27
|
-
return [menuBuilder];
|
|
28
|
-
} else {
|
|
29
|
-
return context?.menuBuilders || [];
|
|
30
|
-
}
|
|
31
|
-
}, [context, menuBuilder]);
|
|
32
|
-
const handleMenuAction = useCallback(
|
|
33
|
-
(menuItemId, options) => {
|
|
34
|
-
if (menuActionHandler?.(menuItemId, options)) {
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
37
|
-
if (context?.menuActionHandler?.(menuItemId, options)) {
|
|
38
|
-
return true;
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
[context, menuActionHandler]
|
|
42
|
-
);
|
|
43
|
-
return /* @__PURE__ */ jsxs(
|
|
44
|
-
ContextMenuContext.Provider,
|
|
45
|
-
{
|
|
46
|
-
value: {
|
|
47
|
-
menuActionHandler: handleMenuAction,
|
|
48
|
-
menuBuilders,
|
|
49
|
-
showContextMenu
|
|
50
|
-
},
|
|
51
|
-
children: [
|
|
52
|
-
children,
|
|
53
|
-
contextMenu
|
|
54
|
-
]
|
|
55
|
-
}
|
|
56
|
-
);
|
|
57
|
-
};
|
|
58
|
-
const ContextMenuProvider = ({
|
|
59
|
-
children,
|
|
60
|
-
menuActionHandler,
|
|
61
|
-
menuBuilder
|
|
62
|
-
}) => {
|
|
63
|
-
return /* @__PURE__ */ jsx(ContextMenuContext.Consumer, { children: (parentContext) => /* @__PURE__ */ jsx(
|
|
64
|
-
Provider,
|
|
65
|
-
{
|
|
66
|
-
context: parentContext,
|
|
67
|
-
menuActionHandler,
|
|
68
|
-
menuBuilder,
|
|
69
|
-
children
|
|
70
|
-
}
|
|
71
|
-
) });
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
export { ContextMenuContext, ContextMenuProvider };
|
|
75
|
-
//# sourceMappingURL=ContextMenuProvider.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ContextMenuProvider.js","sources":["../src/ContextMenuProvider.tsx"],"sourcesContent":["import {\n createContext,\n ReactElement,\n ReactNode,\n useCallback,\n useMemo,\n useState,\n} from \"react\";\n\nimport { ContextMenuItemDescriptor } from \"./menu-utils\";\n\nexport type MenuActionHandler<T extends string = string, Options = unknown> = (\n menuItemId: T,\n options?: Options,\n) => boolean | undefined;\n\nexport type MenuBuilder<Location extends string = string, Options = unknown> = (\n location: Location,\n options: Options,\n) => ContextMenuItemDescriptor[];\n\nexport interface ContextMenuContextType {\n menuBuilders: MenuBuilder[];\n menuActionHandler: MenuActionHandler;\n showContextMenu: (contextMenu: ReactElement | null) => void;\n}\n\nexport const ContextMenuContext = createContext<ContextMenuContextType | null>(\n null,\n);\n\nexport interface ContextMenuProviderProps<\n L extends string = string,\n O = unknown,\n> {\n children: ReactNode;\n menuActionHandler?: MenuActionHandler;\n menuBuilder?: MenuBuilder<L, O>;\n}\n\ninterface ProviderProps<L extends string = string, O = unknown>\n extends ContextMenuProviderProps<L, O> {\n context: ContextMenuContextType | null;\n}\n\nconst Provider = <L extends string = string, O = unknown>({\n children,\n context,\n menuActionHandler,\n menuBuilder,\n}: ProviderProps<L, O>) => {\n const [contextMenu, setContextMenu] = useState<ReactElement | null>(null);\n const showContextMenu = useMemo(() => {\n if (context?.showContextMenu) {\n return context.showContextMenu;\n } else {\n return (contextMenu: ReactElement | null) => {\n setContextMenu(contextMenu);\n };\n }\n }, [context]);\n const menuBuilders = useMemo(() => {\n if (context?.menuBuilders && menuBuilder) {\n // menuBuilder may have a narrower type than the inherited menuBuilders, discard this\n return context.menuBuilders.concat(menuBuilder as MenuBuilder);\n } else if (menuBuilder) {\n return [menuBuilder as MenuBuilder];\n } else {\n return context?.menuBuilders || [];\n }\n }, [context, menuBuilder]);\n\n const handleMenuAction = useCallback<MenuActionHandler>(\n (menuItemId, options) => {\n if (menuActionHandler?.(menuItemId, options)) {\n return true;\n }\n\n if (context?.menuActionHandler?.(menuItemId, options)) {\n return true;\n }\n },\n [context, menuActionHandler],\n );\n\n return (\n <ContextMenuContext.Provider\n value={{\n menuActionHandler: handleMenuAction,\n menuBuilders,\n showContextMenu,\n }}\n >\n {children}\n {contextMenu}\n </ContextMenuContext.Provider>\n );\n};\n\nexport const ContextMenuProvider = <L extends string = string, O = unknown>({\n children,\n menuActionHandler,\n menuBuilder,\n}: ContextMenuProviderProps<L, O>) => {\n return (\n <ContextMenuContext.Consumer>\n {(parentContext) => (\n <Provider<L, O>\n context={parentContext}\n menuActionHandler={menuActionHandler}\n menuBuilder={menuBuilder}\n >\n {children}\n </Provider>\n )}\n </ContextMenuContext.Consumer>\n );\n};\n"],"names":["contextMenu"],"mappings":";;;AA2BO,MAAM,kBAAqB,GAAA,aAAA;AAAA,EAChC;AACF;AAgBA,MAAM,WAAW,CAAyC;AAAA,EACxD,QAAA;AAAA,EACA,OAAA;AAAA,EACA,iBAAA;AAAA,EACA;AACF,CAA2B,KAAA;AACzB,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAI,SAA8B,IAAI,CAAA;AACxE,EAAM,MAAA,eAAA,GAAkB,QAAQ,MAAM;AACpC,IAAA,IAAI,SAAS,eAAiB,EAAA;AAC5B,MAAA,OAAO,OAAQ,CAAA,eAAA;AAAA,KACV,MAAA;AACL,MAAA,OAAO,CAACA,YAAqC,KAAA;AAC3C,QAAA,cAAA,CAAeA,YAAW,CAAA;AAAA,OAC5B;AAAA;AACF,GACF,EAAG,CAAC,OAAO,CAAC,CAAA;AACZ,EAAM,MAAA,YAAA,GAAe,QAAQ,MAAM;AACjC,IAAI,IAAA,OAAA,EAAS,gBAAgB,WAAa,EAAA;AAExC,MAAO,OAAA,OAAA,CAAQ,YAAa,CAAA,MAAA,CAAO,WAA0B,CAAA;AAAA,eACpD,WAAa,EAAA;AACtB,MAAA,OAAO,CAAC,WAA0B,CAAA;AAAA,KAC7B,MAAA;AACL,MAAO,OAAA,OAAA,EAAS,gBAAgB,EAAC;AAAA;AACnC,GACC,EAAA,CAAC,OAAS,EAAA,WAAW,CAAC,CAAA;AAEzB,EAAA,MAAM,gBAAmB,GAAA,WAAA;AAAA,IACvB,CAAC,YAAY,OAAY,KAAA;AACvB,MAAI,IAAA,iBAAA,GAAoB,UAAY,EAAA,OAAO,CAAG,EAAA;AAC5C,QAAO,OAAA,IAAA;AAAA;AAGT,MAAA,IAAI,OAAS,EAAA,iBAAA,GAAoB,UAAY,EAAA,OAAO,CAAG,EAAA;AACrD,QAAO,OAAA,IAAA;AAAA;AACT,KACF;AAAA,IACA,CAAC,SAAS,iBAAiB;AAAA,GAC7B;AAEA,EACE,uBAAA,IAAA;AAAA,IAAC,kBAAmB,CAAA,QAAA;AAAA,IAAnB;AAAA,MACC,KAAO,EAAA;AAAA,QACL,iBAAmB,EAAA,gBAAA;AAAA,QACnB,YAAA;AAAA,QACA;AAAA,OACF;AAAA,MAEC,QAAA,EAAA;AAAA,QAAA,QAAA;AAAA,QACA;AAAA;AAAA;AAAA,GACH;AAEJ,CAAA;AAEO,MAAM,sBAAsB,CAAyC;AAAA,EAC1E,QAAA;AAAA,EACA,iBAAA;AAAA,EACA;AACF,CAAsC,KAAA;AACpC,EAAA,uBACG,GAAA,CAAA,kBAAA,CAAmB,QAAnB,EAAA,EACE,WAAC,aACA,qBAAA,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,OAAS,EAAA,aAAA;AAAA,MACT,iBAAA;AAAA,MACA,WAAA;AAAA,MAEC;AAAA;AAAA,GAGP,EAAA,CAAA;AAEJ;;;;"}
|
package/esm/menu-utils.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { Menu, MenuTrigger, MenuItem, MenuPanel } from '@salt-ds/core';
|
|
3
|
-
|
|
4
|
-
const isGroupMenuItemDescriptor = (menuItem) => menuItem !== void 0 && "children" in menuItem;
|
|
5
|
-
const menuItemsFromMenuDescriptors = (menuDescriptors, menuActionHandler) => {
|
|
6
|
-
const fromDescriptor = (menuItem, index) => isGroupMenuItemDescriptor(menuItem) ? /* @__PURE__ */ jsxs(Menu, { children: [
|
|
7
|
-
/* @__PURE__ */ jsx(MenuTrigger, { children: /* @__PURE__ */ jsx(MenuItem, { children: menuItem.label }) }),
|
|
8
|
-
/* @__PURE__ */ jsx(MenuPanel, { className: "vuuContextMenuPanel", children: menuItem.children.map(fromDescriptor) })
|
|
9
|
-
] }, index) : /* @__PURE__ */ jsx(
|
|
10
|
-
MenuItem,
|
|
11
|
-
{
|
|
12
|
-
className: menuItem.className,
|
|
13
|
-
"data-icon": menuItem.icon,
|
|
14
|
-
onClick: () => menuActionHandler(menuItem.id, menuItem.options),
|
|
15
|
-
children: menuItem.label
|
|
16
|
-
},
|
|
17
|
-
index
|
|
18
|
-
);
|
|
19
|
-
return menuDescriptors.map(fromDescriptor);
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export { isGroupMenuItemDescriptor, menuItemsFromMenuDescriptors };
|
|
23
|
-
//# sourceMappingURL=menu-utils.js.map
|
package/esm/menu-utils.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"menu-utils.js","sources":["../src/menu-utils.tsx"],"sourcesContent":["import { Menu, MenuItem, MenuPanel, MenuTrigger } from \"@salt-ds/core\";\nimport { MenuActionHandler } from \"./ContextMenuProvider\";\n\nexport interface ContextMenuItemBase {\n className?: string;\n icon?: string;\n label: string;\n location?: string;\n}\n\nexport interface ContextMenuLeafItemDescriptor extends ContextMenuItemBase {\n id: string;\n options?: unknown;\n}\n\nexport interface ContextMenuGroupItemDescriptor extends ContextMenuItemBase {\n children: ContextMenuItemDescriptor[];\n}\n\nexport type ContextMenuItemDescriptor =\n | ContextMenuLeafItemDescriptor\n | ContextMenuGroupItemDescriptor;\n\nexport const isGroupMenuItemDescriptor = (\n menuItem?: ContextMenuItemDescriptor,\n): menuItem is ContextMenuGroupItemDescriptor =>\n menuItem !== undefined && \"children\" in menuItem;\n\nexport const menuItemsFromMenuDescriptors = (\n menuDescriptors: ContextMenuItemDescriptor[],\n menuActionHandler: MenuActionHandler,\n) => {\n const fromDescriptor = (\n menuItem: ContextMenuItemDescriptor,\n index: number,\n ) =>\n isGroupMenuItemDescriptor(menuItem) ? (\n <Menu key={index}>\n <MenuTrigger>\n <MenuItem>{menuItem.label}</MenuItem>\n </MenuTrigger>\n <MenuPanel className=\"vuuContextMenuPanel\">\n {menuItem.children.map(fromDescriptor)}\n </MenuPanel>\n </Menu>\n ) : (\n <MenuItem\n key={index}\n className={menuItem.className}\n data-icon={menuItem.icon}\n onClick={() => menuActionHandler(menuItem.id, menuItem.options)}\n >\n {menuItem.label}\n </MenuItem>\n );\n\n return menuDescriptors.map(fromDescriptor);\n};\n"],"names":[],"mappings":";;;AAuBO,MAAM,yBAA4B,GAAA,CACvC,QAEA,KAAA,QAAA,KAAa,UAAa,UAAc,IAAA;AAE7B,MAAA,4BAAA,GAA+B,CAC1C,eAAA,EACA,iBACG,KAAA;AACH,EAAM,MAAA,cAAA,GAAiB,CACrB,QACA,EAAA,KAAA,KAEA,0BAA0B,QAAQ,CAAA,wBAC/B,IACC,EAAA,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,WACC,EAAA,EAAA,QAAA,kBAAA,GAAA,CAAC,QAAU,EAAA,EAAA,QAAA,EAAA,QAAA,CAAS,OAAM,CAC5B,EAAA,CAAA;AAAA,oBACA,GAAA,CAAC,aAAU,SAAU,EAAA,qBAAA,EAClB,mBAAS,QAAS,CAAA,GAAA,CAAI,cAAc,CACvC,EAAA;AAAA,GAAA,EAAA,EANS,KAOX,CAEA,mBAAA,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MAEC,WAAW,QAAS,CAAA,SAAA;AAAA,MACpB,aAAW,QAAS,CAAA,IAAA;AAAA,MACpB,SAAS,MAAM,iBAAA,CAAkB,QAAS,CAAA,EAAA,EAAI,SAAS,OAAO,CAAA;AAAA,MAE7D,QAAS,EAAA,QAAA,CAAA;AAAA,KAAA;AAAA,IALL;AAAA,GAMP;AAGJ,EAAO,OAAA,eAAA,CAAgB,IAAI,cAAc,CAAA;AAC3C;;;;"}
|
package/esm/useContextMenu.js
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { useContext, useCallback } from 'react';
|
|
3
|
-
import { ContextMenu } from './ContextMenu.js';
|
|
4
|
-
import { ContextMenuContext } from './ContextMenuProvider.js';
|
|
5
|
-
|
|
6
|
-
const useContextMenu = (menuBuilder, menuActionHandler) => {
|
|
7
|
-
const ctx = useContext(ContextMenuContext);
|
|
8
|
-
const buildMenuOptions = useCallback(
|
|
9
|
-
(menuBuilders, location, options) => {
|
|
10
|
-
let results = [];
|
|
11
|
-
for (const menuBuilder2 of menuBuilders) {
|
|
12
|
-
results = results.concat(menuBuilder2(location, options));
|
|
13
|
-
}
|
|
14
|
-
return results;
|
|
15
|
-
},
|
|
16
|
-
[]
|
|
17
|
-
);
|
|
18
|
-
const handleOpenChange = useCallback(
|
|
19
|
-
(open) => {
|
|
20
|
-
if (!open) {
|
|
21
|
-
ctx?.showContextMenu(null);
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
[ctx]
|
|
25
|
-
);
|
|
26
|
-
const showContextMenu = useCallback(
|
|
27
|
-
(evt, location, options, { onOpenChange, x = evt.clientX, y = evt.clientY } = {
|
|
28
|
-
x: evt.clientX,
|
|
29
|
-
y: evt.clientY
|
|
30
|
-
}) => {
|
|
31
|
-
evt.stopPropagation?.();
|
|
32
|
-
evt.preventDefault?.();
|
|
33
|
-
console.log(
|
|
34
|
-
`showContextMenu at ${evt.clientX} ${evt.clientY} location ${location}`
|
|
35
|
-
);
|
|
36
|
-
const menuBuilders = [];
|
|
37
|
-
if (menuBuilder) {
|
|
38
|
-
menuBuilders.push(menuBuilder);
|
|
39
|
-
}
|
|
40
|
-
if (ctx && Array.isArray(ctx?.menuBuilders) && ctx.menuBuilders.length > 0) {
|
|
41
|
-
menuBuilders.push(...ctx.menuBuilders);
|
|
42
|
-
}
|
|
43
|
-
if (menuBuilders.length > 0) {
|
|
44
|
-
const menuItemDescriptors = buildMenuOptions(
|
|
45
|
-
menuBuilders,
|
|
46
|
-
location,
|
|
47
|
-
options
|
|
48
|
-
);
|
|
49
|
-
const menuHandler = (menuItemId, options2) => {
|
|
50
|
-
if (menuActionHandler?.(menuItemId, options2) === true) {
|
|
51
|
-
return true;
|
|
52
|
-
} else {
|
|
53
|
-
return ctx?.menuActionHandler(menuItemId, options2);
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
const localOpenChange = (isOpen) => {
|
|
57
|
-
onOpenChange?.(isOpen);
|
|
58
|
-
handleOpenChange(isOpen);
|
|
59
|
-
};
|
|
60
|
-
if (menuItemDescriptors.length) {
|
|
61
|
-
ctx?.showContextMenu(
|
|
62
|
-
/* @__PURE__ */ jsx(
|
|
63
|
-
ContextMenu,
|
|
64
|
-
{
|
|
65
|
-
menuHandler,
|
|
66
|
-
menuItemDescriptors,
|
|
67
|
-
onOpenChange: localOpenChange,
|
|
68
|
-
open: true,
|
|
69
|
-
x,
|
|
70
|
-
y
|
|
71
|
-
}
|
|
72
|
-
)
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
} else {
|
|
76
|
-
console.warn(
|
|
77
|
-
"useContextMenu, no menuBuilders configured. These should be supplied via the ContextMenuProvider(s)"
|
|
78
|
-
);
|
|
79
|
-
}
|
|
80
|
-
},
|
|
81
|
-
[buildMenuOptions, ctx, handleOpenChange, menuActionHandler, menuBuilder]
|
|
82
|
-
);
|
|
83
|
-
return showContextMenu;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
export { useContextMenu };
|
|
87
|
-
//# sourceMappingURL=useContextMenu.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useContextMenu.js","sources":["../src/useContextMenu.tsx"],"sourcesContent":["import { useCallback, useContext } from \"react\";\nimport { ContextMenu, ContextMenuProps } from \"./ContextMenu\";\nimport {\n ContextMenuContext,\n MenuActionHandler,\n MenuBuilder,\n} from \"./ContextMenuProvider\";\nimport { ContextMenuItemDescriptor } from \"./menu-utils\";\n\nexport type EventLike = {\n clientX: number;\n clientY: number;\n preventDefault?: () => void;\n stopPropagation?: () => void;\n};\n\nexport type ShowContextMenu = (\n e: EventLike,\n location: string,\n options: unknown,\n contextMenuProps?: Pick<ContextMenuProps, \"onOpenChange\" | \"x\" | \"y\">,\n) => void;\n\n// The argument allows a top-level menuBuilder to operate outside the Context\nexport const useContextMenu = (\n menuBuilder?: MenuBuilder,\n menuActionHandler?: MenuActionHandler,\n): ShowContextMenu => {\n const ctx = useContext(ContextMenuContext);\n\n const buildMenuOptions = useCallback(\n (menuBuilders: MenuBuilder[], location: string, options: unknown) => {\n let results: ContextMenuItemDescriptor[] = [];\n for (const menuBuilder of menuBuilders) {\n // Maybe we should leave the concatenation to the menuBuilder, then it can control menuItem order\n results = results.concat(menuBuilder(location, options));\n }\n return results;\n },\n [],\n );\n\n const handleOpenChange = useCallback(\n (open: boolean) => {\n if (!open) {\n ctx?.showContextMenu(null);\n }\n },\n [ctx],\n );\n\n const showContextMenu = useCallback<ShowContextMenu>(\n (\n evt,\n location,\n options,\n { onOpenChange, x = evt.clientX, y = evt.clientY } = {\n x: evt.clientX,\n y: evt.clientY,\n },\n ) => {\n evt.stopPropagation?.();\n evt.preventDefault?.();\n\n console.log(\n `showContextMenu at ${evt.clientX} ${evt.clientY} location ${location}`,\n );\n\n const menuBuilders: MenuBuilder[] = [];\n if (menuBuilder) {\n menuBuilders.push(menuBuilder);\n }\n if (\n ctx &&\n Array.isArray(ctx?.menuBuilders) &&\n ctx.menuBuilders.length > 0\n ) {\n menuBuilders.push(...ctx.menuBuilders);\n }\n\n if (menuBuilders.length > 0) {\n const menuItemDescriptors = buildMenuOptions(\n menuBuilders,\n location,\n options,\n );\n\n const menuHandler: MenuActionHandler = (menuItemId, options) => {\n if (menuActionHandler?.(menuItemId, options) === true) {\n return true;\n } else {\n return ctx?.menuActionHandler(menuItemId, options);\n }\n };\n\n const localOpenChange = (isOpen: boolean) => {\n onOpenChange?.(isOpen);\n handleOpenChange(isOpen);\n };\n\n if (menuItemDescriptors.length) {\n ctx?.showContextMenu(\n <ContextMenu\n menuHandler={menuHandler}\n menuItemDescriptors={menuItemDescriptors}\n onOpenChange={localOpenChange}\n open={true}\n x={x}\n y={y}\n />,\n );\n }\n } else {\n console.warn(\n \"useContextMenu, no menuBuilders configured. These should be supplied via the ContextMenuProvider(s)\",\n );\n }\n },\n [buildMenuOptions, ctx, handleOpenChange, menuActionHandler, menuBuilder],\n );\n\n return showContextMenu;\n};\n"],"names":["menuBuilder","options"],"mappings":"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"}
|