@vuu-ui/vuu-popups 0.8.17-debug → 0.8.18-debug
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 +1294 -1239
- package/cjs/index.js.map +4 -4
- package/esm/index.js +1318 -1260
- package/esm/index.js.map +4 -4
- package/index.css +41 -38
- package/index.css.map +3 -3
- package/package.json +8 -11
- package/types/dialog/Dialog.d.ts +4 -2
- package/types/menu/ContextMenu.d.ts +2 -2
- package/types/popup/Popup.d.ts +1 -1
- package/types/popup-menu/PopupMenu.d.ts +2 -2
- package/types/portal/Portal.d.ts +5 -3
package/cjs/index.js
CHANGED
|
@@ -42,7 +42,7 @@ __export(src_exports, {
|
|
|
42
42
|
NotificationLevel: () => NotificationLevel,
|
|
43
43
|
NotificationsContext: () => NotificationsContext,
|
|
44
44
|
NotificationsProvider: () => NotificationsProvider,
|
|
45
|
-
PopupComponent: () =>
|
|
45
|
+
PopupComponent: () => PopupComponent2,
|
|
46
46
|
PopupMenu: () => PopupMenu,
|
|
47
47
|
PopupService: () => PopupService,
|
|
48
48
|
Portal: () => Portal,
|
|
@@ -64,61 +64,13 @@ __export(src_exports, {
|
|
|
64
64
|
module.exports = __toCommonJS(src_exports);
|
|
65
65
|
|
|
66
66
|
// src/dialog/Dialog.tsx
|
|
67
|
-
var
|
|
68
|
-
var
|
|
69
|
-
var
|
|
70
|
-
|
|
71
|
-
// src/portal/Portal.tsx
|
|
72
|
-
var import_vuu_shell = require("@vuu-ui/vuu-shell");
|
|
73
|
-
var import_react = require("react");
|
|
74
|
-
var import_react_dom = require("react-dom");
|
|
75
|
-
function getContainer(container) {
|
|
76
|
-
return typeof container === "function" ? container() : container;
|
|
77
|
-
}
|
|
78
|
-
var DEFAULT_ID = "vuu-portal-root";
|
|
79
|
-
var Portal = ({
|
|
80
|
-
children,
|
|
81
|
-
container: containerProp = document.body,
|
|
82
|
-
id = DEFAULT_ID,
|
|
83
|
-
onRender,
|
|
84
|
-
open = true,
|
|
85
|
-
themeAttributes
|
|
86
|
-
}) => {
|
|
87
|
-
var _a;
|
|
88
|
-
const [mounted, setMounted] = (0, import_react.useState)(false);
|
|
89
|
-
const portalRef = (0, import_react.useRef)(null);
|
|
90
|
-
const container = (_a = getContainer(containerProp)) != null ? _a : document.body;
|
|
91
|
-
const [themeClass, densityClass, dataMode] = (0, import_vuu_shell.useThemeAttributes)(themeAttributes);
|
|
92
|
-
(0, import_react.useLayoutEffect)(() => {
|
|
93
|
-
const root = document.getElementById(id);
|
|
94
|
-
if (root) {
|
|
95
|
-
portalRef.current = root;
|
|
96
|
-
} else {
|
|
97
|
-
portalRef.current = document.createElement("div");
|
|
98
|
-
portalRef.current.id = id;
|
|
99
|
-
}
|
|
100
|
-
const el = portalRef.current;
|
|
101
|
-
if (!container.contains(el)) {
|
|
102
|
-
container.appendChild(el);
|
|
103
|
-
}
|
|
104
|
-
el.classList.add(themeClass, densityClass);
|
|
105
|
-
el.dataset.mode = dataMode;
|
|
106
|
-
setMounted(true);
|
|
107
|
-
}, [id, container, themeClass, densityClass, dataMode]);
|
|
108
|
-
(0, import_react.useLayoutEffect)(() => {
|
|
109
|
-
requestAnimationFrame(() => {
|
|
110
|
-
onRender == null ? void 0 : onRender();
|
|
111
|
-
});
|
|
112
|
-
}, [onRender]);
|
|
113
|
-
if (open && mounted && portalRef.current && children) {
|
|
114
|
-
return (0, import_react_dom.createPortal)(children, portalRef.current);
|
|
115
|
-
}
|
|
116
|
-
return null;
|
|
117
|
-
};
|
|
67
|
+
var import_clsx5 = __toESM(require("clsx"));
|
|
68
|
+
var import_vuu_utils = require("@vuu-ui/vuu-utils");
|
|
69
|
+
var import_react3 = require("react");
|
|
118
70
|
|
|
119
71
|
// src/dialog-header/DialogHeader.tsx
|
|
120
72
|
var import_core = require("@salt-ds/core");
|
|
121
|
-
var
|
|
73
|
+
var import_clsx = __toESM(require("clsx"));
|
|
122
74
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
123
75
|
var classBase = "vuuDialogHeader";
|
|
124
76
|
var DialogHeader = ({
|
|
@@ -127,7 +79,7 @@ var DialogHeader = ({
|
|
|
127
79
|
onClose,
|
|
128
80
|
...htmlAttributes
|
|
129
81
|
}) => {
|
|
130
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ...htmlAttributes, className: (0,
|
|
82
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ...htmlAttributes, className: (0, import_clsx.default)(classBase, "vuuToolbarProxy"), children: [
|
|
131
83
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Text, { className: "dialogHeader", children: title }),
|
|
132
84
|
!hideCloseButton && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
133
85
|
import_core.Button,
|
|
@@ -142,1286 +94,1389 @@ var DialogHeader = ({
|
|
|
142
94
|
] });
|
|
143
95
|
};
|
|
144
96
|
|
|
145
|
-
// src/
|
|
146
|
-
var
|
|
147
|
-
var
|
|
148
|
-
var
|
|
149
|
-
|
|
97
|
+
// src/popup/popup-service.ts
|
|
98
|
+
var import_clsx3 = __toESM(require("clsx"));
|
|
99
|
+
var import_react = __toESM(require("react"));
|
|
100
|
+
var import_react_dom = __toESM(require("react-dom"));
|
|
101
|
+
|
|
102
|
+
// src/portal-deprecated/render-portal.tsx
|
|
103
|
+
var ReactDOM = __toESM(require("react-dom"));
|
|
104
|
+
var import_clsx2 = __toESM(require("clsx"));
|
|
105
|
+
var containerId = 1;
|
|
106
|
+
var getPortalContainer = ({
|
|
150
107
|
className,
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
...props
|
|
108
|
+
dataMode,
|
|
109
|
+
x = 0,
|
|
110
|
+
y = 0,
|
|
111
|
+
win = window
|
|
156
112
|
}) => {
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
return null;
|
|
113
|
+
const el = win.document.createElement("div");
|
|
114
|
+
el.className = (0, import_clsx2.default)(`vuuPopup ${containerId++}`, className);
|
|
115
|
+
el.style.cssText = `left:${x}px; top:${y}px;`;
|
|
116
|
+
if (dataMode) {
|
|
117
|
+
el.dataset.mode = dataMode;
|
|
163
118
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
DialogHeader,
|
|
167
|
-
{
|
|
168
|
-
hideCloseButton,
|
|
169
|
-
onClose: close,
|
|
170
|
-
title
|
|
171
|
-
}
|
|
172
|
-
),
|
|
173
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: `${classBase2}-body`, children })
|
|
174
|
-
] }) }) });
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
// src/dialog/useDialog.tsx
|
|
178
|
-
var import_react3 = require("react");
|
|
179
|
-
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
180
|
-
var useDialog = () => {
|
|
181
|
-
const [dialogState, setDialogState] = (0, import_react3.useState)();
|
|
182
|
-
const handleClose = (0, import_react3.useCallback)(() => {
|
|
183
|
-
setDialogState(void 0);
|
|
184
|
-
}, []);
|
|
185
|
-
const dialog = dialogState ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
186
|
-
Dialog,
|
|
187
|
-
{
|
|
188
|
-
className: "vuDialog",
|
|
189
|
-
isOpen: true,
|
|
190
|
-
onClose: handleClose,
|
|
191
|
-
style: { maxHeight: 500 },
|
|
192
|
-
title: dialogState.title,
|
|
193
|
-
hideCloseButton: dialogState.hideCloseButton,
|
|
194
|
-
children: dialogState.content
|
|
195
|
-
}
|
|
196
|
-
) : null;
|
|
197
|
-
return {
|
|
198
|
-
dialog,
|
|
199
|
-
setDialogState
|
|
200
|
-
};
|
|
119
|
+
win.document.body.appendChild(el);
|
|
120
|
+
return el;
|
|
201
121
|
};
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
// src/menu/MenuList.tsx
|
|
207
|
-
var import_react6 = __toESM(require("react"));
|
|
208
|
-
var import_classnames3 = __toESM(require("classnames"));
|
|
209
|
-
var import_vuu_layout = require("@vuu-ui/vuu-layout");
|
|
210
|
-
|
|
211
|
-
// src/menu/use-keyboard-navigation.ts
|
|
212
|
-
var import_react4 = require("react");
|
|
213
|
-
|
|
214
|
-
// src/menu/utils.ts
|
|
215
|
-
var isRoot = (el) => el.closest(`[data-root='true']`) !== null;
|
|
216
|
-
var hasPopup = (el, idx) => {
|
|
217
|
-
var _a;
|
|
218
|
-
return el.ariaHasPopup === "true" && ((_a = el.dataset) == null ? void 0 : _a.idx) === `${idx}` || el.querySelector(`:scope > [data-index='${idx}'][aria-haspopup='true']`) !== null;
|
|
122
|
+
var createContainer = (props) => getPortalContainer(props);
|
|
123
|
+
var renderPortal = (component, container, x, y, onRender) => {
|
|
124
|
+
container.style.cssText = `left:${x}px; top:${y}px;position: absolute;`;
|
|
125
|
+
ReactDOM.render(component, container, onRender);
|
|
219
126
|
};
|
|
220
127
|
|
|
221
|
-
// src/
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
128
|
+
// src/popup/popup-service.ts
|
|
129
|
+
var _dialogOpen = false;
|
|
130
|
+
var _popups = [];
|
|
131
|
+
var reasonIsMenuAction = (reason) => (reason == null ? void 0 : reason.type) === "menu-action";
|
|
132
|
+
var reasonIsClickAway = (reason) => (reason == null ? void 0 : reason.type) === "click-away";
|
|
133
|
+
function specialKeyHandler(e) {
|
|
134
|
+
if (e.key === "Esc") {
|
|
135
|
+
if (_popups.length) {
|
|
136
|
+
closeAllPopups();
|
|
137
|
+
} else if (_dialogOpen) {
|
|
138
|
+
const dialogRoot = document.body.querySelector(".vuuDialog");
|
|
139
|
+
if (dialogRoot) {
|
|
140
|
+
import_react_dom.default.unmountComponentAtNode(dialogRoot);
|
|
141
|
+
}
|
|
227
142
|
}
|
|
228
143
|
}
|
|
229
|
-
return result;
|
|
230
144
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
var arrowLeftRightKeys = /* @__PURE__ */ new Set(["ArrowRight", "ArrowLeft"]);
|
|
236
|
-
var verticalNavigationKeys = /* @__PURE__ */ new Set(["Home", "End", "ArrowDown", "ArrowUp"]);
|
|
237
|
-
var horizontalNavigationKeys = /* @__PURE__ */ new Set([
|
|
238
|
-
"Home",
|
|
239
|
-
"End",
|
|
240
|
-
"ArrowRight",
|
|
241
|
-
"ArrowLeft"
|
|
242
|
-
]);
|
|
243
|
-
var functionKeys = /* @__PURE__ */ new Set([
|
|
244
|
-
"F1",
|
|
245
|
-
"F2",
|
|
246
|
-
"F3",
|
|
247
|
-
"F4",
|
|
248
|
-
"F5",
|
|
249
|
-
"F6",
|
|
250
|
-
"F7",
|
|
251
|
-
"F8",
|
|
252
|
-
"F9",
|
|
253
|
-
"F10",
|
|
254
|
-
"F11",
|
|
255
|
-
"F12"
|
|
256
|
-
]);
|
|
257
|
-
var specialKeys = union(
|
|
258
|
-
actionKeys,
|
|
259
|
-
horizontalNavigationKeys,
|
|
260
|
-
verticalNavigationKeys,
|
|
261
|
-
arrowLeftRightKeys,
|
|
262
|
-
functionKeys,
|
|
263
|
-
focusKeys
|
|
264
|
-
);
|
|
265
|
-
var isNavigationKey = ({ key }, orientation = "vertical") => {
|
|
266
|
-
const navigationKeys = orientation === "vertical" ? verticalNavigationKeys : horizontalNavigationKeys;
|
|
267
|
-
return navigationKeys.has(key);
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
// src/menu/use-keyboard-navigation.ts
|
|
271
|
-
var import_vuu_utils = require("@vuu-ui/vuu-utils");
|
|
272
|
-
var useKeyboardNavigation = ({
|
|
273
|
-
autoHighlightFirstItem = false,
|
|
274
|
-
count,
|
|
275
|
-
defaultHighlightedIdx,
|
|
276
|
-
highlightedIndex: highlightedIndexProp,
|
|
277
|
-
onActivate,
|
|
278
|
-
onHighlight,
|
|
279
|
-
// onKeyDown,
|
|
280
|
-
onCloseMenu,
|
|
281
|
-
onOpenMenu
|
|
282
|
-
}) => {
|
|
283
|
-
var _a;
|
|
284
|
-
if ((0, import_vuu_utils.isValidNumber)(highlightedIndexProp) && (0, import_vuu_utils.isValidNumber)(defaultHighlightedIdx)) {
|
|
285
|
-
throw Error(
|
|
286
|
-
"useKeyboardNavigation do not pass values for both highlightedIndex and defaultHighlightedIdx"
|
|
145
|
+
function outsideClickHandler(e) {
|
|
146
|
+
if (_popups.length) {
|
|
147
|
+
const popupContainers = document.body.querySelectorAll(
|
|
148
|
+
".vuuPopup,#vuu-portal-root"
|
|
287
149
|
);
|
|
150
|
+
for (let i = 0; i < popupContainers.length; i++) {
|
|
151
|
+
if (popupContainers[i].contains(e.target)) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
closeAllPopups({ mouseEvt: e, type: "click-away" });
|
|
288
156
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
(
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
157
|
+
}
|
|
158
|
+
function closeAllPopups(reason) {
|
|
159
|
+
if (_popups.length === 1) {
|
|
160
|
+
PopupService.hidePopup(reason, "anon", "all");
|
|
161
|
+
} else if (_popups.length) {
|
|
162
|
+
const popupContainers = document.body.querySelectorAll(".vuuPopup");
|
|
163
|
+
for (let i = 0; i < popupContainers.length; i++) {
|
|
164
|
+
import_react_dom.default.unmountComponentAtNode(popupContainers[i]);
|
|
165
|
+
}
|
|
166
|
+
popupClosed("*");
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function dialogOpened() {
|
|
170
|
+
if (_dialogOpen === false) {
|
|
171
|
+
_dialogOpen = true;
|
|
172
|
+
window.addEventListener("keydown", specialKeyHandler, true);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function dialogClosed() {
|
|
176
|
+
if (_dialogOpen) {
|
|
177
|
+
_dialogOpen = false;
|
|
178
|
+
window.removeEventListener("keydown", specialKeyHandler, true);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function popupOpened(name) {
|
|
182
|
+
if (_popups.indexOf(name) === -1) {
|
|
183
|
+
_popups.push(name);
|
|
184
|
+
if (_dialogOpen === false) {
|
|
185
|
+
window.addEventListener("keydown", specialKeyHandler, true);
|
|
186
|
+
window.addEventListener("click", outsideClickHandler, true);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
function popupClosed(name) {
|
|
191
|
+
if (_popups.length) {
|
|
192
|
+
if (name === "*") {
|
|
193
|
+
_popups.length = 0;
|
|
194
|
+
} else {
|
|
195
|
+
const pos = _popups.indexOf(name);
|
|
196
|
+
if (pos !== -1) {
|
|
197
|
+
_popups.splice(pos, 1);
|
|
308
198
|
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
[count, setHighlightedIndex]
|
|
324
|
-
);
|
|
325
|
-
const handleKeyDown = (0, import_react4.useCallback)(
|
|
326
|
-
(e) => {
|
|
327
|
-
if (isNavigationKey(e)) {
|
|
328
|
-
e.preventDefault();
|
|
329
|
-
e.stopPropagation();
|
|
330
|
-
keyBoardNavigation.current = true;
|
|
331
|
-
navigateChildldItems(e);
|
|
332
|
-
} else if ((e.key === "ArrowRight" || e.key === "Enter") && hasPopup(e.target, highlightedIndex)) {
|
|
333
|
-
const menuEl = e.target;
|
|
334
|
-
const menuItemEl = menuEl.querySelector(
|
|
335
|
-
`:scope > [data-index='${highlightedIndex}']`
|
|
336
|
-
);
|
|
337
|
-
if (menuItemEl) {
|
|
338
|
-
onOpenMenu == null ? void 0 : onOpenMenu(menuItemEl, true);
|
|
339
|
-
}
|
|
340
|
-
} else if (e.key === "ArrowLeft" && !isRoot(e.target)) {
|
|
341
|
-
onCloseMenu(highlightedIndex);
|
|
342
|
-
} else if (e.key === "Enter") {
|
|
343
|
-
e.preventDefault();
|
|
344
|
-
e.stopPropagation();
|
|
345
|
-
onActivate && onActivate(highlightedIndex);
|
|
346
|
-
} else if (e.key === "Tab") {
|
|
347
|
-
onCloseMenu(-1);
|
|
348
|
-
}
|
|
349
|
-
},
|
|
350
|
-
[
|
|
351
|
-
highlightedIndex,
|
|
352
|
-
navigateChildldItems,
|
|
353
|
-
onActivate,
|
|
354
|
-
onCloseMenu,
|
|
355
|
-
onOpenMenu
|
|
356
|
-
]
|
|
357
|
-
);
|
|
358
|
-
const listProps = (0, import_react4.useMemo)(
|
|
359
|
-
() => ({
|
|
360
|
-
onFocus: () => {
|
|
361
|
-
if (highlightedIndex === -1) {
|
|
362
|
-
setHighlightedIdx(0);
|
|
363
|
-
}
|
|
364
|
-
},
|
|
365
|
-
onKeyDown: handleKeyDown,
|
|
366
|
-
onMouseDownCapture: () => {
|
|
367
|
-
keyBoardNavigation.current = false;
|
|
368
|
-
setIgnoreFocus(true);
|
|
369
|
-
},
|
|
370
|
-
// onMouseEnter would seem less expensive but it misses some cases
|
|
371
|
-
onMouseMove: () => {
|
|
372
|
-
if (keyBoardNavigation.current) {
|
|
373
|
-
keyBoardNavigation.current = false;
|
|
374
|
-
}
|
|
375
|
-
},
|
|
376
|
-
onMouseLeave: () => {
|
|
377
|
-
keyBoardNavigation.current = true;
|
|
378
|
-
setIgnoreFocus(false);
|
|
379
|
-
setHighlightedIndex(-1);
|
|
380
|
-
}
|
|
381
|
-
}),
|
|
382
|
-
[handleKeyDown, highlightedIndex, setHighlightedIdx, setHighlightedIndex]
|
|
383
|
-
);
|
|
384
|
-
return {
|
|
385
|
-
focusVisible: keyBoardNavigation.current ? highlightedIndex : -1,
|
|
386
|
-
controlledHighlighting,
|
|
387
|
-
highlightedIndex,
|
|
388
|
-
setHighlightedIndex,
|
|
389
|
-
// keyBoardNavigation,
|
|
390
|
-
listProps,
|
|
391
|
-
setIgnoreFocus
|
|
392
|
-
};
|
|
199
|
+
}
|
|
200
|
+
if (_popups.length === 0 && _dialogOpen === false) {
|
|
201
|
+
window.removeEventListener("keydown", specialKeyHandler, true);
|
|
202
|
+
window.removeEventListener("click", outsideClickHandler, true);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
var PopupComponent = ({
|
|
207
|
+
children,
|
|
208
|
+
position,
|
|
209
|
+
style
|
|
210
|
+
}) => {
|
|
211
|
+
const className = (0, import_clsx3.default)("hwPopup", "hwPopupContainer", position);
|
|
212
|
+
return (0, import_react.createElement)("div", { className, style }, children);
|
|
393
213
|
};
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
214
|
+
var incrementingKey = 1;
|
|
215
|
+
var PopupService = class _PopupService {
|
|
216
|
+
static showPopup({
|
|
217
|
+
group = "all",
|
|
218
|
+
name = "anon",
|
|
219
|
+
left = 0,
|
|
220
|
+
position = "",
|
|
221
|
+
right = "auto",
|
|
222
|
+
top = 0,
|
|
223
|
+
width = "auto",
|
|
224
|
+
component
|
|
225
|
+
}) {
|
|
226
|
+
if (!component) {
|
|
227
|
+
throw Error(`PopupService showPopup, no component supplied`);
|
|
400
228
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
return 0;
|
|
404
|
-
} else if (idx === count - 1) {
|
|
405
|
-
return idx;
|
|
229
|
+
if (typeof component.props.onClose === "function") {
|
|
230
|
+
_PopupService.onClose = component.props.onClose;
|
|
406
231
|
} else {
|
|
407
|
-
|
|
232
|
+
_PopupService.onClose = void 0;
|
|
233
|
+
}
|
|
234
|
+
popupOpened(name);
|
|
235
|
+
document.addEventListener("keydown", _PopupService.escapeKeyListener, true);
|
|
236
|
+
let el = document.body.querySelector(".vuuPopup." + group);
|
|
237
|
+
if (el === null) {
|
|
238
|
+
el = document.createElement("div");
|
|
239
|
+
el.className = "vuuPopup " + group;
|
|
240
|
+
document.body.appendChild(el);
|
|
241
|
+
}
|
|
242
|
+
const style = { width };
|
|
243
|
+
renderPortal(
|
|
244
|
+
(0, import_react.createElement)(
|
|
245
|
+
PopupComponent,
|
|
246
|
+
{ key: incrementingKey++, position, style },
|
|
247
|
+
component
|
|
248
|
+
),
|
|
249
|
+
el,
|
|
250
|
+
left,
|
|
251
|
+
top,
|
|
252
|
+
() => {
|
|
253
|
+
_PopupService.keepWithinThePage(el, right);
|
|
254
|
+
}
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
static escapeKeyListener(evt) {
|
|
258
|
+
if (evt.key === "Escape") {
|
|
259
|
+
_PopupService.hidePopup({ type: "escape", event: evt });
|
|
408
260
|
}
|
|
409
261
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
262
|
+
static hidePopup(reason, name = "anon", group = "all") {
|
|
263
|
+
var _a;
|
|
264
|
+
if (_popups.indexOf(name) !== -1) {
|
|
265
|
+
popupClosed(name);
|
|
266
|
+
const popupRoot = document.body.querySelector(`.vuuPopup.${group}`);
|
|
267
|
+
if (popupRoot) {
|
|
268
|
+
import_react_dom.default.unmountComponentAtNode(popupRoot);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
document.removeEventListener(
|
|
272
|
+
"keydown",
|
|
273
|
+
_PopupService.escapeKeyListener,
|
|
274
|
+
true
|
|
275
|
+
);
|
|
276
|
+
(_a = _PopupService == null ? void 0 : _PopupService.onClose) == null ? void 0 : _a.call(_PopupService, reason);
|
|
277
|
+
}
|
|
278
|
+
static keepWithinThePage(el, right = "auto") {
|
|
279
|
+
const target = el.querySelector(".vuuPopupContainer > *");
|
|
280
|
+
if (target) {
|
|
281
|
+
const {
|
|
282
|
+
top,
|
|
283
|
+
left,
|
|
284
|
+
width,
|
|
285
|
+
height,
|
|
286
|
+
right: currentRight
|
|
287
|
+
} = target.getBoundingClientRect();
|
|
288
|
+
const w = window.innerWidth;
|
|
289
|
+
const h = window.innerHeight;
|
|
290
|
+
const overflowH = h - (top + height);
|
|
291
|
+
if (overflowH < 0) {
|
|
292
|
+
target.style.top = Math.round(top) + overflowH + "px";
|
|
293
|
+
}
|
|
294
|
+
const overflowW = w - (left + width);
|
|
295
|
+
if (overflowW < 0) {
|
|
296
|
+
target.style.left = Math.round(left) + overflowW + "px";
|
|
297
|
+
}
|
|
298
|
+
if (typeof right === "number" && right !== currentRight) {
|
|
299
|
+
const adjustment = right - currentRight;
|
|
300
|
+
target.style.left = left + adjustment + "px";
|
|
301
|
+
}
|
|
302
|
+
}
|
|
418
303
|
}
|
|
419
304
|
};
|
|
420
|
-
var
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
};
|
|
433
|
-
};
|
|
434
|
-
var useItemsWithIdsNext = (childrenProp, rootId) => {
|
|
435
|
-
const normalizeChildren = (0, import_react5.useCallback)(() => {
|
|
436
|
-
const collectChildren = (children, path = rootId, menus2 = {}, actions2 = {}) => {
|
|
437
|
-
const list = menus2[path] = [];
|
|
438
|
-
let idx = 0;
|
|
439
|
-
let hasSeparator = false;
|
|
440
|
-
import_react5.default.Children.forEach(children, (child) => {
|
|
441
|
-
if (isMenuItemLabel(child)) {
|
|
442
|
-
} else if (child.type === Separator) {
|
|
443
|
-
hasSeparator = true;
|
|
444
|
-
} else {
|
|
445
|
-
const hasChildItems = isMenuItemGroup(child);
|
|
446
|
-
const childPath = `${path}-${idx}`;
|
|
447
|
-
const {
|
|
448
|
-
props: { action, options }
|
|
449
|
-
} = child;
|
|
450
|
-
const { childWithId, grandChildren } = assignId(
|
|
451
|
-
child,
|
|
452
|
-
childPath,
|
|
453
|
-
hasChildItems,
|
|
454
|
-
hasSeparator
|
|
455
|
-
);
|
|
456
|
-
list.push(childWithId);
|
|
457
|
-
if (grandChildren) {
|
|
458
|
-
collectChildren(grandChildren, childPath, menus2, actions2);
|
|
459
|
-
} else {
|
|
460
|
-
actions2[childPath] = { action, options };
|
|
305
|
+
var DialogService = class _DialogService {
|
|
306
|
+
static showDialog(dialog) {
|
|
307
|
+
const containerEl = ".vuuDialog";
|
|
308
|
+
const onClose = dialog.props.onClose;
|
|
309
|
+
dialogOpened();
|
|
310
|
+
import_react_dom.default.render(
|
|
311
|
+
import_react.default.cloneElement(dialog, {
|
|
312
|
+
container: containerEl,
|
|
313
|
+
onClose: () => {
|
|
314
|
+
_DialogService.closeDialog();
|
|
315
|
+
if (onClose) {
|
|
316
|
+
onClose();
|
|
461
317
|
}
|
|
462
|
-
idx += 1;
|
|
463
|
-
hasSeparator = false;
|
|
464
318
|
}
|
|
465
|
-
})
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
319
|
+
}),
|
|
320
|
+
document.body.querySelector(containerEl)
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
static closeDialog() {
|
|
324
|
+
dialogClosed();
|
|
325
|
+
const dialogRoot = document.body.querySelector(".vuuDialog");
|
|
326
|
+
if (dialogRoot) {
|
|
327
|
+
import_react_dom.default.unmountComponentAtNode(dialogRoot);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
475
330
|
};
|
|
476
331
|
|
|
477
|
-
// src/
|
|
478
|
-
var
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
var
|
|
482
|
-
var
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
332
|
+
// src/popup/Popup.tsx
|
|
333
|
+
var import_clsx4 = __toESM(require("clsx"));
|
|
334
|
+
|
|
335
|
+
// src/popup/useAnchoredPosition.ts
|
|
336
|
+
var import_react2 = require("react");
|
|
337
|
+
var getPositionRelativeToAnchor = (anchorElement, placement, offsetLeft, offsetTop, minWidth, dimensions) => {
|
|
338
|
+
const { bottom, height, left, right, top, width } = anchorElement.getBoundingClientRect();
|
|
339
|
+
switch (placement) {
|
|
340
|
+
case "below":
|
|
341
|
+
return { left: left + offsetLeft, top: bottom + offsetTop };
|
|
342
|
+
case "right":
|
|
343
|
+
return { left: right + offsetLeft, top: top + offsetTop };
|
|
344
|
+
case "below-center":
|
|
345
|
+
return { left: left + width / 2 + offsetLeft, top: bottom + offsetTop };
|
|
346
|
+
case "below-right":
|
|
347
|
+
return { left, minWidth, top: bottom + offsetTop };
|
|
348
|
+
case "below-full-width":
|
|
349
|
+
return {
|
|
350
|
+
left: left + offsetLeft,
|
|
351
|
+
minWidth,
|
|
352
|
+
top: bottom + offsetTop,
|
|
353
|
+
width
|
|
354
|
+
};
|
|
355
|
+
case "center":
|
|
356
|
+
if (dimensions) {
|
|
357
|
+
return {
|
|
358
|
+
left: width / 2 - dimensions.width / 2 + offsetLeft,
|
|
359
|
+
top: height / 2 - dimensions.height / 2 + offsetTop,
|
|
360
|
+
visibility: "visible"
|
|
361
|
+
};
|
|
362
|
+
} else {
|
|
363
|
+
return {
|
|
364
|
+
left: width / 2 + offsetLeft,
|
|
365
|
+
top: height / 2 + offsetTop,
|
|
366
|
+
visibility: "hidden"
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
default:
|
|
370
|
+
throw Error(
|
|
371
|
+
"Popup getPositionRelativeToAnchor only supported placement values are below and right"
|
|
372
|
+
);
|
|
373
|
+
}
|
|
489
374
|
};
|
|
490
|
-
var
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
375
|
+
var useAnchoredPosition = ({
|
|
376
|
+
anchorElement,
|
|
377
|
+
minWidth,
|
|
378
|
+
offsetLeft = 0,
|
|
379
|
+
offsetTop = 0,
|
|
380
|
+
placement,
|
|
381
|
+
position: positionProp
|
|
382
|
+
}) => {
|
|
383
|
+
const popupRef = (0, import_react2.useRef)(null);
|
|
384
|
+
const [position, setPosition] = (0, import_react2.useState)(positionProp);
|
|
385
|
+
(0, import_react2.useLayoutEffect)(() => {
|
|
386
|
+
if (placement === "absolute" && positionProp) {
|
|
387
|
+
setPosition(positionProp);
|
|
388
|
+
} else if (anchorElement.current && placement !== "auto") {
|
|
389
|
+
const dimensions = popupRef.current === null ? void 0 : popupRef.current.getBoundingClientRect();
|
|
390
|
+
const position2 = getPositionRelativeToAnchor(
|
|
391
|
+
anchorElement.current,
|
|
392
|
+
placement,
|
|
393
|
+
offsetLeft,
|
|
394
|
+
offsetTop,
|
|
395
|
+
minWidth,
|
|
396
|
+
dimensions
|
|
397
|
+
);
|
|
398
|
+
setPosition(position2);
|
|
399
|
+
}
|
|
400
|
+
}, [anchorElement, minWidth, offsetLeft, offsetTop, placement, positionProp]);
|
|
401
|
+
const popupCallbackRef = (0, import_react2.useCallback)(
|
|
402
|
+
(el) => {
|
|
403
|
+
popupRef.current = el;
|
|
404
|
+
if (el && placement === "center" && anchorElement.current) {
|
|
405
|
+
const { height, width } = el.getBoundingClientRect();
|
|
406
|
+
setPosition(
|
|
407
|
+
getPositionRelativeToAnchor(
|
|
408
|
+
anchorElement.current,
|
|
409
|
+
placement,
|
|
410
|
+
offsetLeft,
|
|
411
|
+
offsetTop,
|
|
412
|
+
void 0,
|
|
413
|
+
{ height, width }
|
|
414
|
+
)
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
},
|
|
418
|
+
[anchorElement, offsetLeft, offsetTop, placement]
|
|
419
|
+
);
|
|
420
|
+
return {
|
|
421
|
+
position,
|
|
422
|
+
popupRef: placement === "center" ? popupCallbackRef : void 0
|
|
423
|
+
};
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
// src/popup/Popup.tsx
|
|
427
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
428
|
+
var PopupComponent2 = ({
|
|
499
429
|
children,
|
|
500
430
|
className,
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
listItemProps,
|
|
506
|
-
onHighlightMenuItem,
|
|
507
|
-
onActivate,
|
|
508
|
-
onCloseMenu,
|
|
509
|
-
openMenu: onOpenMenu,
|
|
510
|
-
...props
|
|
431
|
+
anchorElement,
|
|
432
|
+
minWidth,
|
|
433
|
+
placement,
|
|
434
|
+
position: positionProp
|
|
511
435
|
}) => {
|
|
512
|
-
const
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
const el = (_a = root.current) == null ? void 0 : _a.querySelector(`:scope > [data-index='${idx}']`);
|
|
518
|
-
(el == null ? void 0 : el.id) && (onActivate == null ? void 0 : onActivate(el.id));
|
|
519
|
-
};
|
|
520
|
-
const { focusVisible, highlightedIndex, listProps } = useKeyboardNavigation({
|
|
521
|
-
count: import_react6.default.Children.count(children),
|
|
522
|
-
defaultHighlightedIdx,
|
|
523
|
-
highlightedIndex: highlightedIdxProp,
|
|
524
|
-
onActivate: handleActivate,
|
|
525
|
-
onHighlight: onHighlightMenuItem,
|
|
526
|
-
onOpenMenu,
|
|
527
|
-
onCloseMenu
|
|
436
|
+
const { popupRef, position } = useAnchoredPosition({
|
|
437
|
+
anchorElement,
|
|
438
|
+
minWidth,
|
|
439
|
+
placement,
|
|
440
|
+
position: positionProp
|
|
528
441
|
});
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
442
|
+
return position === void 0 ? null : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: (0, import_clsx4.default)(`vuuPortal`, className), ref: popupRef, style: position, children });
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
// src/dialog/Dialog.tsx
|
|
446
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
447
|
+
var classBase2 = "vuuDialog";
|
|
448
|
+
var AnchorBody = { current: document.body };
|
|
449
|
+
var EMPTY_PROPS = {};
|
|
450
|
+
var Dialog = ({
|
|
451
|
+
PopupProps = EMPTY_PROPS,
|
|
452
|
+
children,
|
|
453
|
+
className,
|
|
454
|
+
isOpen = false,
|
|
455
|
+
onClose,
|
|
456
|
+
style,
|
|
457
|
+
title,
|
|
458
|
+
hideCloseButton = false,
|
|
459
|
+
...htmlAttributes
|
|
460
|
+
}) => {
|
|
461
|
+
const {
|
|
462
|
+
anchorElement = AnchorBody,
|
|
463
|
+
offsetLeft = 0,
|
|
464
|
+
offsetTop = 0,
|
|
465
|
+
placement = "auto"
|
|
466
|
+
} = PopupProps;
|
|
467
|
+
const rootRef = (0, import_react3.useRef)(null);
|
|
468
|
+
const portalRef = (0, import_react3.useRef)(null);
|
|
469
|
+
const [themeClass, densityClass, dataMode] = (0, import_vuu_utils.useThemeAttributes)();
|
|
470
|
+
const { position } = useAnchoredPosition({
|
|
471
|
+
anchorElement,
|
|
472
|
+
offsetLeft,
|
|
473
|
+
offsetTop,
|
|
474
|
+
placement
|
|
475
|
+
});
|
|
476
|
+
const close = (0, import_react3.useCallback)(() => {
|
|
477
|
+
onClose == null ? void 0 : onClose();
|
|
478
|
+
}, [onClose]);
|
|
479
|
+
(0, import_react3.useLayoutEffect)(() => {
|
|
480
|
+
if (rootRef.current) {
|
|
481
|
+
if (isOpen) {
|
|
482
|
+
rootRef.current.showModal();
|
|
483
|
+
const { left, top } = rootRef.current.getBoundingClientRect();
|
|
484
|
+
if (portalRef.current) {
|
|
485
|
+
portalRef.current.style.cssText = `left:-${left}px;position:absolute;top:-${top}px;`;
|
|
486
|
+
}
|
|
487
|
+
} else {
|
|
488
|
+
rootRef.current.close();
|
|
489
|
+
}
|
|
490
|
+
if (placement.endsWith("center")) {
|
|
491
|
+
const { width } = rootRef.current.getBoundingClientRect();
|
|
492
|
+
rootRef.current.style.marginLeft = `-${width / 2}px`;
|
|
493
|
+
}
|
|
534
494
|
}
|
|
535
|
-
}, [
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
...
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
"icon"
|
|
550
|
-
)
|
|
551
|
-
].concat(childElement) : childElement;
|
|
552
|
-
function addClonedChild(list, child, idx, withIcon) {
|
|
553
|
-
var _a;
|
|
554
|
-
const {
|
|
555
|
-
children: children2,
|
|
556
|
-
className: className2,
|
|
557
|
-
"data-icon": iconName,
|
|
558
|
-
id: itemId,
|
|
559
|
-
hasSeparator,
|
|
560
|
-
label,
|
|
561
|
-
...props2
|
|
562
|
-
} = child.props;
|
|
563
|
-
const hasSubMenu = isMenuItemGroup(child);
|
|
564
|
-
const subMenuShowing = hasSubMenu && childMenuShowing === itemId;
|
|
565
|
-
const ariaControls = subMenuShowing ? `${id}-${itemId}` : void 0;
|
|
566
|
-
list.push(
|
|
567
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
568
|
-
MenuItem,
|
|
495
|
+
}, [isOpen, placement]);
|
|
496
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
497
|
+
"dialog",
|
|
498
|
+
{
|
|
499
|
+
...htmlAttributes,
|
|
500
|
+
className: (0, import_clsx5.default)(classBase2, themeClass),
|
|
501
|
+
"data-mode": dataMode,
|
|
502
|
+
onClose: close,
|
|
503
|
+
id: "vuu-dialog",
|
|
504
|
+
ref: rootRef,
|
|
505
|
+
style: { ...style, ...position },
|
|
506
|
+
children: [
|
|
507
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
508
|
+
DialogHeader,
|
|
569
509
|
{
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
itemId,
|
|
574
|
-
idx,
|
|
575
|
-
(_a = child.key) != null ? _a : itemId,
|
|
576
|
-
highlightedIndex,
|
|
577
|
-
appliedFocusVisible,
|
|
578
|
-
className2,
|
|
579
|
-
hasSeparator
|
|
580
|
-
),
|
|
581
|
-
"aria-controls": ariaControls,
|
|
582
|
-
"aria-haspopup": hasSubMenu || void 0,
|
|
583
|
-
"aria-expanded": subMenuShowing || void 0,
|
|
584
|
-
children: hasSubMenu ? maybeIcon(label != null ? label : children2, withIcon, iconName) : maybeIcon(children2, withIcon, iconName)
|
|
510
|
+
hideCloseButton,
|
|
511
|
+
onClose: close,
|
|
512
|
+
title
|
|
585
513
|
}
|
|
586
|
-
)
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
if (children.length > 0) {
|
|
591
|
-
const withIcon = children.some(hasIcon);
|
|
592
|
-
children.forEach((child, idx) => {
|
|
593
|
-
addClonedChild(listItems, child, idx, withIcon);
|
|
594
|
-
});
|
|
595
|
-
}
|
|
596
|
-
return listItems;
|
|
597
|
-
}
|
|
598
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
599
|
-
"div",
|
|
600
|
-
{
|
|
601
|
-
...props,
|
|
602
|
-
...listProps,
|
|
603
|
-
"aria-activedescendant": getActiveDescendant(),
|
|
604
|
-
className: (0, import_classnames3.default)(classBase3, className, {
|
|
605
|
-
[`${classBase3}-childMenuShowing`]: childMenuShowing !== void 0
|
|
606
|
-
}),
|
|
607
|
-
"data-root": isRoot2 || void 0,
|
|
608
|
-
id,
|
|
609
|
-
ref: root,
|
|
610
|
-
role: "menu",
|
|
611
|
-
children: renderContent()
|
|
514
|
+
),
|
|
515
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: `${classBase2}-body`, children }),
|
|
516
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { id: "vuu-dialog-portal-root", ref: portalRef })
|
|
517
|
+
]
|
|
612
518
|
}
|
|
613
519
|
);
|
|
614
520
|
};
|
|
615
|
-
var getMenuItemProps = (itemId, idx, key, highlightedIdx, focusVisible, className, hasSeparator) => ({
|
|
616
|
-
id: `menuitem-${itemId}`,
|
|
617
|
-
key: key != null ? key : idx,
|
|
618
|
-
"data-index": idx,
|
|
619
|
-
"data-highlighted": idx === highlightedIdx || void 0,
|
|
620
|
-
className: (0, import_classnames3.default)("vuuMenuItem", className, {
|
|
621
|
-
"vuuMenuItem-separator": hasSeparator,
|
|
622
|
-
focusVisible: focusVisible === idx
|
|
623
|
-
})
|
|
624
|
-
});
|
|
625
|
-
MenuList.displayName = "MenuList";
|
|
626
521
|
|
|
627
|
-
// src/
|
|
628
|
-
var
|
|
522
|
+
// src/dialog/useDialog.tsx
|
|
523
|
+
var import_react4 = require("react");
|
|
524
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
525
|
+
var useDialog = () => {
|
|
526
|
+
const [dialogState, setDialogState] = (0, import_react4.useState)();
|
|
527
|
+
const handleClose = (0, import_react4.useCallback)(() => {
|
|
528
|
+
setDialogState(void 0);
|
|
529
|
+
}, []);
|
|
530
|
+
const dialog = dialogState ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
531
|
+
Dialog,
|
|
532
|
+
{
|
|
533
|
+
className: "vuDialog",
|
|
534
|
+
isOpen: true,
|
|
535
|
+
onClose: handleClose,
|
|
536
|
+
style: { maxHeight: 500 },
|
|
537
|
+
title: dialogState.title,
|
|
538
|
+
hideCloseButton: dialogState.hideCloseButton,
|
|
539
|
+
children: dialogState.content
|
|
540
|
+
}
|
|
541
|
+
) : null;
|
|
542
|
+
return {
|
|
543
|
+
dialog,
|
|
544
|
+
setDialogState
|
|
545
|
+
};
|
|
546
|
+
};
|
|
629
547
|
|
|
630
|
-
// src/menu/
|
|
631
|
-
var
|
|
548
|
+
// src/menu/ContextMenu.tsx
|
|
549
|
+
var import_vuu_utils5 = require("@vuu-ui/vuu-utils");
|
|
550
|
+
var import_react10 = require("react");
|
|
632
551
|
|
|
633
|
-
// src/
|
|
634
|
-
var
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
552
|
+
// src/portal/Portal.tsx
|
|
553
|
+
var import_vuu_utils2 = require("@vuu-ui/vuu-utils");
|
|
554
|
+
var import_react5 = require("react");
|
|
555
|
+
var import_react_dom2 = require("react-dom");
|
|
556
|
+
function getContainer(container) {
|
|
557
|
+
return typeof container === "function" ? container() : container;
|
|
558
|
+
}
|
|
559
|
+
var DEFAULT_ID = ["vuu-dialog-portal-root", "vuu-portal-root"];
|
|
560
|
+
var getFirstAvailableElementById = (id) => {
|
|
561
|
+
if (Array.isArray(id)) {
|
|
562
|
+
for (const i of id) {
|
|
563
|
+
const element = document.getElementById(i);
|
|
564
|
+
if (element) {
|
|
565
|
+
return element;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
} else {
|
|
569
|
+
return document.getElementById(id);
|
|
649
570
|
}
|
|
650
|
-
|
|
651
|
-
return menus.map(
|
|
652
|
-
(m) => m === menu ? {
|
|
653
|
-
...m,
|
|
654
|
-
left: parentMenu.left - (width - 2)
|
|
655
|
-
} : m
|
|
656
|
-
);
|
|
571
|
+
return null;
|
|
657
572
|
};
|
|
658
|
-
var
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
573
|
+
var Portal = ({
|
|
574
|
+
children,
|
|
575
|
+
container: containerProp = document.body,
|
|
576
|
+
id = DEFAULT_ID,
|
|
577
|
+
onRender,
|
|
578
|
+
open = true,
|
|
579
|
+
themeAttributes
|
|
580
|
+
}) => {
|
|
581
|
+
var _a;
|
|
582
|
+
const [mounted, setMounted] = (0, import_react5.useState)(false);
|
|
583
|
+
const portalRef = (0, import_react5.useRef)(null);
|
|
584
|
+
const container = (_a = getContainer(containerProp)) != null ? _a : document.body;
|
|
585
|
+
const [themeClass, densityClass, dataMode] = (0, import_vuu_utils2.useThemeAttributes)(themeAttributes);
|
|
586
|
+
(0, import_react5.useLayoutEffect)(() => {
|
|
587
|
+
const root = getFirstAvailableElementById(id);
|
|
588
|
+
if (root) {
|
|
589
|
+
portalRef.current = root;
|
|
590
|
+
} else {
|
|
591
|
+
portalRef.current = document.createElement("div");
|
|
592
|
+
portalRef.current.id = typeof id === "string" ? id : id.length > 0 ? id.at(-1) : "vuu-portal-root";
|
|
593
|
+
}
|
|
594
|
+
const el = portalRef.current;
|
|
595
|
+
if (!container.contains(el)) {
|
|
596
|
+
container.appendChild(el);
|
|
597
|
+
}
|
|
598
|
+
el.classList.add(themeClass, densityClass);
|
|
599
|
+
el.dataset.mode = dataMode;
|
|
600
|
+
setMounted(true);
|
|
601
|
+
}, [id, container, themeClass, densityClass, dataMode]);
|
|
602
|
+
(0, import_react5.useLayoutEffect)(() => {
|
|
603
|
+
requestAnimationFrame(() => {
|
|
604
|
+
onRender == null ? void 0 : onRender();
|
|
605
|
+
});
|
|
606
|
+
}, [onRender]);
|
|
607
|
+
if (open && mounted && portalRef.current && children) {
|
|
608
|
+
return (0, import_react_dom2.createPortal)(children, portalRef.current);
|
|
609
|
+
}
|
|
610
|
+
return null;
|
|
662
611
|
};
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
612
|
+
|
|
613
|
+
// src/menu/MenuList.tsx
|
|
614
|
+
var import_clsx6 = __toESM(require("clsx"));
|
|
615
|
+
var import_react8 = __toESM(require("react"));
|
|
616
|
+
var import_vuu_utils4 = require("@vuu-ui/vuu-utils");
|
|
617
|
+
|
|
618
|
+
// src/menu/use-items-with-ids-next.ts
|
|
619
|
+
var import_react6 = __toESM(require("react"));
|
|
620
|
+
var isMenuItemGroup = (child) => child.type === MenuItemGroup || !!child.props["data-group"];
|
|
621
|
+
var getLabelFromChildren = (children) => {
|
|
622
|
+
if (Array.isArray(children) && isMenuItemLabel(children[0])) {
|
|
623
|
+
return children[0];
|
|
669
624
|
}
|
|
670
625
|
};
|
|
671
|
-
var
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
626
|
+
var assignId = (child, path, group, hasSeparator = false) => {
|
|
627
|
+
const {
|
|
628
|
+
props: { children }
|
|
629
|
+
} = child;
|
|
630
|
+
return {
|
|
631
|
+
childWithId: import_react6.default.cloneElement(child, {
|
|
632
|
+
hasSeparator,
|
|
633
|
+
id: `${path}`,
|
|
634
|
+
key: path,
|
|
635
|
+
children: group ? getLabelFromChildren(children) : children
|
|
636
|
+
}),
|
|
637
|
+
grandChildren: group ? children : void 0
|
|
638
|
+
};
|
|
639
|
+
};
|
|
640
|
+
var useItemsWithIdsNext = (childrenProp, rootId) => {
|
|
641
|
+
const normalizeChildren = (0, import_react6.useCallback)(() => {
|
|
642
|
+
const collectChildren = (children, path = rootId, menus2 = {}, actions2 = {}) => {
|
|
643
|
+
const list = menus2[path] = [];
|
|
644
|
+
let idx = 0;
|
|
645
|
+
let hasSeparator = false;
|
|
646
|
+
import_react6.default.Children.forEach(children, (child) => {
|
|
647
|
+
if (isMenuItemLabel(child)) {
|
|
648
|
+
} else if (child.type === Separator) {
|
|
649
|
+
hasSeparator = true;
|
|
650
|
+
} else {
|
|
651
|
+
const hasChildItems = isMenuItemGroup(child);
|
|
652
|
+
const childPath = `${path}-${idx}`;
|
|
653
|
+
const {
|
|
654
|
+
props: { action, options }
|
|
655
|
+
} = child;
|
|
656
|
+
const { childWithId, grandChildren } = assignId(
|
|
657
|
+
child,
|
|
658
|
+
childPath,
|
|
659
|
+
hasChildItems,
|
|
660
|
+
hasSeparator
|
|
661
|
+
);
|
|
662
|
+
list.push(childWithId);
|
|
663
|
+
if (grandChildren) {
|
|
664
|
+
collectChildren(grandChildren, childPath, menus2, actions2);
|
|
665
|
+
} else {
|
|
666
|
+
actions2[childPath] = { action, options };
|
|
667
|
+
}
|
|
668
|
+
idx += 1;
|
|
669
|
+
hasSeparator = false;
|
|
670
|
+
}
|
|
671
|
+
});
|
|
672
|
+
return [menus2, actions2];
|
|
680
673
|
};
|
|
681
|
-
|
|
682
|
-
|
|
674
|
+
return collectChildren(childrenProp);
|
|
675
|
+
}, [rootId, childrenProp]);
|
|
676
|
+
const [menus, actions] = (0, import_react6.useMemo)(
|
|
677
|
+
() => normalizeChildren(),
|
|
678
|
+
[normalizeChildren]
|
|
679
|
+
);
|
|
680
|
+
return [menus, actions];
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
// src/menu/use-keyboard-navigation.ts
|
|
684
|
+
var import_react7 = require("react");
|
|
685
|
+
|
|
686
|
+
// src/menu/utils.ts
|
|
687
|
+
var isRoot = (el) => el.closest(`[data-root='true']`) !== null;
|
|
688
|
+
var hasPopup = (el, idx) => {
|
|
689
|
+
var _a;
|
|
690
|
+
return el.ariaHasPopup === "true" && ((_a = el.dataset) == null ? void 0 : _a.idx) === `${idx}` || el.querySelector(`:scope > [data-index='${idx}'][aria-haspopup='true']`) !== null;
|
|
691
|
+
};
|
|
692
|
+
|
|
693
|
+
// src/menu/key-code.ts
|
|
694
|
+
function union(set1, ...sets) {
|
|
695
|
+
const result = new Set(set1);
|
|
696
|
+
for (const set of sets) {
|
|
697
|
+
for (const element of set) {
|
|
698
|
+
result.add(element);
|
|
699
|
+
}
|
|
683
700
|
}
|
|
701
|
+
return result;
|
|
702
|
+
}
|
|
703
|
+
var Enter = "Enter";
|
|
704
|
+
var Delete = "Delete";
|
|
705
|
+
var actionKeys = /* @__PURE__ */ new Set([Enter, Delete]);
|
|
706
|
+
var focusKeys = /* @__PURE__ */ new Set(["Tab"]);
|
|
707
|
+
var arrowLeftRightKeys = /* @__PURE__ */ new Set(["ArrowRight", "ArrowLeft"]);
|
|
708
|
+
var verticalNavigationKeys = /* @__PURE__ */ new Set(["Home", "End", "ArrowDown", "ArrowUp"]);
|
|
709
|
+
var horizontalNavigationKeys = /* @__PURE__ */ new Set([
|
|
710
|
+
"Home",
|
|
711
|
+
"End",
|
|
712
|
+
"ArrowRight",
|
|
713
|
+
"ArrowLeft"
|
|
714
|
+
]);
|
|
715
|
+
var functionKeys = /* @__PURE__ */ new Set([
|
|
716
|
+
"F1",
|
|
717
|
+
"F2",
|
|
718
|
+
"F3",
|
|
719
|
+
"F4",
|
|
720
|
+
"F5",
|
|
721
|
+
"F6",
|
|
722
|
+
"F7",
|
|
723
|
+
"F8",
|
|
724
|
+
"F9",
|
|
725
|
+
"F10",
|
|
726
|
+
"F11",
|
|
727
|
+
"F12"
|
|
728
|
+
]);
|
|
729
|
+
var specialKeys = union(
|
|
730
|
+
actionKeys,
|
|
731
|
+
horizontalNavigationKeys,
|
|
732
|
+
verticalNavigationKeys,
|
|
733
|
+
arrowLeftRightKeys,
|
|
734
|
+
functionKeys,
|
|
735
|
+
focusKeys
|
|
736
|
+
);
|
|
737
|
+
var isNavigationKey = ({ key }, orientation = "vertical") => {
|
|
738
|
+
const navigationKeys = orientation === "vertical" ? verticalNavigationKeys : horizontalNavigationKeys;
|
|
739
|
+
return navigationKeys.has(key);
|
|
684
740
|
};
|
|
685
|
-
|
|
686
|
-
|
|
741
|
+
|
|
742
|
+
// src/menu/use-keyboard-navigation.ts
|
|
743
|
+
var import_vuu_utils3 = require("@vuu-ui/vuu-utils");
|
|
744
|
+
var useKeyboardNavigation = ({
|
|
745
|
+
autoHighlightFirstItem = false,
|
|
746
|
+
count,
|
|
747
|
+
defaultHighlightedIdx,
|
|
748
|
+
highlightedIndex: highlightedIndexProp,
|
|
687
749
|
onActivate,
|
|
688
|
-
|
|
689
|
-
|
|
750
|
+
onHighlight,
|
|
751
|
+
// onKeyDown,
|
|
752
|
+
onCloseMenu,
|
|
753
|
+
onOpenMenu
|
|
690
754
|
}) => {
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
)
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
openMenus.current = menus;
|
|
708
|
-
forceRefresh({});
|
|
709
|
-
}, []);
|
|
710
|
-
const menuOpenPendingTimeout = (0, import_react7.useRef)();
|
|
711
|
-
const menuClosePendingTimeout = (0, import_react7.useRef)();
|
|
712
|
-
const menuState = (0, import_react7.useRef)({ [rootId]: "no-popup" });
|
|
713
|
-
const openMenu = (0, import_react7.useCallback)(
|
|
714
|
-
(hostMenuId = rootId, targetMenuId, itemId = null) => {
|
|
715
|
-
if (hostMenuId === rootId && itemId === null) {
|
|
716
|
-
setOpenMenus([{ id: rootId, left: posX, top: posY }]);
|
|
717
|
-
} else {
|
|
718
|
-
menuState.current[hostMenuId] = "popup-open";
|
|
719
|
-
const el = document.getElementById(itemId);
|
|
720
|
-
if (el !== null) {
|
|
721
|
-
const { left, top } = getPosition(el, openMenus.current);
|
|
722
|
-
setOpenMenus(
|
|
723
|
-
openMenus.current.concat({ id: targetMenuId, left, top })
|
|
724
|
-
);
|
|
725
|
-
} else {
|
|
726
|
-
throw Error(`openMenu no menuItem ${itemId}`);
|
|
727
|
-
}
|
|
728
|
-
}
|
|
755
|
+
var _a;
|
|
756
|
+
if ((0, import_vuu_utils3.isValidNumber)(highlightedIndexProp) && (0, import_vuu_utils3.isValidNumber)(defaultHighlightedIdx)) {
|
|
757
|
+
throw Error(
|
|
758
|
+
"useKeyboardNavigation do not pass values for both highlightedIndex and defaultHighlightedIdx"
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
const controlledHighlighting = (0, import_vuu_utils3.isValidNumber)(highlightedIndexProp);
|
|
762
|
+
const highlightedIndexRef = (0, import_react7.useRef)(
|
|
763
|
+
(_a = defaultHighlightedIdx != null ? defaultHighlightedIdx : highlightedIndexProp) != null ? _a : autoHighlightFirstItem ? 0 : -1
|
|
764
|
+
);
|
|
765
|
+
const [, forceRender] = (0, import_react7.useState)(null);
|
|
766
|
+
const setHighlightedIdx = (0, import_react7.useCallback)(
|
|
767
|
+
(idx) => {
|
|
768
|
+
highlightedIndexRef.current = idx;
|
|
769
|
+
onHighlight == null ? void 0 : onHighlight(idx);
|
|
770
|
+
forceRender({});
|
|
729
771
|
},
|
|
730
|
-
[
|
|
772
|
+
[onHighlight]
|
|
731
773
|
);
|
|
732
|
-
const
|
|
733
|
-
(
|
|
734
|
-
if (
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
const menus = openMenus.current.slice();
|
|
738
|
-
const lastMenu = menus.pop();
|
|
739
|
-
menuState.current[lastMenu.id] = "no-popup";
|
|
740
|
-
const parentMenu = menus.at(-1);
|
|
741
|
-
if (parentMenu) {
|
|
742
|
-
menuState.current[parentMenu.id] = "no-popup";
|
|
774
|
+
const setHighlightedIndex = (0, import_react7.useCallback)(
|
|
775
|
+
(idx) => {
|
|
776
|
+
if (idx !== highlightedIndexRef.current) {
|
|
777
|
+
if (!controlledHighlighting) {
|
|
778
|
+
setHighlightedIdx(idx);
|
|
743
779
|
}
|
|
744
|
-
setOpenMenus(menus);
|
|
745
780
|
}
|
|
746
781
|
},
|
|
747
|
-
[
|
|
782
|
+
[controlledHighlighting, setHighlightedIdx]
|
|
748
783
|
);
|
|
749
|
-
const
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
menuState.current[parentMenuId] = "no-popup";
|
|
759
|
-
({ id: lastMenuId } = menus[menus.length - 1]);
|
|
760
|
-
}
|
|
761
|
-
if (menus.length < openMenus.current.length) {
|
|
762
|
-
setOpenMenus(menus);
|
|
784
|
+
const keyBoardNavigation = (0, import_react7.useRef)(true);
|
|
785
|
+
const ignoreFocus = (0, import_react7.useRef)(false);
|
|
786
|
+
const setIgnoreFocus = (value) => ignoreFocus.current = value;
|
|
787
|
+
const highlightedIndex = controlledHighlighting ? highlightedIndexProp : highlightedIndexRef.current;
|
|
788
|
+
const navigateChildldItems = (0, import_react7.useCallback)(
|
|
789
|
+
(e) => {
|
|
790
|
+
const nextIdx = nextItemIdx(count, e.key, highlightedIndexRef.current);
|
|
791
|
+
if (nextIdx !== highlightedIndexRef.current) {
|
|
792
|
+
setHighlightedIndex(nextIdx);
|
|
763
793
|
}
|
|
764
794
|
},
|
|
765
|
-
[
|
|
766
|
-
);
|
|
767
|
-
const clearAnyScheduledOpenTasks = (0, import_react7.useCallback)(() => {
|
|
768
|
-
if (menuOpenPendingTimeout.current) {
|
|
769
|
-
clearTimeout(menuOpenPendingTimeout.current);
|
|
770
|
-
menuOpenPendingTimeout.current = void 0;
|
|
771
|
-
}
|
|
772
|
-
}, []);
|
|
773
|
-
const scheduleOpen = (0, import_react7.useCallback)(
|
|
774
|
-
(hostMenuId, targetMenuId, menuItemId, delay = 300) => {
|
|
775
|
-
clearAnyScheduledOpenTasks();
|
|
776
|
-
menuOpenPendingTimeout.current = window.setTimeout(() => {
|
|
777
|
-
closeMenus(menuItemId);
|
|
778
|
-
menuState.current[hostMenuId] = "popup-open";
|
|
779
|
-
menuState.current[targetMenuId] = "no-popup";
|
|
780
|
-
openMenu(hostMenuId, targetMenuId, menuItemId);
|
|
781
|
-
}, delay);
|
|
782
|
-
},
|
|
783
|
-
[clearAnyScheduledOpenTasks, closeMenus, openMenu]
|
|
784
|
-
);
|
|
785
|
-
const scheduleClose = (0, import_react7.useCallback)(
|
|
786
|
-
(hostMenuId, openMenuId, itemId) => {
|
|
787
|
-
menuState.current[openMenuId] = "pending-close";
|
|
788
|
-
menuClosePendingTimeout.current = window.setTimeout(() => {
|
|
789
|
-
closeMenus(itemId);
|
|
790
|
-
}, 400);
|
|
791
|
-
},
|
|
792
|
-
[closeMenus]
|
|
795
|
+
[count, setHighlightedIndex]
|
|
793
796
|
);
|
|
794
|
-
const
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
if (
|
|
802
|
-
const
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
if (typeof el.tabIndex === "number") {
|
|
809
|
-
el.focus();
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
}, [rootId, setOpenMenus]);
|
|
813
|
-
const triggerChildMenu = (0, import_react7.useCallback)(
|
|
814
|
-
(menuItemEl, immediate = false) => {
|
|
815
|
-
const { hostMenuId, targetMenuId, menuItemId, isGroup, isOpen } = getMenuItemDetails(menuItemEl, rootId);
|
|
816
|
-
const {
|
|
817
|
-
current: { [hostMenuId]: state }
|
|
818
|
-
} = menuState;
|
|
819
|
-
const delay = immediate ? 0 : void 0;
|
|
820
|
-
if (state === "no-popup" && isGroup) {
|
|
821
|
-
menuState.current[hostMenuId] = "popup-pending";
|
|
822
|
-
scheduleOpen(hostMenuId, targetMenuId, menuItemId, delay);
|
|
823
|
-
} else if (state === "popup-pending" && !isGroup) {
|
|
824
|
-
menuState.current[hostMenuId] = "no-popup";
|
|
825
|
-
clearTimeout(menuOpenPendingTimeout.current);
|
|
826
|
-
menuOpenPendingTimeout.current = void 0;
|
|
827
|
-
} else if (state === "popup-pending" && isGroup) {
|
|
828
|
-
clearTimeout(menuOpenPendingTimeout.current);
|
|
829
|
-
scheduleOpen(hostMenuId, targetMenuId, menuItemId, delay);
|
|
830
|
-
} else if (state === "popup-open") {
|
|
831
|
-
if (menuIsOpen(targetMenuId)) {
|
|
832
|
-
const menuStatus = getOpenMenuStatus(targetMenuId);
|
|
833
|
-
closeMenus(menuItemId);
|
|
834
|
-
switch (menuStatus) {
|
|
835
|
-
case "pending-close":
|
|
836
|
-
clearTimeout(menuClosePendingTimeout.current);
|
|
837
|
-
menuClosePendingTimeout.current = void 0;
|
|
838
|
-
menuState.current[targetMenuId] = "no-popup";
|
|
839
|
-
clearAnyScheduledOpenTasks();
|
|
840
|
-
break;
|
|
841
|
-
default:
|
|
842
|
-
}
|
|
843
|
-
} else {
|
|
844
|
-
const [parentOfLastOpenedMenu, lastOpenedMenu] = openMenus.current.slice(-2);
|
|
845
|
-
if (parentOfLastOpenedMenu.id === hostMenuId && menuState.current[lastOpenedMenu.id] !== "pending-close") {
|
|
846
|
-
scheduleClose(hostMenuId, lastOpenedMenu.id, menuItemId);
|
|
847
|
-
if (isGroup && !isOpen) {
|
|
848
|
-
scheduleOpen(hostMenuId, targetMenuId, menuItemId, delay);
|
|
849
|
-
}
|
|
850
|
-
} else if (parentOfLastOpenedMenu.id === hostMenuId && isGroup && menuItemId !== lastOpenedMenu.id && menuState.current[lastOpenedMenu.id] === "pending-close") {
|
|
851
|
-
scheduleOpen(hostMenuId, targetMenuId, menuItemId, delay);
|
|
852
|
-
} else if (isGroup) {
|
|
853
|
-
scheduleOpen(hostMenuId, targetMenuId, menuItemId, delay);
|
|
854
|
-
} else if (!(menuState.current[lastOpenedMenu.id] === "pending-close")) {
|
|
855
|
-
closeMenus(menuItemId);
|
|
856
|
-
}
|
|
797
|
+
const handleKeyDown = (0, import_react7.useCallback)(
|
|
798
|
+
(e) => {
|
|
799
|
+
if (isNavigationKey(e)) {
|
|
800
|
+
e.preventDefault();
|
|
801
|
+
e.stopPropagation();
|
|
802
|
+
keyBoardNavigation.current = true;
|
|
803
|
+
navigateChildldItems(e);
|
|
804
|
+
} else if ((e.key === "ArrowRight" || e.key === "Enter") && hasPopup(e.target, highlightedIndex)) {
|
|
805
|
+
const menuEl = e.target;
|
|
806
|
+
const menuItemEl = menuEl.querySelector(
|
|
807
|
+
`:scope > [data-index='${highlightedIndex}']`
|
|
808
|
+
);
|
|
809
|
+
if (menuItemEl) {
|
|
810
|
+
onOpenMenu == null ? void 0 : onOpenMenu(menuItemEl, true);
|
|
857
811
|
}
|
|
858
|
-
}
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
812
|
+
} else if (e.key === "ArrowLeft" && !isRoot(e.target)) {
|
|
813
|
+
onCloseMenu(highlightedIndex);
|
|
814
|
+
} else if (e.key === "Enter") {
|
|
815
|
+
e.preventDefault();
|
|
816
|
+
e.stopPropagation();
|
|
817
|
+
onActivate && onActivate(highlightedIndex);
|
|
818
|
+
} else if (e.key === "Tab") {
|
|
819
|
+
onCloseMenu(-1);
|
|
864
820
|
}
|
|
865
821
|
},
|
|
866
822
|
[
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
scheduleClose,
|
|
873
|
-
scheduleOpen
|
|
823
|
+
highlightedIndex,
|
|
824
|
+
navigateChildldItems,
|
|
825
|
+
onActivate,
|
|
826
|
+
onCloseMenu,
|
|
827
|
+
onOpenMenu
|
|
874
828
|
]
|
|
875
829
|
);
|
|
876
|
-
const
|
|
830
|
+
const listProps = (0, import_react7.useMemo)(
|
|
877
831
|
() => ({
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
832
|
+
onFocus: () => {
|
|
833
|
+
if (highlightedIndex === -1) {
|
|
834
|
+
setHighlightedIdx(0);
|
|
835
|
+
}
|
|
882
836
|
},
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
837
|
+
onKeyDown: handleKeyDown,
|
|
838
|
+
onMouseDownCapture: () => {
|
|
839
|
+
keyBoardNavigation.current = false;
|
|
840
|
+
setIgnoreFocus(true);
|
|
841
|
+
},
|
|
842
|
+
// onMouseEnter would seem less expensive but it misses some cases
|
|
843
|
+
onMouseMove: () => {
|
|
844
|
+
if (keyBoardNavigation.current) {
|
|
845
|
+
keyBoardNavigation.current = false;
|
|
890
846
|
}
|
|
847
|
+
},
|
|
848
|
+
onMouseLeave: () => {
|
|
849
|
+
keyBoardNavigation.current = true;
|
|
850
|
+
setIgnoreFocus(false);
|
|
851
|
+
setHighlightedIndex(-1);
|
|
891
852
|
}
|
|
892
853
|
}),
|
|
893
|
-
[
|
|
854
|
+
[handleKeyDown, highlightedIndex, setHighlightedIdx, setHighlightedIndex]
|
|
894
855
|
);
|
|
895
856
|
return {
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
857
|
+
focusVisible: keyBoardNavigation.current ? highlightedIndex : -1,
|
|
858
|
+
controlledHighlighting,
|
|
859
|
+
highlightedIndex,
|
|
860
|
+
setHighlightedIndex,
|
|
861
|
+
// keyBoardNavigation,
|
|
862
|
+
listProps,
|
|
863
|
+
setIgnoreFocus
|
|
901
864
|
};
|
|
902
865
|
};
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
var import_react9 = require("react");
|
|
908
|
-
var noop = () => void 0;
|
|
909
|
-
var ContextMenu = ({
|
|
910
|
-
PortalProps: PortalProps2,
|
|
911
|
-
activatedByKeyboard,
|
|
912
|
-
children: childrenProp,
|
|
913
|
-
className,
|
|
914
|
-
id: idProp,
|
|
915
|
-
onClose = () => void 0,
|
|
916
|
-
position = { x: 0, y: 0 },
|
|
917
|
-
style,
|
|
918
|
-
...menuListProps
|
|
919
|
-
}) => {
|
|
920
|
-
const closeHandlerRef = (0, import_react8.useRef)(onClose);
|
|
921
|
-
closeHandlerRef.current = onClose;
|
|
922
|
-
const id = (0, import_vuu_layout2.useId)(idProp);
|
|
923
|
-
const closeMenuRef = (0, import_react8.useRef)(noop);
|
|
924
|
-
const [menus, actions] = useItemsWithIdsNext(childrenProp, id);
|
|
925
|
-
const navigatingWithKeyboard = (0, import_react8.useRef)(activatedByKeyboard);
|
|
926
|
-
const handleMouseEnterItem = (0, import_react8.useCallback)(() => {
|
|
927
|
-
navigatingWithKeyboard.current = false;
|
|
928
|
-
}, []);
|
|
929
|
-
const handleActivate = (0, import_react8.useCallback)(
|
|
930
|
-
(menuItemId) => {
|
|
931
|
-
const actionId = menuItemId.slice(9);
|
|
932
|
-
const { action, options } = actions[actionId];
|
|
933
|
-
closeMenuRef.current(id);
|
|
934
|
-
onClose({
|
|
935
|
-
type: "menu-action",
|
|
936
|
-
menuId: action,
|
|
937
|
-
options
|
|
938
|
-
});
|
|
939
|
-
},
|
|
940
|
-
[actions, id, onClose]
|
|
941
|
-
);
|
|
942
|
-
const {
|
|
943
|
-
closeMenu,
|
|
944
|
-
listItemProps,
|
|
945
|
-
openMenu: onOpenMenu,
|
|
946
|
-
openMenus,
|
|
947
|
-
handleRender
|
|
948
|
-
} = useCascade({
|
|
949
|
-
// FIXME
|
|
950
|
-
id: `${id}`,
|
|
951
|
-
onActivate: handleActivate,
|
|
952
|
-
onMouseEnterItem: handleMouseEnterItem,
|
|
953
|
-
position
|
|
954
|
-
});
|
|
955
|
-
closeMenuRef.current = closeMenu;
|
|
956
|
-
const handleCloseMenu = () => {
|
|
957
|
-
navigatingWithKeyboard.current = true;
|
|
958
|
-
closeMenu();
|
|
959
|
-
};
|
|
960
|
-
const handleHighlightMenuItem = () => {
|
|
961
|
-
};
|
|
962
|
-
const lastMenu = openMenus.length - 1;
|
|
963
|
-
const getChildMenuId = (i) => {
|
|
964
|
-
if (i >= lastMenu) {
|
|
965
|
-
return void 0;
|
|
866
|
+
function nextItemIdx(count, key, idx) {
|
|
867
|
+
if (key === "ArrowUp") {
|
|
868
|
+
if (idx > 0) {
|
|
869
|
+
return idx - 1;
|
|
966
870
|
} else {
|
|
967
|
-
|
|
968
|
-
return id2;
|
|
871
|
+
return idx;
|
|
969
872
|
}
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
MenuList,
|
|
981
|
-
{
|
|
982
|
-
...menuListProps,
|
|
983
|
-
activatedByKeyboard: navigatingWithKeyboard.current,
|
|
984
|
-
childMenuShowing: childMenuId,
|
|
985
|
-
className,
|
|
986
|
-
id: menuId,
|
|
987
|
-
isRoot: i === 0,
|
|
988
|
-
key: i,
|
|
989
|
-
listItemProps,
|
|
990
|
-
onActivate: handleActivate,
|
|
991
|
-
onHighlightMenuItem: handleHighlightMenuItem,
|
|
992
|
-
onCloseMenu: handleCloseMenu,
|
|
993
|
-
openMenu: onOpenMenu,
|
|
994
|
-
style,
|
|
995
|
-
tabIndex: i === all.length - 1 ? 0 : void 0
|
|
996
|
-
},
|
|
997
|
-
menus[menuId]
|
|
998
|
-
)
|
|
999
|
-
}
|
|
1000
|
-
));
|
|
1001
|
-
}) });
|
|
1002
|
-
};
|
|
1003
|
-
ContextMenu.displayName = "ContextMenu";
|
|
873
|
+
} else {
|
|
874
|
+
if (idx === null) {
|
|
875
|
+
return 0;
|
|
876
|
+
} else if (idx === count - 1) {
|
|
877
|
+
return idx;
|
|
878
|
+
} else {
|
|
879
|
+
return idx + 1;
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
}
|
|
1004
883
|
|
|
1005
|
-
// src/menu/
|
|
1006
|
-
var
|
|
1007
|
-
var
|
|
1008
|
-
var
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
var Provider = ({
|
|
884
|
+
// src/menu/MenuList.tsx
|
|
885
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
886
|
+
var classBase3 = "vuuMenuList";
|
|
887
|
+
var Separator = () => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("li", { className: "vuuMenuItem-divider" });
|
|
888
|
+
var MenuItemGroup = () => null;
|
|
889
|
+
var MenuItem = ({
|
|
1012
890
|
children,
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
891
|
+
idx,
|
|
892
|
+
options,
|
|
893
|
+
...props
|
|
1016
894
|
}) => {
|
|
1017
|
-
|
|
1018
|
-
if ((context == null ? void 0 : context.menuBuilders) && menuBuilder) {
|
|
1019
|
-
return context.menuBuilders.concat(menuBuilder);
|
|
1020
|
-
} else if (menuBuilder) {
|
|
1021
|
-
return [menuBuilder];
|
|
1022
|
-
} else {
|
|
1023
|
-
return (context == null ? void 0 : context.menuBuilders) || [];
|
|
1024
|
-
}
|
|
1025
|
-
}, [context, menuBuilder]);
|
|
1026
|
-
const handleMenuAction = (0, import_react10.useCallback)(
|
|
1027
|
-
(reason) => {
|
|
1028
|
-
var _a;
|
|
1029
|
-
if (menuActionHandler == null ? void 0 : menuActionHandler(reason)) {
|
|
1030
|
-
return true;
|
|
1031
|
-
}
|
|
1032
|
-
if ((_a = context == null ? void 0 : context.menuActionHandler) == null ? void 0 : _a.call(context, reason)) {
|
|
1033
|
-
return true;
|
|
1034
|
-
}
|
|
1035
|
-
},
|
|
1036
|
-
[context, menuActionHandler]
|
|
1037
|
-
);
|
|
1038
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1039
|
-
ContextMenuContext.Provider,
|
|
1040
|
-
{
|
|
1041
|
-
value: {
|
|
1042
|
-
menuActionHandler: handleMenuAction,
|
|
1043
|
-
menuBuilders
|
|
1044
|
-
},
|
|
1045
|
-
children
|
|
1046
|
-
}
|
|
1047
|
-
);
|
|
895
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { ...props, children });
|
|
1048
896
|
};
|
|
1049
|
-
var
|
|
897
|
+
var MenuItemLabel = ({ children }) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children });
|
|
898
|
+
MenuItemLabel.displayName = "MenuItemLabel";
|
|
899
|
+
MenuItem.Label = MenuItemLabel;
|
|
900
|
+
var getDisplayName = (item) => import_react8.default.isValidElement(item) && typeof item.type !== "string" && "displayName" in item.type ? item.type.displayName : void 0;
|
|
901
|
+
var isMenuItemLabel = (item) => getDisplayName(item) === "MenuItemLabel";
|
|
902
|
+
var hasIcon = (child) => child.props["data-icon"];
|
|
903
|
+
var MenuList = ({
|
|
904
|
+
activatedByKeyboard,
|
|
905
|
+
childMenuShowing,
|
|
1050
906
|
children,
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
907
|
+
className,
|
|
908
|
+
defaultHighlightedIdx,
|
|
909
|
+
highlightedIdx: highlightedIdxProp,
|
|
910
|
+
id: idProp,
|
|
911
|
+
isRoot: isRoot2,
|
|
912
|
+
listItemProps,
|
|
913
|
+
onHighlightMenuItem,
|
|
914
|
+
onActivate,
|
|
915
|
+
onCloseMenu,
|
|
916
|
+
openMenu: onOpenMenu,
|
|
917
|
+
...props
|
|
1054
918
|
}) => {
|
|
1055
|
-
|
|
1056
|
-
|
|
919
|
+
const id = (0, import_vuu_utils4.useId)(idProp);
|
|
920
|
+
const root = (0, import_react8.useRef)(null);
|
|
921
|
+
const mapIdxToId = (0, import_react8.useMemo)(() => /* @__PURE__ */ new Map(), []);
|
|
922
|
+
const handleActivate = (idx) => {
|
|
923
|
+
var _a;
|
|
924
|
+
const el = (_a = root.current) == null ? void 0 : _a.querySelector(`:scope > [data-index='${idx}']`);
|
|
925
|
+
(el == null ? void 0 : el.id) && (onActivate == null ? void 0 : onActivate(el.id));
|
|
926
|
+
};
|
|
927
|
+
const { focusVisible, highlightedIndex, listProps } = useKeyboardNavigation({
|
|
928
|
+
count: import_react8.default.Children.count(children),
|
|
929
|
+
defaultHighlightedIdx,
|
|
930
|
+
highlightedIndex: highlightedIdxProp,
|
|
931
|
+
onActivate: handleActivate,
|
|
932
|
+
onHighlight: onHighlightMenuItem,
|
|
933
|
+
onOpenMenu,
|
|
934
|
+
onCloseMenu
|
|
935
|
+
});
|
|
936
|
+
const appliedFocusVisible = childMenuShowing == void 0 ? focusVisible : -1;
|
|
937
|
+
(0, import_react8.useLayoutEffect)(() => {
|
|
938
|
+
var _a;
|
|
939
|
+
if (childMenuShowing === void 0 && activatedByKeyboard) {
|
|
940
|
+
(_a = root.current) == null ? void 0 : _a.focus();
|
|
941
|
+
}
|
|
942
|
+
}, [activatedByKeyboard, childMenuShowing]);
|
|
943
|
+
const getActiveDescendant = () => highlightedIndex === void 0 || highlightedIndex === -1 ? void 0 : mapIdxToId.get(highlightedIndex);
|
|
944
|
+
function renderContent() {
|
|
945
|
+
const propsCommonToAllListItems = {
|
|
946
|
+
...listItemProps,
|
|
947
|
+
role: "menuitem"
|
|
948
|
+
};
|
|
949
|
+
const maybeIcon = (childElement, withIcon, iconName) => withIcon ? [
|
|
950
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
951
|
+
"span",
|
|
952
|
+
{
|
|
953
|
+
className: "vuuIconContainer",
|
|
954
|
+
"data-icon": iconName
|
|
955
|
+
},
|
|
956
|
+
"icon"
|
|
957
|
+
)
|
|
958
|
+
].concat(childElement) : childElement;
|
|
959
|
+
function addClonedChild(list, child, idx, withIcon) {
|
|
960
|
+
var _a;
|
|
961
|
+
const {
|
|
962
|
+
children: children2,
|
|
963
|
+
className: className2,
|
|
964
|
+
"data-icon": iconName,
|
|
965
|
+
id: itemId,
|
|
966
|
+
hasSeparator,
|
|
967
|
+
label,
|
|
968
|
+
...props2
|
|
969
|
+
} = child.props;
|
|
970
|
+
const hasSubMenu = isMenuItemGroup(child);
|
|
971
|
+
const subMenuShowing = hasSubMenu && childMenuShowing === itemId;
|
|
972
|
+
const ariaControls = subMenuShowing ? `${id}-${itemId}` : void 0;
|
|
973
|
+
list.push(
|
|
974
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
975
|
+
MenuItem,
|
|
976
|
+
{
|
|
977
|
+
...props2,
|
|
978
|
+
...propsCommonToAllListItems,
|
|
979
|
+
...getMenuItemProps(
|
|
980
|
+
itemId,
|
|
981
|
+
idx,
|
|
982
|
+
(_a = child.key) != null ? _a : itemId,
|
|
983
|
+
highlightedIndex,
|
|
984
|
+
appliedFocusVisible,
|
|
985
|
+
className2,
|
|
986
|
+
hasSeparator
|
|
987
|
+
),
|
|
988
|
+
"aria-controls": ariaControls,
|
|
989
|
+
"aria-haspopup": hasSubMenu || void 0,
|
|
990
|
+
"aria-expanded": subMenuShowing || void 0,
|
|
991
|
+
children: hasSubMenu ? maybeIcon(label != null ? label : children2, withIcon, iconName) : maybeIcon(children2, withIcon, iconName)
|
|
992
|
+
}
|
|
993
|
+
)
|
|
994
|
+
);
|
|
995
|
+
}
|
|
996
|
+
const listItems = [];
|
|
997
|
+
if (children.length > 0) {
|
|
998
|
+
const withIcon = children.some(hasIcon);
|
|
999
|
+
children.forEach((child, idx) => {
|
|
1000
|
+
addClonedChild(listItems, child, idx, withIcon);
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
return listItems;
|
|
1004
|
+
}
|
|
1005
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1006
|
+
"div",
|
|
1057
1007
|
{
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1008
|
+
...props,
|
|
1009
|
+
...listProps,
|
|
1010
|
+
"aria-activedescendant": getActiveDescendant(),
|
|
1011
|
+
className: (0, import_clsx6.default)(classBase3, className, {
|
|
1012
|
+
[`${classBase3}-childMenuShowing`]: childMenuShowing !== void 0
|
|
1013
|
+
}),
|
|
1014
|
+
"data-root": isRoot2 || void 0,
|
|
1015
|
+
id,
|
|
1016
|
+
ref: root,
|
|
1017
|
+
role: "menu",
|
|
1018
|
+
children: renderContent()
|
|
1063
1019
|
}
|
|
1064
|
-
)
|
|
1020
|
+
);
|
|
1065
1021
|
};
|
|
1022
|
+
var getMenuItemProps = (itemId, idx, key, highlightedIdx, focusVisible, className, hasSeparator) => ({
|
|
1023
|
+
id: `menuitem-${itemId}`,
|
|
1024
|
+
key: key != null ? key : idx,
|
|
1025
|
+
"data-index": idx,
|
|
1026
|
+
"data-highlighted": idx === highlightedIdx || void 0,
|
|
1027
|
+
className: (0, import_clsx6.default)("vuuMenuItem", className, {
|
|
1028
|
+
"vuuMenuItem-separator": hasSeparator,
|
|
1029
|
+
focusVisible: focusVisible === idx
|
|
1030
|
+
})
|
|
1031
|
+
});
|
|
1032
|
+
MenuList.displayName = "MenuList";
|
|
1066
1033
|
|
|
1067
|
-
// src/menu/
|
|
1068
|
-
var
|
|
1069
|
-
var import_react13 = require("react");
|
|
1070
|
-
|
|
1071
|
-
// src/popup/popup-service.ts
|
|
1072
|
-
var import_classnames5 = __toESM(require("classnames"));
|
|
1073
|
-
var import_react11 = __toESM(require("react"));
|
|
1074
|
-
var import_react_dom2 = __toESM(require("react-dom"));
|
|
1034
|
+
// src/menu/use-cascade.ts
|
|
1035
|
+
var import_react9 = require("react");
|
|
1075
1036
|
|
|
1076
|
-
// src/
|
|
1077
|
-
var
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
var
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1037
|
+
// src/menu/list-dom-utils.ts
|
|
1038
|
+
var closestListItem = (el) => el == null ? void 0 : el.closest("[data-index],[aria-posinset]");
|
|
1039
|
+
|
|
1040
|
+
// src/menu/use-cascade.ts
|
|
1041
|
+
var nudge = (menus, distance, pos) => {
|
|
1042
|
+
return menus.map(
|
|
1043
|
+
(m, i) => i === menus.length - 1 ? {
|
|
1044
|
+
...m,
|
|
1045
|
+
[pos]: m[pos] - distance
|
|
1046
|
+
} : m
|
|
1047
|
+
);
|
|
1048
|
+
};
|
|
1049
|
+
var nudgeLeft = (menus, distance) => nudge(menus, distance, "left");
|
|
1050
|
+
var nudgeUp = (menus, distance) => nudge(menus, distance, "top");
|
|
1051
|
+
var flipSides = (id, menus) => {
|
|
1052
|
+
const [parentMenu, menu] = menus.slice(-2);
|
|
1053
|
+
const el = document.getElementById(`${id}-${menu.id}`);
|
|
1054
|
+
if (el === null) {
|
|
1055
|
+
throw Error(`useCascade.flipSides element with id ${menu.id} not found`);
|
|
1092
1056
|
}
|
|
1093
|
-
|
|
1094
|
-
return
|
|
1057
|
+
const { width } = el.getBoundingClientRect();
|
|
1058
|
+
return menus.map(
|
|
1059
|
+
(m) => m === menu ? {
|
|
1060
|
+
...m,
|
|
1061
|
+
left: parentMenu.left - (width - 2)
|
|
1062
|
+
} : m
|
|
1063
|
+
);
|
|
1095
1064
|
};
|
|
1096
|
-
var
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1065
|
+
var getPosition = (el, openMenus) => {
|
|
1066
|
+
const [{ left, top: menuTop }] = openMenus.slice(-1);
|
|
1067
|
+
const { offsetWidth: width, offsetTop: top } = el;
|
|
1068
|
+
return { left: left + width, top: top + menuTop };
|
|
1100
1069
|
};
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
function specialKeyHandler(e) {
|
|
1108
|
-
if (e.key === "Esc") {
|
|
1109
|
-
if (_popups.length) {
|
|
1110
|
-
closeAllPopups();
|
|
1111
|
-
} else if (_dialogOpen) {
|
|
1112
|
-
const dialogRoot = document.body.querySelector(".vuuDialog");
|
|
1113
|
-
if (dialogRoot) {
|
|
1114
|
-
import_react_dom2.default.unmountComponentAtNode(dialogRoot);
|
|
1115
|
-
}
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
}
|
|
1119
|
-
function outsideClickHandler(e) {
|
|
1120
|
-
if (_popups.length) {
|
|
1121
|
-
const popupContainers = document.body.querySelectorAll(
|
|
1122
|
-
".vuuPopup,#vuu-portal-root"
|
|
1123
|
-
);
|
|
1124
|
-
for (let i = 0; i < popupContainers.length; i++) {
|
|
1125
|
-
if (popupContainers[i].contains(e.target)) {
|
|
1126
|
-
return;
|
|
1127
|
-
}
|
|
1128
|
-
}
|
|
1129
|
-
closeAllPopups({ mouseEvt: e, type: "click-away" });
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
function closeAllPopups(reason) {
|
|
1133
|
-
if (_popups.length === 1) {
|
|
1134
|
-
PopupService.hidePopup(reason, "anon", "all");
|
|
1135
|
-
} else if (_popups.length) {
|
|
1136
|
-
const popupContainers = document.body.querySelectorAll(".vuuPopup");
|
|
1137
|
-
for (let i = 0; i < popupContainers.length; i++) {
|
|
1138
|
-
import_react_dom2.default.unmountComponentAtNode(popupContainers[i]);
|
|
1139
|
-
}
|
|
1140
|
-
popupClosed("*");
|
|
1141
|
-
}
|
|
1142
|
-
}
|
|
1143
|
-
function dialogOpened() {
|
|
1144
|
-
if (_dialogOpen === false) {
|
|
1145
|
-
_dialogOpen = true;
|
|
1146
|
-
window.addEventListener("keydown", specialKeyHandler, true);
|
|
1147
|
-
}
|
|
1148
|
-
}
|
|
1149
|
-
function dialogClosed() {
|
|
1150
|
-
if (_dialogOpen) {
|
|
1151
|
-
_dialogOpen = false;
|
|
1152
|
-
window.removeEventListener("keydown", specialKeyHandler, true);
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
function popupOpened(name) {
|
|
1156
|
-
if (_popups.indexOf(name) === -1) {
|
|
1157
|
-
_popups.push(name);
|
|
1158
|
-
if (_dialogOpen === false) {
|
|
1159
|
-
window.addEventListener("keydown", specialKeyHandler, true);
|
|
1160
|
-
window.addEventListener("click", outsideClickHandler, true);
|
|
1161
|
-
}
|
|
1070
|
+
var getHostMenuId = (id, rootId) => {
|
|
1071
|
+
const pos = id.lastIndexOf("-");
|
|
1072
|
+
if (id.startsWith("menuitem")) {
|
|
1073
|
+
return pos > -1 ? id.slice(9, pos) : rootId;
|
|
1074
|
+
} else {
|
|
1075
|
+
return pos > -1 ? id.slice(0, pos) : rootId;
|
|
1162
1076
|
}
|
|
1163
|
-
}
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
}
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
window.removeEventListener("click", outsideClickHandler, true);
|
|
1177
|
-
}
|
|
1077
|
+
};
|
|
1078
|
+
var getTargetMenuId = (id) => id.slice(9);
|
|
1079
|
+
var getMenuItemDetails = ({ ariaExpanded, ariaHasPopup, id }, rootId) => {
|
|
1080
|
+
if (id.startsWith("menuitem")) {
|
|
1081
|
+
return {
|
|
1082
|
+
hostMenuId: getHostMenuId(id, rootId),
|
|
1083
|
+
targetMenuId: getTargetMenuId(id),
|
|
1084
|
+
menuItemId: id,
|
|
1085
|
+
isGroup: ariaHasPopup === "true",
|
|
1086
|
+
isOpen: ariaExpanded === "true"
|
|
1087
|
+
};
|
|
1088
|
+
} else {
|
|
1089
|
+
throw Error(`getMenuItemDetails #${id} is not a menuitem`);
|
|
1178
1090
|
}
|
|
1179
|
-
}
|
|
1180
|
-
var PopupComponent2 = ({
|
|
1181
|
-
children,
|
|
1182
|
-
position,
|
|
1183
|
-
style
|
|
1184
|
-
}) => {
|
|
1185
|
-
const className = (0, import_classnames5.default)("hwPopup", "hwPopupContainer", position);
|
|
1186
|
-
return (0, import_react11.createElement)("div", { className, style }, children);
|
|
1187
1091
|
};
|
|
1188
|
-
var
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
top
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
PopupService.onClose = void 0;
|
|
1207
|
-
}
|
|
1208
|
-
popupOpened(name);
|
|
1209
|
-
document.addEventListener("keydown", PopupService.escapeKeyListener, true);
|
|
1210
|
-
let el = document.body.querySelector(".vuuPopup." + group);
|
|
1211
|
-
if (el === null) {
|
|
1212
|
-
el = document.createElement("div");
|
|
1213
|
-
el.className = "vuuPopup " + group;
|
|
1214
|
-
document.body.appendChild(el);
|
|
1092
|
+
var useCascade = ({
|
|
1093
|
+
id: rootId,
|
|
1094
|
+
onActivate,
|
|
1095
|
+
onMouseEnterItem,
|
|
1096
|
+
position: { x: posX, y: posY }
|
|
1097
|
+
}) => {
|
|
1098
|
+
const [, forceRefresh] = (0, import_react9.useState)({});
|
|
1099
|
+
const openMenus = (0, import_react9.useRef)([
|
|
1100
|
+
{ id: rootId, left: posX, top: posY }
|
|
1101
|
+
]);
|
|
1102
|
+
const menuIsOpen = (0, import_react9.useCallback)(
|
|
1103
|
+
(menuId) => openMenus.current.findIndex((menu) => menu.id === menuId) !== -1,
|
|
1104
|
+
[]
|
|
1105
|
+
);
|
|
1106
|
+
const getOpenMenuStatus = (0, import_react9.useCallback)((menuId) => {
|
|
1107
|
+
const state = menuState.current[menuId];
|
|
1108
|
+
if (state === void 0) {
|
|
1109
|
+
throw Error(`getOpenMenuState no entry for menu ${menuId}`);
|
|
1215
1110
|
}
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1111
|
+
return state;
|
|
1112
|
+
}, []);
|
|
1113
|
+
const setOpenMenus = (0, import_react9.useCallback)((menus) => {
|
|
1114
|
+
openMenus.current = menus;
|
|
1115
|
+
forceRefresh({});
|
|
1116
|
+
}, []);
|
|
1117
|
+
const menuOpenPendingTimeout = (0, import_react9.useRef)();
|
|
1118
|
+
const menuClosePendingTimeout = (0, import_react9.useRef)();
|
|
1119
|
+
const menuState = (0, import_react9.useRef)({ [rootId]: "no-popup" });
|
|
1120
|
+
const openMenu = (0, import_react9.useCallback)(
|
|
1121
|
+
(hostMenuId = rootId, targetMenuId, itemId = null) => {
|
|
1122
|
+
if (hostMenuId === rootId && itemId === null) {
|
|
1123
|
+
setOpenMenus([{ id: rootId, left: posX, top: posY }]);
|
|
1124
|
+
} else {
|
|
1125
|
+
menuState.current[hostMenuId] = "popup-open";
|
|
1126
|
+
const el = document.getElementById(itemId);
|
|
1127
|
+
if (el !== null) {
|
|
1128
|
+
const { left, top } = getPosition(el, openMenus.current);
|
|
1129
|
+
setOpenMenus(
|
|
1130
|
+
openMenus.current.concat({ id: targetMenuId, left, top })
|
|
1131
|
+
);
|
|
1132
|
+
} else {
|
|
1133
|
+
throw Error(`openMenu no menuItem ${itemId}`);
|
|
1134
|
+
}
|
|
1228
1135
|
}
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1136
|
+
},
|
|
1137
|
+
[rootId, posX, posY, setOpenMenus]
|
|
1138
|
+
);
|
|
1139
|
+
const closeMenu = (0, import_react9.useCallback)(
|
|
1140
|
+
(menuId) => {
|
|
1141
|
+
if (menuId === rootId) {
|
|
1142
|
+
setOpenMenus([]);
|
|
1143
|
+
} else {
|
|
1144
|
+
const menus = openMenus.current.slice();
|
|
1145
|
+
const lastMenu = menus.pop();
|
|
1146
|
+
menuState.current[lastMenu.id] = "no-popup";
|
|
1147
|
+
const parentMenu = menus.at(-1);
|
|
1148
|
+
if (parentMenu) {
|
|
1149
|
+
menuState.current[parentMenu.id] = "no-popup";
|
|
1150
|
+
}
|
|
1151
|
+
setOpenMenus(menus);
|
|
1152
|
+
}
|
|
1153
|
+
},
|
|
1154
|
+
[rootId, setOpenMenus]
|
|
1155
|
+
);
|
|
1156
|
+
const closeMenus = (0, import_react9.useCallback)(
|
|
1157
|
+
(menuItemId) => {
|
|
1158
|
+
const menus = openMenus.current.slice();
|
|
1159
|
+
const menuItemMenuId = menuItemId.slice(9);
|
|
1160
|
+
let { id: lastMenuId } = menus.at(-1);
|
|
1161
|
+
while (menus.length > 1 && !menuItemMenuId.startsWith(lastMenuId)) {
|
|
1162
|
+
const parentMenuId = getHostMenuId(lastMenuId, rootId);
|
|
1163
|
+
menus.pop();
|
|
1164
|
+
menuState.current[lastMenuId] = "no-popup";
|
|
1165
|
+
menuState.current[parentMenuId] = "no-popup";
|
|
1166
|
+
({ id: lastMenuId } = menus[menus.length - 1]);
|
|
1167
|
+
}
|
|
1168
|
+
if (menus.length < openMenus.current.length) {
|
|
1169
|
+
setOpenMenus(menus);
|
|
1170
|
+
}
|
|
1171
|
+
},
|
|
1172
|
+
[rootId, setOpenMenus]
|
|
1173
|
+
);
|
|
1174
|
+
const clearAnyScheduledOpenTasks = (0, import_react9.useCallback)(() => {
|
|
1175
|
+
if (menuOpenPendingTimeout.current) {
|
|
1176
|
+
clearTimeout(menuOpenPendingTimeout.current);
|
|
1177
|
+
menuOpenPendingTimeout.current = void 0;
|
|
1234
1178
|
}
|
|
1235
|
-
}
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1179
|
+
}, []);
|
|
1180
|
+
const scheduleOpen = (0, import_react9.useCallback)(
|
|
1181
|
+
(hostMenuId, targetMenuId, menuItemId, delay = 300) => {
|
|
1182
|
+
clearAnyScheduledOpenTasks();
|
|
1183
|
+
menuOpenPendingTimeout.current = window.setTimeout(() => {
|
|
1184
|
+
closeMenus(menuItemId);
|
|
1185
|
+
menuState.current[hostMenuId] = "popup-open";
|
|
1186
|
+
menuState.current[targetMenuId] = "no-popup";
|
|
1187
|
+
openMenu(hostMenuId, targetMenuId, menuItemId);
|
|
1188
|
+
}, delay);
|
|
1189
|
+
},
|
|
1190
|
+
[clearAnyScheduledOpenTasks, closeMenus, openMenu]
|
|
1191
|
+
);
|
|
1192
|
+
const scheduleClose = (0, import_react9.useCallback)(
|
|
1193
|
+
(hostMenuId, openMenuId, itemId) => {
|
|
1194
|
+
menuState.current[openMenuId] = "pending-close";
|
|
1195
|
+
menuClosePendingTimeout.current = window.setTimeout(() => {
|
|
1196
|
+
closeMenus(itemId);
|
|
1197
|
+
}, 400);
|
|
1198
|
+
},
|
|
1199
|
+
[closeMenus]
|
|
1200
|
+
);
|
|
1201
|
+
const handleRender = (0, import_react9.useCallback)(() => {
|
|
1202
|
+
const { current: menus } = openMenus;
|
|
1203
|
+
const menu = menus.at(-1);
|
|
1204
|
+
const el = menu ? document.getElementById(menu.id) : void 0;
|
|
1205
|
+
if (el) {
|
|
1206
|
+
const { right, bottom } = el.getBoundingClientRect();
|
|
1207
|
+
const { clientHeight, clientWidth } = document.body;
|
|
1208
|
+
if (right > clientWidth) {
|
|
1209
|
+
const newMenus = menus.length > 1 ? flipSides(rootId, menus) : nudgeLeft(menus, right - clientWidth);
|
|
1210
|
+
setOpenMenus(newMenus);
|
|
1211
|
+
} else if (bottom > clientHeight) {
|
|
1212
|
+
const newMenus = nudgeUp(menus, bottom - clientHeight);
|
|
1213
|
+
setOpenMenus(newMenus);
|
|
1214
|
+
}
|
|
1215
|
+
if (typeof el.tabIndex === "number") {
|
|
1216
|
+
el.focus();
|
|
1243
1217
|
}
|
|
1244
1218
|
}
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
);
|
|
1250
|
-
(_a = PopupService == null ? void 0 : PopupService.onClose) == null ? void 0 : _a.call(PopupService, reason);
|
|
1251
|
-
}
|
|
1252
|
-
static keepWithinThePage(el, right = "auto") {
|
|
1253
|
-
const target = el.querySelector(".vuuPopupContainer > *");
|
|
1254
|
-
if (target) {
|
|
1219
|
+
}, [rootId, setOpenMenus]);
|
|
1220
|
+
const triggerChildMenu = (0, import_react9.useCallback)(
|
|
1221
|
+
(menuItemEl, immediate = false) => {
|
|
1222
|
+
const { hostMenuId, targetMenuId, menuItemId, isGroup, isOpen } = getMenuItemDetails(menuItemEl, rootId);
|
|
1255
1223
|
const {
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1224
|
+
current: { [hostMenuId]: state }
|
|
1225
|
+
} = menuState;
|
|
1226
|
+
const delay = immediate ? 0 : void 0;
|
|
1227
|
+
if (state === "no-popup" && isGroup) {
|
|
1228
|
+
menuState.current[hostMenuId] = "popup-pending";
|
|
1229
|
+
scheduleOpen(hostMenuId, targetMenuId, menuItemId, delay);
|
|
1230
|
+
} else if (state === "popup-pending" && !isGroup) {
|
|
1231
|
+
menuState.current[hostMenuId] = "no-popup";
|
|
1232
|
+
clearTimeout(menuOpenPendingTimeout.current);
|
|
1233
|
+
menuOpenPendingTimeout.current = void 0;
|
|
1234
|
+
} else if (state === "popup-pending" && isGroup) {
|
|
1235
|
+
clearTimeout(menuOpenPendingTimeout.current);
|
|
1236
|
+
scheduleOpen(hostMenuId, targetMenuId, menuItemId, delay);
|
|
1237
|
+
} else if (state === "popup-open") {
|
|
1238
|
+
if (menuIsOpen(targetMenuId)) {
|
|
1239
|
+
const menuStatus = getOpenMenuStatus(targetMenuId);
|
|
1240
|
+
closeMenus(menuItemId);
|
|
1241
|
+
switch (menuStatus) {
|
|
1242
|
+
case "pending-close":
|
|
1243
|
+
clearTimeout(menuClosePendingTimeout.current);
|
|
1244
|
+
menuClosePendingTimeout.current = void 0;
|
|
1245
|
+
menuState.current[targetMenuId] = "no-popup";
|
|
1246
|
+
clearAnyScheduledOpenTasks();
|
|
1247
|
+
break;
|
|
1248
|
+
default:
|
|
1249
|
+
}
|
|
1250
|
+
} else {
|
|
1251
|
+
const [parentOfLastOpenedMenu, lastOpenedMenu] = openMenus.current.slice(-2);
|
|
1252
|
+
if (parentOfLastOpenedMenu.id === hostMenuId && menuState.current[lastOpenedMenu.id] !== "pending-close") {
|
|
1253
|
+
scheduleClose(hostMenuId, lastOpenedMenu.id, menuItemId);
|
|
1254
|
+
if (isGroup && !isOpen) {
|
|
1255
|
+
scheduleOpen(hostMenuId, targetMenuId, menuItemId, delay);
|
|
1256
|
+
}
|
|
1257
|
+
} else if (parentOfLastOpenedMenu.id === hostMenuId && isGroup && menuItemId !== lastOpenedMenu.id && menuState.current[lastOpenedMenu.id] === "pending-close") {
|
|
1258
|
+
scheduleOpen(hostMenuId, targetMenuId, menuItemId, delay);
|
|
1259
|
+
} else if (isGroup) {
|
|
1260
|
+
scheduleOpen(hostMenuId, targetMenuId, menuItemId, delay);
|
|
1261
|
+
} else if (!(menuState.current[lastOpenedMenu.id] === "pending-close")) {
|
|
1262
|
+
closeMenus(menuItemId);
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1267
1265
|
}
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1266
|
+
if (state === "pending-close") {
|
|
1267
|
+
clearAnyScheduledOpenTasks();
|
|
1268
|
+
clearTimeout(menuClosePendingTimeout.current);
|
|
1269
|
+
menuClosePendingTimeout.current = void 0;
|
|
1270
|
+
menuState.current[hostMenuId] = "popup-open";
|
|
1271
1271
|
}
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1272
|
+
},
|
|
1273
|
+
[
|
|
1274
|
+
clearAnyScheduledOpenTasks,
|
|
1275
|
+
closeMenus,
|
|
1276
|
+
getOpenMenuStatus,
|
|
1277
|
+
menuIsOpen,
|
|
1278
|
+
rootId,
|
|
1279
|
+
scheduleClose,
|
|
1280
|
+
scheduleOpen
|
|
1281
|
+
]
|
|
1282
|
+
);
|
|
1283
|
+
const listItemProps = (0, import_react9.useMemo)(
|
|
1284
|
+
() => ({
|
|
1285
|
+
onMouseEnter: (evt) => {
|
|
1286
|
+
const menuItemEl = closestListItem(evt.target);
|
|
1287
|
+
triggerChildMenu(menuItemEl);
|
|
1288
|
+
onMouseEnterItem(evt, menuItemEl.id);
|
|
1289
|
+
},
|
|
1290
|
+
onClick: (evt) => {
|
|
1291
|
+
const listItemEl = closestListItem(evt.target);
|
|
1292
|
+
const { isGroup, menuItemId } = getMenuItemDetails(listItemEl, rootId);
|
|
1293
|
+
if (isGroup) {
|
|
1294
|
+
triggerChildMenu(listItemEl);
|
|
1295
|
+
} else {
|
|
1296
|
+
onActivate(menuItemId);
|
|
1297
|
+
}
|
|
1275
1298
|
}
|
|
1276
|
-
}
|
|
1277
|
-
|
|
1299
|
+
}),
|
|
1300
|
+
[onActivate, onMouseEnterItem, rootId, triggerChildMenu]
|
|
1301
|
+
);
|
|
1302
|
+
return {
|
|
1303
|
+
closeMenu,
|
|
1304
|
+
handleRender,
|
|
1305
|
+
listItemProps,
|
|
1306
|
+
openMenu: triggerChildMenu,
|
|
1307
|
+
openMenus: openMenus.current
|
|
1308
|
+
};
|
|
1278
1309
|
};
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1310
|
+
|
|
1311
|
+
// src/menu/ContextMenu.tsx
|
|
1312
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1313
|
+
var import_react11 = require("react");
|
|
1314
|
+
var noop = () => void 0;
|
|
1315
|
+
var ContextMenu = ({
|
|
1316
|
+
PortalProps: PortalProps2,
|
|
1317
|
+
activatedByKeyboard,
|
|
1318
|
+
children: childrenProp,
|
|
1319
|
+
className,
|
|
1320
|
+
id: idProp,
|
|
1321
|
+
onClose = () => void 0,
|
|
1322
|
+
position = { x: 0, y: 0 },
|
|
1323
|
+
style,
|
|
1324
|
+
...menuListProps
|
|
1325
|
+
}) => {
|
|
1326
|
+
const closeHandlerRef = (0, import_react10.useRef)(onClose);
|
|
1327
|
+
closeHandlerRef.current = onClose;
|
|
1328
|
+
const id = (0, import_vuu_utils5.useId)(idProp);
|
|
1329
|
+
const closeMenuRef = (0, import_react10.useRef)(noop);
|
|
1330
|
+
const [menus, actions] = useItemsWithIdsNext(childrenProp, id);
|
|
1331
|
+
const navigatingWithKeyboard = (0, import_react10.useRef)(activatedByKeyboard);
|
|
1332
|
+
const handleMouseEnterItem = (0, import_react10.useCallback)(() => {
|
|
1333
|
+
navigatingWithKeyboard.current = false;
|
|
1334
|
+
}, []);
|
|
1335
|
+
const handleActivate = (0, import_react10.useCallback)(
|
|
1336
|
+
(menuItemId) => {
|
|
1337
|
+
const actionId = menuItemId.slice(9);
|
|
1338
|
+
const { action, options } = actions[actionId];
|
|
1339
|
+
closeMenuRef.current(id);
|
|
1340
|
+
onClose({
|
|
1341
|
+
type: "menu-action",
|
|
1342
|
+
menuId: action,
|
|
1343
|
+
options
|
|
1344
|
+
});
|
|
1345
|
+
},
|
|
1346
|
+
[actions, id, onClose]
|
|
1347
|
+
);
|
|
1348
|
+
const {
|
|
1349
|
+
closeMenu,
|
|
1350
|
+
listItemProps,
|
|
1351
|
+
openMenu: onOpenMenu,
|
|
1352
|
+
openMenus,
|
|
1353
|
+
handleRender
|
|
1354
|
+
} = useCascade({
|
|
1355
|
+
// FIXME
|
|
1356
|
+
id: `${id}`,
|
|
1357
|
+
onActivate: handleActivate,
|
|
1358
|
+
onMouseEnterItem: handleMouseEnterItem,
|
|
1359
|
+
position
|
|
1360
|
+
});
|
|
1361
|
+
closeMenuRef.current = closeMenu;
|
|
1362
|
+
const handleCloseMenu = () => {
|
|
1363
|
+
navigatingWithKeyboard.current = true;
|
|
1364
|
+
closeMenu();
|
|
1365
|
+
};
|
|
1366
|
+
const handleHighlightMenuItem = () => {
|
|
1367
|
+
};
|
|
1368
|
+
const lastMenu = openMenus.length - 1;
|
|
1369
|
+
const getChildMenuId = (i) => {
|
|
1370
|
+
if (i >= lastMenu) {
|
|
1371
|
+
return void 0;
|
|
1372
|
+
} else {
|
|
1373
|
+
const { id: id2 } = openMenus[i + 1];
|
|
1374
|
+
return id2;
|
|
1302
1375
|
}
|
|
1303
|
-
}
|
|
1376
|
+
};
|
|
1377
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_jsx_runtime6.Fragment, { children: openMenus.map(({ id: menuId, left, top }, i, all) => {
|
|
1378
|
+
const childMenuId = getChildMenuId(i);
|
|
1379
|
+
return /* @__PURE__ */ (0, import_react11.createElement)(Portal, { ...PortalProps2, key: i, onRender: handleRender }, /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1380
|
+
PopupComponent2,
|
|
1381
|
+
{
|
|
1382
|
+
anchorElement: { current: document.body },
|
|
1383
|
+
placement: "absolute",
|
|
1384
|
+
position: { left, top },
|
|
1385
|
+
children: /* @__PURE__ */ (0, import_react11.createElement)(
|
|
1386
|
+
MenuList,
|
|
1387
|
+
{
|
|
1388
|
+
...menuListProps,
|
|
1389
|
+
activatedByKeyboard: navigatingWithKeyboard.current,
|
|
1390
|
+
childMenuShowing: childMenuId,
|
|
1391
|
+
className,
|
|
1392
|
+
id: menuId,
|
|
1393
|
+
isRoot: i === 0,
|
|
1394
|
+
key: i,
|
|
1395
|
+
listItemProps,
|
|
1396
|
+
onActivate: handleActivate,
|
|
1397
|
+
onHighlightMenuItem: handleHighlightMenuItem,
|
|
1398
|
+
onCloseMenu: handleCloseMenu,
|
|
1399
|
+
openMenu: onOpenMenu,
|
|
1400
|
+
style,
|
|
1401
|
+
tabIndex: i === all.length - 1 ? 0 : void 0
|
|
1402
|
+
},
|
|
1403
|
+
menus[menuId]
|
|
1404
|
+
)
|
|
1405
|
+
}
|
|
1406
|
+
));
|
|
1407
|
+
}) });
|
|
1304
1408
|
};
|
|
1409
|
+
ContextMenu.displayName = "ContextMenu";
|
|
1305
1410
|
|
|
1306
|
-
// src/
|
|
1307
|
-
var import_classnames6 = __toESM(require("classnames"));
|
|
1308
|
-
|
|
1309
|
-
// src/popup/useAnchoredPosition.ts
|
|
1411
|
+
// src/menu/context-menu-provider.tsx
|
|
1310
1412
|
var import_react12 = require("react");
|
|
1311
|
-
var
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
case "below-right":
|
|
1321
|
-
return { left, minWidth, top: bottom + offsetTop };
|
|
1322
|
-
case "below-full-width":
|
|
1323
|
-
return {
|
|
1324
|
-
left: left + offsetLeft,
|
|
1325
|
-
minWidth,
|
|
1326
|
-
top: bottom + offsetTop,
|
|
1327
|
-
width
|
|
1328
|
-
};
|
|
1329
|
-
case "center":
|
|
1330
|
-
if (dimensions) {
|
|
1331
|
-
return {
|
|
1332
|
-
left: width / 2 - dimensions.width / 2 + offsetLeft,
|
|
1333
|
-
top: height / 2 - dimensions.height / 2 + offsetTop,
|
|
1334
|
-
visibility: "visible"
|
|
1335
|
-
};
|
|
1336
|
-
} else {
|
|
1337
|
-
return {
|
|
1338
|
-
left: width / 2 + offsetLeft,
|
|
1339
|
-
top: height / 2 + offsetTop,
|
|
1340
|
-
visibility: "hidden"
|
|
1341
|
-
};
|
|
1342
|
-
}
|
|
1343
|
-
default:
|
|
1344
|
-
throw Error(
|
|
1345
|
-
"Popup getPositionRelativeToAnchor only supported placement values are below and right"
|
|
1346
|
-
);
|
|
1347
|
-
}
|
|
1348
|
-
};
|
|
1349
|
-
var useAnchoredPosition = ({
|
|
1350
|
-
anchorElement,
|
|
1351
|
-
minWidth,
|
|
1352
|
-
offsetLeft = 0,
|
|
1353
|
-
offsetTop = 0,
|
|
1354
|
-
placement,
|
|
1355
|
-
position: positionProp
|
|
1413
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1414
|
+
var ContextMenuContext = (0, import_react12.createContext)(
|
|
1415
|
+
null
|
|
1416
|
+
);
|
|
1417
|
+
var Provider = ({
|
|
1418
|
+
children,
|
|
1419
|
+
context,
|
|
1420
|
+
menuActionHandler,
|
|
1421
|
+
menuBuilder
|
|
1356
1422
|
}) => {
|
|
1357
|
-
const
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
if (
|
|
1361
|
-
|
|
1362
|
-
} else
|
|
1363
|
-
|
|
1364
|
-
const position2 = getPositionRelativeToAnchor(
|
|
1365
|
-
anchorElement.current,
|
|
1366
|
-
placement,
|
|
1367
|
-
offsetLeft,
|
|
1368
|
-
offsetTop,
|
|
1369
|
-
minWidth,
|
|
1370
|
-
dimensions
|
|
1371
|
-
);
|
|
1372
|
-
setPosition(position2);
|
|
1423
|
+
const menuBuilders = (0, import_react12.useMemo)(() => {
|
|
1424
|
+
if ((context == null ? void 0 : context.menuBuilders) && menuBuilder) {
|
|
1425
|
+
return context.menuBuilders.concat(menuBuilder);
|
|
1426
|
+
} else if (menuBuilder) {
|
|
1427
|
+
return [menuBuilder];
|
|
1428
|
+
} else {
|
|
1429
|
+
return (context == null ? void 0 : context.menuBuilders) || [];
|
|
1373
1430
|
}
|
|
1374
|
-
}, [
|
|
1375
|
-
const
|
|
1376
|
-
(
|
|
1377
|
-
|
|
1378
|
-
if (
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
placement,
|
|
1384
|
-
offsetLeft,
|
|
1385
|
-
offsetTop,
|
|
1386
|
-
void 0,
|
|
1387
|
-
{ height, width }
|
|
1388
|
-
)
|
|
1389
|
-
);
|
|
1431
|
+
}, [context, menuBuilder]);
|
|
1432
|
+
const handleMenuAction = (0, import_react12.useCallback)(
|
|
1433
|
+
(reason) => {
|
|
1434
|
+
var _a;
|
|
1435
|
+
if (menuActionHandler == null ? void 0 : menuActionHandler(reason)) {
|
|
1436
|
+
return true;
|
|
1437
|
+
}
|
|
1438
|
+
if ((_a = context == null ? void 0 : context.menuActionHandler) == null ? void 0 : _a.call(context, reason)) {
|
|
1439
|
+
return true;
|
|
1390
1440
|
}
|
|
1391
1441
|
},
|
|
1392
|
-
[
|
|
1442
|
+
[context, menuActionHandler]
|
|
1443
|
+
);
|
|
1444
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1445
|
+
ContextMenuContext.Provider,
|
|
1446
|
+
{
|
|
1447
|
+
value: {
|
|
1448
|
+
menuActionHandler: handleMenuAction,
|
|
1449
|
+
menuBuilders
|
|
1450
|
+
},
|
|
1451
|
+
children
|
|
1452
|
+
}
|
|
1393
1453
|
);
|
|
1394
|
-
return {
|
|
1395
|
-
position,
|
|
1396
|
-
popupRef: placement === "center" ? popupCallbackRef : void 0
|
|
1397
|
-
};
|
|
1398
1454
|
};
|
|
1399
|
-
|
|
1400
|
-
// src/popup/Popup.tsx
|
|
1401
|
-
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1402
|
-
var PopupComponent = ({
|
|
1455
|
+
var ContextMenuProvider = ({
|
|
1403
1456
|
children,
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
placement,
|
|
1408
|
-
position: positionProp
|
|
1457
|
+
label,
|
|
1458
|
+
menuActionHandler,
|
|
1459
|
+
menuBuilder
|
|
1409
1460
|
}) => {
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1461
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ContextMenuContext.Consumer, { children: (parentContext) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1462
|
+
Provider,
|
|
1463
|
+
{
|
|
1464
|
+
context: parentContext,
|
|
1465
|
+
label,
|
|
1466
|
+
menuActionHandler,
|
|
1467
|
+
menuBuilder,
|
|
1468
|
+
children
|
|
1469
|
+
}
|
|
1470
|
+
) });
|
|
1417
1471
|
};
|
|
1418
1472
|
|
|
1419
1473
|
// src/menu/useContextMenu.tsx
|
|
1420
|
-
var
|
|
1474
|
+
var import_vuu_utils6 = require("@vuu-ui/vuu-utils");
|
|
1475
|
+
var import_react13 = require("react");
|
|
1421
1476
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1422
1477
|
var useContextMenu = (menuBuilder, menuActionHandler) => {
|
|
1423
1478
|
const ctx = (0, import_react13.useContext)(ContextMenuContext);
|
|
1424
|
-
const [themeClass, densityClass, dataMode] = (0,
|
|
1479
|
+
const [themeClass, densityClass, dataMode] = (0, import_vuu_utils6.useThemeAttributes)();
|
|
1425
1480
|
const themeAttributes = (0, import_react13.useMemo)(
|
|
1426
1481
|
() => ({
|
|
1427
1482
|
themeClass,
|
|
@@ -1509,7 +1564,7 @@ var showContextMenu = (e, menuDescriptors, handleContextMenuAction, {
|
|
|
1509
1564
|
...contextMenuProps
|
|
1510
1565
|
} = NO_OPTIONS) => {
|
|
1511
1566
|
const menuItems = (menuDescriptors2) => {
|
|
1512
|
-
const fromDescriptor = (menuItem, i) => (0,
|
|
1567
|
+
const fromDescriptor = (menuItem, i) => (0, import_vuu_utils6.isGroupMenuItemDescriptor)(menuItem) ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(MenuItemGroup, { label: menuItem.label, children: menuItem.children.map(fromDescriptor) }, i) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
1513
1568
|
MenuItem,
|
|
1514
1569
|
{
|
|
1515
1570
|
action: menuItem.action,
|
|
@@ -1547,10 +1602,10 @@ var showContextMenu = (e, menuDescriptors, handleContextMenuAction, {
|
|
|
1547
1602
|
};
|
|
1548
1603
|
|
|
1549
1604
|
// src/popup-menu/PopupMenu.tsx
|
|
1550
|
-
var
|
|
1551
|
-
var import_classnames7 = __toESM(require("classnames"));
|
|
1605
|
+
var import_vuu_utils7 = require("@vuu-ui/vuu-utils");
|
|
1552
1606
|
var import_core2 = require("@salt-ds/core");
|
|
1553
|
-
var
|
|
1607
|
+
var import_clsx7 = __toESM(require("clsx"));
|
|
1608
|
+
var import_react14 = require("react");
|
|
1554
1609
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
1555
1610
|
var classBase4 = "vuuPopupMenu";
|
|
1556
1611
|
var getPosition2 = (element) => {
|
|
@@ -1575,7 +1630,7 @@ var PopupMenu = ({
|
|
|
1575
1630
|
const rootRef = (0, import_react14.useRef)(null);
|
|
1576
1631
|
const suppressShowMenuRef = (0, import_react14.useRef)(false);
|
|
1577
1632
|
const [menuOpen, setMenuOpen] = (0, import_react14.useState)(false);
|
|
1578
|
-
const id = (0,
|
|
1633
|
+
const id = (0, import_vuu_utils7.useId)(idProp);
|
|
1579
1634
|
const [showContextMenu2] = useContextMenu(menuBuilder, menuActionHandler);
|
|
1580
1635
|
const handleOpenMenu = (0, import_react14.useCallback)((el) => {
|
|
1581
1636
|
console.log(`menu Open `, {
|
|
@@ -1635,7 +1690,7 @@ var PopupMenu = ({
|
|
|
1635
1690
|
"aria-controls": `${id}-menu-root`,
|
|
1636
1691
|
"aria-expanded": menuOpen,
|
|
1637
1692
|
"aria-haspopup": "menu",
|
|
1638
|
-
className: (0,
|
|
1693
|
+
className: (0, import_clsx7.default)(classBase4, className, {
|
|
1639
1694
|
[`${classBase4}-withCaption`]: label !== void 0,
|
|
1640
1695
|
[`${classBase4}-open`]: menuOpen
|
|
1641
1696
|
}),
|
|
@@ -1651,16 +1706,16 @@ var PopupMenu = ({
|
|
|
1651
1706
|
};
|
|
1652
1707
|
|
|
1653
1708
|
// src/prompt/Prompt.tsx
|
|
1654
|
-
var
|
|
1709
|
+
var import_vuu_utils8 = require("@vuu-ui/vuu-utils");
|
|
1655
1710
|
var import_core3 = require("@salt-ds/core");
|
|
1656
|
-
var
|
|
1711
|
+
var import_clsx8 = __toESM(require("clsx"));
|
|
1657
1712
|
var import_react15 = require("react");
|
|
1658
1713
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
1659
1714
|
var classBase5 = "vuuPrompt";
|
|
1660
|
-
var
|
|
1661
|
-
var
|
|
1715
|
+
var AnchorBody2 = { current: document.body };
|
|
1716
|
+
var EMPTY_PROPS2 = {};
|
|
1662
1717
|
var Prompt = ({
|
|
1663
|
-
PopupProps =
|
|
1718
|
+
PopupProps = EMPTY_PROPS2,
|
|
1664
1719
|
cancelButtonLabel = "Cancel",
|
|
1665
1720
|
confirmButtonLabel = "Confirm",
|
|
1666
1721
|
icon,
|
|
@@ -1673,12 +1728,12 @@ var Prompt = ({
|
|
|
1673
1728
|
...htmlAttributes
|
|
1674
1729
|
}) => {
|
|
1675
1730
|
const {
|
|
1676
|
-
anchorElement =
|
|
1731
|
+
anchorElement = AnchorBody2,
|
|
1677
1732
|
offsetLeft = 0,
|
|
1678
1733
|
offsetTop = 0,
|
|
1679
1734
|
placement = "below"
|
|
1680
1735
|
} = PopupProps;
|
|
1681
|
-
const [themeClass, densityClass, dataMode] = (0,
|
|
1736
|
+
const [themeClass, densityClass, dataMode] = (0, import_vuu_utils8.useThemeAttributes)();
|
|
1682
1737
|
const { position } = useAnchoredPosition({
|
|
1683
1738
|
anchorElement,
|
|
1684
1739
|
offsetLeft,
|
|
@@ -1703,7 +1758,7 @@ var Prompt = ({
|
|
|
1703
1758
|
"dialog",
|
|
1704
1759
|
{
|
|
1705
1760
|
...htmlAttributes,
|
|
1706
|
-
className: (0,
|
|
1761
|
+
className: (0, import_clsx8.default)(classBase5, `${classBase5}-${variant}`, themeClass),
|
|
1707
1762
|
"data-mode": dataMode,
|
|
1708
1763
|
ref: rootRef,
|
|
1709
1764
|
style: { ...style, ...position },
|
|
@@ -1762,7 +1817,7 @@ var useAnchoredPosition2 = ({
|
|
|
1762
1817
|
};
|
|
1763
1818
|
|
|
1764
1819
|
// src/tooltip/Tooltip.tsx
|
|
1765
|
-
var
|
|
1820
|
+
var import_clsx9 = __toESM(require("clsx"));
|
|
1766
1821
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
1767
1822
|
var classBase6 = "vuuTooltip";
|
|
1768
1823
|
var Tooltip = ({
|
|
@@ -1782,7 +1837,7 @@ var Tooltip = ({
|
|
|
1782
1837
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1783
1838
|
"div",
|
|
1784
1839
|
{
|
|
1785
|
-
className: (0,
|
|
1840
|
+
className: (0, import_clsx9.default)(classBase6, {
|
|
1786
1841
|
[`${classBase6}-error`]: status === "error"
|
|
1787
1842
|
}),
|
|
1788
1843
|
"data-align": placement,
|
|
@@ -1802,8 +1857,8 @@ var Tooltip = ({
|
|
|
1802
1857
|
};
|
|
1803
1858
|
|
|
1804
1859
|
// src/tooltip/useTooltip.ts
|
|
1860
|
+
var import_vuu_utils9 = require("@vuu-ui/vuu-utils");
|
|
1805
1861
|
var import_react17 = require("react");
|
|
1806
|
-
var import_vuu_layout4 = require("@vuu-ui/vuu-layout");
|
|
1807
1862
|
var useTooltip = ({
|
|
1808
1863
|
id: idProp,
|
|
1809
1864
|
placement = "right",
|
|
@@ -1814,7 +1869,7 @@ var useTooltip = ({
|
|
|
1814
1869
|
const mouseEnterTimerRef = (0, import_react17.useRef)();
|
|
1815
1870
|
const mouseLeaveTimerRef = (0, import_react17.useRef)();
|
|
1816
1871
|
const [tooltipProps, setTooltipProps] = (0, import_react17.useState)();
|
|
1817
|
-
const id = (0,
|
|
1872
|
+
const id = (0, import_vuu_utils9.useId)(idProp);
|
|
1818
1873
|
const escapeListener = (0, import_react17.useCallback)((evt) => {
|
|
1819
1874
|
var _a;
|
|
1820
1875
|
if (evt.key === "Escape") {
|
|
@@ -1891,8 +1946,8 @@ var useTooltip = ({
|
|
|
1891
1946
|
|
|
1892
1947
|
// src/notifications/NotificationsProvider.tsx
|
|
1893
1948
|
var import_react18 = __toESM(require("react"));
|
|
1894
|
-
var
|
|
1895
|
-
var
|
|
1949
|
+
var import_clsx10 = __toESM(require("clsx"));
|
|
1950
|
+
var import_vuu_utils10 = require("@vuu-ui/vuu-utils");
|
|
1896
1951
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1897
1952
|
var toastOffsetTop = 60;
|
|
1898
1953
|
var toastDisplayDuration = 6e3;
|
|
@@ -1917,7 +1972,7 @@ var NotificationsContext = import_react18.default.createContext({
|
|
|
1917
1972
|
var NotificationsProvider = (props) => {
|
|
1918
1973
|
const [notifications, setNotifications] = (0, import_react18.useState)([]);
|
|
1919
1974
|
const notify = (0, import_react18.useCallback)((notification) => {
|
|
1920
|
-
const newNotification = { ...notification, id: (0,
|
|
1975
|
+
const newNotification = { ...notification, id: (0, import_vuu_utils10.getUniqueId)() };
|
|
1921
1976
|
setNotifications((prev) => [...prev, newNotification]);
|
|
1922
1977
|
setTimeout(() => {
|
|
1923
1978
|
setNotifications((prev) => prev.filter((n) => n !== newNotification));
|
|
@@ -1959,7 +2014,7 @@ var ToastNotification = (props) => {
|
|
|
1959
2014
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1960
2015
|
"div",
|
|
1961
2016
|
{
|
|
1962
|
-
className: (0,
|
|
2017
|
+
className: (0, import_clsx10.default)(`${classBase7}-toast`, notification.type),
|
|
1963
2018
|
style: {
|
|
1964
2019
|
height: toastHeight,
|
|
1965
2020
|
right,
|
|
@@ -1971,7 +2026,7 @@ var ToastNotification = (props) => {
|
|
|
1971
2026
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1972
2027
|
"div",
|
|
1973
2028
|
{
|
|
1974
|
-
className: (0,
|
|
2029
|
+
className: (0, import_clsx10.default)(
|
|
1975
2030
|
`${classBase7}-toastIcon`,
|
|
1976
2031
|
`${notification.type}-icon`
|
|
1977
2032
|
)
|