@iris-ui-kit/vue 0.2.26 → 0.2.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/admin.cjs +355 -264
- package/dist/admin.cjs.map +1 -1
- package/dist/admin.d.cts +1 -0
- package/dist/admin.d.ts +1 -0
- package/dist/admin.js +1 -1
- package/dist/{chunk-ZWFSGMOB.js → chunk-ASFDGYIR.js} +359 -268
- package/dist/chunk-ASFDGYIR.js.map +1 -0
- package/dist/index.cjs +359 -268
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/dist/chunk-ZWFSGMOB.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1188,10 +1188,317 @@ function installNavMenuStyles() {
|
|
|
1188
1188
|
document.head.appendChild(style);
|
|
1189
1189
|
installed2 = true;
|
|
1190
1190
|
}
|
|
1191
|
+
var HOVER_OPEN_DELAY_VAL = 60;
|
|
1192
|
+
var HOVER_CLOSE_DELAY_VAL = 150;
|
|
1193
|
+
function createNavMenuFlyout(ctx) {
|
|
1194
|
+
const hovered = vue.ref(null);
|
|
1195
|
+
const hoveredBranches = vue.ref([]);
|
|
1196
|
+
const focusedBranches = vue.ref([]);
|
|
1197
|
+
const clickedBranches = vue.ref([]);
|
|
1198
|
+
let suppressFocusOpen = false;
|
|
1199
|
+
let openTimer = null;
|
|
1200
|
+
const closeTimers = /* @__PURE__ */ new Map();
|
|
1201
|
+
const clearOpenTimer = () => {
|
|
1202
|
+
if (openTimer) {
|
|
1203
|
+
clearTimeout(openTimer);
|
|
1204
|
+
openTimer = null;
|
|
1205
|
+
}
|
|
1206
|
+
};
|
|
1207
|
+
const cancelClose = (key) => {
|
|
1208
|
+
const timer = closeTimers.get(key);
|
|
1209
|
+
if (timer) {
|
|
1210
|
+
clearTimeout(timer);
|
|
1211
|
+
closeTimers.delete(key);
|
|
1212
|
+
}
|
|
1213
|
+
};
|
|
1214
|
+
const cancelAllTimers = () => {
|
|
1215
|
+
clearOpenTimer();
|
|
1216
|
+
for (const timer of closeTimers.values()) clearTimeout(timer);
|
|
1217
|
+
closeTimers.clear();
|
|
1218
|
+
};
|
|
1219
|
+
vue.onBeforeUnmount(cancelAllTimers);
|
|
1220
|
+
const flyoutTriggers = /* @__PURE__ */ new Map();
|
|
1221
|
+
const flyoutPanels = /* @__PURE__ */ new Map();
|
|
1222
|
+
const setFlyoutRef = (map, key, el) => {
|
|
1223
|
+
if (el instanceof HTMLElement) map.set(key, el);
|
|
1224
|
+
else map.delete(key);
|
|
1225
|
+
};
|
|
1226
|
+
const positionFlyout = (key) => {
|
|
1227
|
+
const trigger = flyoutTriggers.get(key);
|
|
1228
|
+
const panel = flyoutPanels.get(key);
|
|
1229
|
+
if (!trigger || !panel || typeof document === "undefined") return;
|
|
1230
|
+
const rect = trigger.getBoundingClientRect();
|
|
1231
|
+
const dir = getComputedStyle(trigger).direction;
|
|
1232
|
+
panel.style.position = "fixed";
|
|
1233
|
+
panel.style.top = `${ctx.collapsed ? rect.top : rect.bottom}px`;
|
|
1234
|
+
if (dir === "rtl") {
|
|
1235
|
+
panel.style.left = "";
|
|
1236
|
+
panel.style.right = `${window.innerWidth - (ctx.collapsed ? rect.left : rect.right)}px`;
|
|
1237
|
+
} else {
|
|
1238
|
+
panel.style.right = "";
|
|
1239
|
+
panel.style.left = `${ctx.collapsed ? rect.right : rect.left}px`;
|
|
1240
|
+
}
|
|
1241
|
+
};
|
|
1242
|
+
vue.onBeforeUnmount(() => {
|
|
1243
|
+
detachViewportListeners();
|
|
1244
|
+
flyoutTriggers.clear();
|
|
1245
|
+
flyoutPanels.clear();
|
|
1246
|
+
});
|
|
1247
|
+
const isolateAtDepth = (key) => {
|
|
1248
|
+
const depth = core.findNavPath(ctx.items, key).length - 1;
|
|
1249
|
+
const isSameDepthOther = (k) => k !== key && core.findNavPath(ctx.items, k).length - 1 === depth;
|
|
1250
|
+
for (const state of [hoveredBranches, clickedBranches, focusedBranches]) {
|
|
1251
|
+
if (state.value.some(isSameDepthOther)) {
|
|
1252
|
+
state.value = state.value.filter((k) => !isSameDepthOther(k));
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
};
|
|
1256
|
+
const scheduleOpen = (key) => {
|
|
1257
|
+
clearOpenTimer();
|
|
1258
|
+
openTimer = setTimeout(() => {
|
|
1259
|
+
openTimer = null;
|
|
1260
|
+
isolateAtDepth(key);
|
|
1261
|
+
setBranchInteraction(hoveredBranches, key, true);
|
|
1262
|
+
}, HOVER_OPEN_DELAY_VAL);
|
|
1263
|
+
};
|
|
1264
|
+
const scheduleClose = (key) => {
|
|
1265
|
+
cancelClose(key);
|
|
1266
|
+
closeTimers.set(
|
|
1267
|
+
key,
|
|
1268
|
+
setTimeout(() => {
|
|
1269
|
+
closeTimers.delete(key);
|
|
1270
|
+
setBranchInteraction(hoveredBranches, key, false);
|
|
1271
|
+
}, HOVER_CLOSE_DELAY_VAL)
|
|
1272
|
+
);
|
|
1273
|
+
};
|
|
1274
|
+
const closeHorizontalMenus = () => {
|
|
1275
|
+
if (!ctx.flyoutMode.value) return;
|
|
1276
|
+
cancelAllTimers();
|
|
1277
|
+
hovered.value = null;
|
|
1278
|
+
hoveredBranches.value = [];
|
|
1279
|
+
focusedBranches.value = [];
|
|
1280
|
+
clickedBranches.value = [];
|
|
1281
|
+
};
|
|
1282
|
+
const select = (node) => {
|
|
1283
|
+
if (node.disabled) return;
|
|
1284
|
+
closeHorizontalMenus();
|
|
1285
|
+
ctx.emitSelect(node.key, node);
|
|
1286
|
+
};
|
|
1287
|
+
const toggleFlyout = (key) => {
|
|
1288
|
+
cancelAllTimers();
|
|
1289
|
+
const current = clickedBranches.value;
|
|
1290
|
+
if (current.includes(key)) {
|
|
1291
|
+
clickedBranches.value = current.filter((k) => k !== key);
|
|
1292
|
+
setBranchInteraction(hoveredBranches, key, false);
|
|
1293
|
+
setBranchInteraction(focusedBranches, key, false);
|
|
1294
|
+
} else {
|
|
1295
|
+
isolateAtDepth(key);
|
|
1296
|
+
clickedBranches.value = [...clickedBranches.value, key];
|
|
1297
|
+
}
|
|
1298
|
+
};
|
|
1299
|
+
const openFlyout = (key) => {
|
|
1300
|
+
cancelAllTimers();
|
|
1301
|
+
isolateAtDepth(key);
|
|
1302
|
+
setBranchInteraction(focusedBranches, key, true);
|
|
1303
|
+
};
|
|
1304
|
+
const setBranchInteraction = (state, key, enabled) => {
|
|
1305
|
+
const current = state.value;
|
|
1306
|
+
if (enabled) {
|
|
1307
|
+
if (!current.includes(key)) state.value = [...current, key];
|
|
1308
|
+
} else if (current.includes(key)) {
|
|
1309
|
+
state.value = current.filter((item) => item !== key);
|
|
1310
|
+
}
|
|
1311
|
+
};
|
|
1312
|
+
const keepsPointerInside = (container, event) => {
|
|
1313
|
+
if (!container || !(container instanceof HTMLElement)) return false;
|
|
1314
|
+
const next = event.relatedTarget;
|
|
1315
|
+
return !!(next && next instanceof Node && container.contains(next));
|
|
1316
|
+
};
|
|
1317
|
+
const interactionKeyAtDepth = (keys, depth) => keys.find((key) => core.findNavPath(ctx.items, key).length === depth + 1);
|
|
1318
|
+
const horizontalBranchVisible = (key, depth) => {
|
|
1319
|
+
const hoveredAtDepth = interactionKeyAtDepth(hoveredBranches.value, depth);
|
|
1320
|
+
if (hoveredAtDepth) return hoveredAtDepth === key;
|
|
1321
|
+
const clickedAtDepth = interactionKeyAtDepth(clickedBranches.value, depth);
|
|
1322
|
+
if (clickedAtDepth) return clickedAtDepth === key;
|
|
1323
|
+
return interactionKeyAtDepth(focusedBranches.value, depth) === key;
|
|
1324
|
+
};
|
|
1325
|
+
const shownFlyoutKeys = vue.computed(() => {
|
|
1326
|
+
if (!ctx.flyoutMode.value) return [];
|
|
1327
|
+
const keys = [];
|
|
1328
|
+
for (const node of ctx.tree.value) {
|
|
1329
|
+
if (core.isBranch(node) && horizontalBranchVisible(node.key, 0)) keys.push(node.key);
|
|
1330
|
+
}
|
|
1331
|
+
return keys;
|
|
1332
|
+
});
|
|
1333
|
+
const repositionOpenFlyouts = () => {
|
|
1334
|
+
for (const key of shownFlyoutKeys.value) positionFlyout(key);
|
|
1335
|
+
};
|
|
1336
|
+
let viewportListenersActive = false;
|
|
1337
|
+
const attachViewportListeners = () => {
|
|
1338
|
+
if (viewportListenersActive || typeof document === "undefined") return;
|
|
1339
|
+
viewportListenersActive = true;
|
|
1340
|
+
document.addEventListener("scroll", repositionOpenFlyouts, true);
|
|
1341
|
+
window.addEventListener("resize", repositionOpenFlyouts);
|
|
1342
|
+
};
|
|
1343
|
+
const detachViewportListeners = () => {
|
|
1344
|
+
if (!viewportListenersActive || typeof document === "undefined") return;
|
|
1345
|
+
viewportListenersActive = false;
|
|
1346
|
+
document.removeEventListener("scroll", repositionOpenFlyouts, true);
|
|
1347
|
+
window.removeEventListener("resize", repositionOpenFlyouts);
|
|
1348
|
+
};
|
|
1349
|
+
vue.watch(
|
|
1350
|
+
shownFlyoutKeys,
|
|
1351
|
+
(keys, prev) => {
|
|
1352
|
+
if (keys.length > 0 && prev.length === 0) attachViewportListeners();
|
|
1353
|
+
else if (keys.length === 0 && prev.length > 0) detachViewportListeners();
|
|
1354
|
+
for (const key of keys) positionFlyout(key);
|
|
1355
|
+
},
|
|
1356
|
+
{ flush: "post" }
|
|
1357
|
+
);
|
|
1358
|
+
return {
|
|
1359
|
+
hovered,
|
|
1360
|
+
hoveredBranches,
|
|
1361
|
+
focusedBranches,
|
|
1362
|
+
clickedBranches,
|
|
1363
|
+
select,
|
|
1364
|
+
toggleFlyout,
|
|
1365
|
+
openFlyout,
|
|
1366
|
+
closeHorizontalMenus,
|
|
1367
|
+
setBranchInteraction,
|
|
1368
|
+
keepsPointerInside,
|
|
1369
|
+
interactionKeyAtDepth,
|
|
1370
|
+
horizontalBranchVisible,
|
|
1371
|
+
shownFlyoutKeys,
|
|
1372
|
+
setFlyoutRef,
|
|
1373
|
+
flyoutTriggers,
|
|
1374
|
+
flyoutPanels,
|
|
1375
|
+
suppressFocusOpen: { get: () => suppressFocusOpen },
|
|
1376
|
+
setSuppressFocusOpen: (value) => {
|
|
1377
|
+
suppressFocusOpen = value;
|
|
1378
|
+
},
|
|
1379
|
+
cancelClose,
|
|
1380
|
+
scheduleOpen,
|
|
1381
|
+
scheduleClose,
|
|
1382
|
+
cancelAllTimers
|
|
1383
|
+
};
|
|
1384
|
+
}
|
|
1385
|
+
function createNavMenuKeydownHandler(deps) {
|
|
1386
|
+
const {
|
|
1387
|
+
items,
|
|
1388
|
+
flyoutMode,
|
|
1389
|
+
expanded,
|
|
1390
|
+
toggle,
|
|
1391
|
+
openFlyout,
|
|
1392
|
+
closeHorizontalMenus,
|
|
1393
|
+
horizontalBranchVisible,
|
|
1394
|
+
setBranchInteraction,
|
|
1395
|
+
focusedBranches,
|
|
1396
|
+
collapsed,
|
|
1397
|
+
hoveredBranches,
|
|
1398
|
+
clickedBranches,
|
|
1399
|
+
setSuppressFocusOpen
|
|
1400
|
+
} = deps;
|
|
1401
|
+
return (e) => {
|
|
1402
|
+
const root = e.currentTarget;
|
|
1403
|
+
const buttons = Array.from(root.querySelectorAll("[data-iris-nav-item]")).filter(
|
|
1404
|
+
(button) => !button.closest('[data-iris-nav-children][aria-hidden="true"]')
|
|
1405
|
+
);
|
|
1406
|
+
if (buttons.length === 0) return;
|
|
1407
|
+
const idx = buttons.indexOf(document.activeElement);
|
|
1408
|
+
const focusAt = (i) => buttons[(i + buttons.length) % buttons.length]?.focus();
|
|
1409
|
+
const key = idx >= 0 ? buttons[idx]?.getAttribute("data-key") : void 0;
|
|
1410
|
+
const node = key ? core.findNavNode(items, key) : void 0;
|
|
1411
|
+
const depth = idx >= 0 ? Number(buttons[idx]?.getAttribute("data-depth") ?? 0) : 0;
|
|
1412
|
+
switch (e.key) {
|
|
1413
|
+
case "ArrowDown": {
|
|
1414
|
+
e.preventDefault();
|
|
1415
|
+
if (flyoutMode() && node && core.isBranch(node)) {
|
|
1416
|
+
openFlyout(key);
|
|
1417
|
+
const group = buttons[idx].closest("[data-iris-nav-group]");
|
|
1418
|
+
void vue.nextTick(() => {
|
|
1419
|
+
group?.querySelector("[data-iris-nav-children] [data-iris-nav-item]")?.focus();
|
|
1420
|
+
});
|
|
1421
|
+
return;
|
|
1422
|
+
}
|
|
1423
|
+
focusAt(idx < 0 ? 0 : idx + 1);
|
|
1424
|
+
return;
|
|
1425
|
+
}
|
|
1426
|
+
case "ArrowUp": {
|
|
1427
|
+
e.preventDefault();
|
|
1428
|
+
if (flyoutMode() && node && core.isBranch(node) && horizontalBranchVisible(key, depth)) {
|
|
1429
|
+
setBranchInteraction(focusedBranches, key, false);
|
|
1430
|
+
setBranchInteraction(clickedBranches, key, false);
|
|
1431
|
+
return;
|
|
1432
|
+
}
|
|
1433
|
+
focusAt(idx < 0 ? buttons.length - 1 : idx - 1);
|
|
1434
|
+
return;
|
|
1435
|
+
}
|
|
1436
|
+
case "Home":
|
|
1437
|
+
e.preventDefault();
|
|
1438
|
+
buttons[0]?.focus();
|
|
1439
|
+
return;
|
|
1440
|
+
case "End":
|
|
1441
|
+
e.preventDefault();
|
|
1442
|
+
buttons[buttons.length - 1]?.focus();
|
|
1443
|
+
return;
|
|
1444
|
+
case "Escape": {
|
|
1445
|
+
if (flyoutMode()) {
|
|
1446
|
+
const openKeys = [
|
|
1447
|
+
...hoveredBranches.value,
|
|
1448
|
+
...clickedBranches.value,
|
|
1449
|
+
...focusedBranches.value
|
|
1450
|
+
];
|
|
1451
|
+
if (openKeys.length > 0) {
|
|
1452
|
+
e.preventDefault();
|
|
1453
|
+
const openTop = openKeys.find((k) => core.findNavPath(items, k).length === 1);
|
|
1454
|
+
closeHorizontalMenus();
|
|
1455
|
+
if (openTop) {
|
|
1456
|
+
setSuppressFocusOpen(true);
|
|
1457
|
+
buttons.find((b) => b.getAttribute("data-key") === openTop)?.focus();
|
|
1458
|
+
void vue.nextTick(() => {
|
|
1459
|
+
setSuppressFocusOpen(false);
|
|
1460
|
+
});
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
return;
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
if (collapsed || idx < 0 || !key || !node) return;
|
|
1468
|
+
if (e.key === "ArrowRight") {
|
|
1469
|
+
e.preventDefault();
|
|
1470
|
+
if (core.isBranch(node)) {
|
|
1471
|
+
if (flyoutMode() || !expanded().includes(key)) {
|
|
1472
|
+
if (flyoutMode()) openFlyout(key);
|
|
1473
|
+
else toggle(key);
|
|
1474
|
+
const group = buttons[idx].closest("[data-iris-nav-group]");
|
|
1475
|
+
void vue.nextTick(() => {
|
|
1476
|
+
group?.querySelector("[data-iris-nav-children] [data-iris-nav-item]")?.focus();
|
|
1477
|
+
});
|
|
1478
|
+
} else {
|
|
1479
|
+
focusAt(idx + 1);
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
} else if (e.key === "ArrowLeft") {
|
|
1483
|
+
e.preventDefault();
|
|
1484
|
+
if (flyoutMode() && core.isBranch(node)) {
|
|
1485
|
+
setBranchInteraction(focusedBranches, key, false);
|
|
1486
|
+
setBranchInteraction(clickedBranches, key, false);
|
|
1487
|
+
return;
|
|
1488
|
+
}
|
|
1489
|
+
if (core.isBranch(node) && expanded().includes(key)) {
|
|
1490
|
+
toggle(key);
|
|
1491
|
+
} else {
|
|
1492
|
+
const parentKey = core.findNavPath(items, key).at(-2)?.key;
|
|
1493
|
+
if (parentKey) {
|
|
1494
|
+
buttons.find((b) => b.getAttribute("data-key") === parentKey)?.focus();
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
};
|
|
1499
|
+
}
|
|
1191
1500
|
|
|
1192
1501
|
// src/admin/NavMenu.ts
|
|
1193
|
-
var HOVER_OPEN_DELAY = 100;
|
|
1194
|
-
var HOVER_CLOSE_DELAY = 150;
|
|
1195
1502
|
var IrisNavMenu = vue.defineComponent({
|
|
1196
1503
|
name: "IrisNavMenu",
|
|
1197
1504
|
inheritAttrs: false,
|
|
@@ -1253,170 +1560,35 @@ var IrisNavMenu = vue.defineComponent({
|
|
|
1253
1560
|
emit("update:expandedKeys", model.get());
|
|
1254
1561
|
}
|
|
1255
1562
|
};
|
|
1256
|
-
const
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
if (openTimer) {
|
|
1265
|
-
clearTimeout(openTimer);
|
|
1266
|
-
openTimer = null;
|
|
1267
|
-
}
|
|
1268
|
-
};
|
|
1269
|
-
const cancelClose = (key) => {
|
|
1270
|
-
const timer = closeTimers.get(key);
|
|
1271
|
-
if (timer) {
|
|
1272
|
-
clearTimeout(timer);
|
|
1273
|
-
closeTimers.delete(key);
|
|
1274
|
-
}
|
|
1275
|
-
};
|
|
1276
|
-
const cancelAllTimers = () => {
|
|
1277
|
-
clearOpenTimer();
|
|
1278
|
-
for (const timer of closeTimers.values()) clearTimeout(timer);
|
|
1279
|
-
closeTimers.clear();
|
|
1280
|
-
};
|
|
1281
|
-
vue.onBeforeUnmount(cancelAllTimers);
|
|
1282
|
-
const flyoutTriggers = /* @__PURE__ */ new Map();
|
|
1283
|
-
const flyoutPanels = /* @__PURE__ */ new Map();
|
|
1284
|
-
const setFlyoutRef = (map, key, el) => {
|
|
1285
|
-
if (el instanceof HTMLElement) map.set(key, el);
|
|
1286
|
-
else map.delete(key);
|
|
1287
|
-
};
|
|
1288
|
-
const positionFlyout = (key) => {
|
|
1289
|
-
const trigger = flyoutTriggers.get(key);
|
|
1290
|
-
const panel = flyoutPanels.get(key);
|
|
1291
|
-
if (!trigger || !panel || typeof document === "undefined") return;
|
|
1292
|
-
const rect = trigger.getBoundingClientRect();
|
|
1293
|
-
const dir = getComputedStyle(trigger).direction;
|
|
1294
|
-
panel.style.position = "fixed";
|
|
1295
|
-
panel.style.top = `${props.collapsed ? rect.top : rect.bottom}px`;
|
|
1296
|
-
if (dir === "rtl") {
|
|
1297
|
-
panel.style.left = "";
|
|
1298
|
-
panel.style.right = `${window.innerWidth - (props.collapsed ? rect.left : rect.right)}px`;
|
|
1299
|
-
} else {
|
|
1300
|
-
panel.style.right = "";
|
|
1301
|
-
panel.style.left = `${props.collapsed ? rect.right : rect.left}px`;
|
|
1302
|
-
}
|
|
1303
|
-
};
|
|
1304
|
-
vue.onBeforeUnmount(() => {
|
|
1305
|
-
detachViewportListeners();
|
|
1306
|
-
flyoutTriggers.clear();
|
|
1307
|
-
flyoutPanels.clear();
|
|
1308
|
-
});
|
|
1309
|
-
const isolateAtDepth = (key) => {
|
|
1310
|
-
const depth = core.findNavPath(props.items, key).length - 1;
|
|
1311
|
-
const isSameDepthOther = (k) => k !== key && core.findNavPath(props.items, k).length - 1 === depth;
|
|
1312
|
-
for (const state of [hoveredBranches, clickedBranches, focusedBranches]) {
|
|
1313
|
-
if (state.value.some(isSameDepthOther)) {
|
|
1314
|
-
state.value = state.value.filter((k) => !isSameDepthOther(k));
|
|
1315
|
-
}
|
|
1316
|
-
}
|
|
1317
|
-
};
|
|
1318
|
-
const scheduleOpen = (key) => {
|
|
1319
|
-
clearOpenTimer();
|
|
1320
|
-
openTimer = setTimeout(() => {
|
|
1321
|
-
openTimer = null;
|
|
1322
|
-
isolateAtDepth(key);
|
|
1323
|
-
setBranchInteraction(hoveredBranches, key, true);
|
|
1324
|
-
}, HOVER_OPEN_DELAY);
|
|
1325
|
-
};
|
|
1326
|
-
const scheduleClose = (key) => {
|
|
1327
|
-
cancelClose(key);
|
|
1328
|
-
closeTimers.set(
|
|
1329
|
-
key,
|
|
1330
|
-
setTimeout(() => {
|
|
1331
|
-
closeTimers.delete(key);
|
|
1332
|
-
setBranchInteraction(hoveredBranches, key, false);
|
|
1333
|
-
}, HOVER_CLOSE_DELAY)
|
|
1334
|
-
);
|
|
1335
|
-
};
|
|
1336
|
-
const closeHorizontalMenus = () => {
|
|
1337
|
-
if (!flyoutMode.value) return;
|
|
1338
|
-
cancelAllTimers();
|
|
1339
|
-
hovered.value = null;
|
|
1340
|
-
hoveredBranches.value = [];
|
|
1341
|
-
focusedBranches.value = [];
|
|
1342
|
-
clickedBranches.value = [];
|
|
1343
|
-
};
|
|
1344
|
-
const select = (node) => {
|
|
1345
|
-
if (node.disabled) return;
|
|
1346
|
-
closeHorizontalMenus();
|
|
1347
|
-
emit("select", node.key, node);
|
|
1348
|
-
};
|
|
1349
|
-
const toggleFlyout = (key) => {
|
|
1350
|
-
cancelAllTimers();
|
|
1351
|
-
const current = clickedBranches.value;
|
|
1352
|
-
if (current.includes(key)) {
|
|
1353
|
-
clickedBranches.value = current.filter((k) => k !== key);
|
|
1354
|
-
setBranchInteraction(hoveredBranches, key, false);
|
|
1355
|
-
setBranchInteraction(focusedBranches, key, false);
|
|
1356
|
-
} else {
|
|
1357
|
-
isolateAtDepth(key);
|
|
1358
|
-
clickedBranches.value = [...clickedBranches.value, key];
|
|
1359
|
-
}
|
|
1360
|
-
};
|
|
1361
|
-
const openFlyout = (key) => {
|
|
1362
|
-
cancelAllTimers();
|
|
1363
|
-
isolateAtDepth(key);
|
|
1364
|
-
setBranchInteraction(focusedBranches, key, true);
|
|
1365
|
-
};
|
|
1366
|
-
const setBranchInteraction = (state, key, enabled) => {
|
|
1367
|
-
const current = state.value;
|
|
1368
|
-
if (enabled) {
|
|
1369
|
-
if (!current.includes(key)) state.value = [...current, key];
|
|
1370
|
-
} else if (current.includes(key)) {
|
|
1371
|
-
state.value = current.filter((item) => item !== key);
|
|
1372
|
-
}
|
|
1373
|
-
};
|
|
1374
|
-
const keepsPointerInside = (container, event) => {
|
|
1375
|
-
if (!container || !(container instanceof HTMLElement)) return false;
|
|
1376
|
-
const next = event.relatedTarget;
|
|
1377
|
-
return !!(next && next instanceof Node && container.contains(next));
|
|
1378
|
-
};
|
|
1379
|
-
const interactionKeyAtDepth = (keys, depth) => keys.find((key) => core.findNavPath(props.items, key).length === depth + 1);
|
|
1380
|
-
const horizontalBranchVisible = (key, depth) => {
|
|
1381
|
-
const hoveredAtDepth = interactionKeyAtDepth(hoveredBranches.value, depth);
|
|
1382
|
-
if (hoveredAtDepth) return hoveredAtDepth === key;
|
|
1383
|
-
const clickedAtDepth = interactionKeyAtDepth(clickedBranches.value, depth);
|
|
1384
|
-
if (clickedAtDepth) return clickedAtDepth === key;
|
|
1385
|
-
return interactionKeyAtDepth(focusedBranches.value, depth) === key;
|
|
1386
|
-
};
|
|
1387
|
-
const shownFlyoutKeys = vue.computed(() => {
|
|
1388
|
-
if (!flyoutMode.value) return [];
|
|
1389
|
-
const keys = [];
|
|
1390
|
-
for (const node of tree.value) {
|
|
1391
|
-
if (core.isBranch(node) && horizontalBranchVisible(node.key, 0)) keys.push(node.key);
|
|
1392
|
-
}
|
|
1393
|
-
return keys;
|
|
1563
|
+
const flyout = createNavMenuFlyout({
|
|
1564
|
+
items: props.items,
|
|
1565
|
+
tree,
|
|
1566
|
+
expanded,
|
|
1567
|
+
flyoutMode: { value: flyoutMode.value },
|
|
1568
|
+
collapsed: props.collapsed,
|
|
1569
|
+
toggle,
|
|
1570
|
+
emitSelect: (key, node) => emit("select", key, node)
|
|
1394
1571
|
});
|
|
1395
|
-
const
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
else if (keys.length === 0 && prev.length > 0) detachViewportListeners();
|
|
1416
|
-
for (const key of keys) positionFlyout(key);
|
|
1417
|
-
},
|
|
1418
|
-
{ flush: "post" }
|
|
1419
|
-
);
|
|
1572
|
+
const {
|
|
1573
|
+
hovered,
|
|
1574
|
+
hoveredBranches,
|
|
1575
|
+
focusedBranches,
|
|
1576
|
+
clickedBranches,
|
|
1577
|
+
select,
|
|
1578
|
+
toggleFlyout,
|
|
1579
|
+
openFlyout,
|
|
1580
|
+
closeHorizontalMenus,
|
|
1581
|
+
setBranchInteraction,
|
|
1582
|
+
keepsPointerInside,
|
|
1583
|
+
horizontalBranchVisible,
|
|
1584
|
+
setFlyoutRef,
|
|
1585
|
+
flyoutTriggers,
|
|
1586
|
+
flyoutPanels,
|
|
1587
|
+
suppressFocusOpen,
|
|
1588
|
+
cancelClose,
|
|
1589
|
+
scheduleOpen,
|
|
1590
|
+
scheduleClose
|
|
1591
|
+
} = flyout;
|
|
1420
1592
|
const itemClass = (opts) => {
|
|
1421
1593
|
const depth = Math.min(9, opts.depth);
|
|
1422
1594
|
return [
|
|
@@ -1552,7 +1724,7 @@ var IrisNavMenu = vue.defineComponent({
|
|
|
1552
1724
|
}
|
|
1553
1725
|
},
|
|
1554
1726
|
onFocusin: () => {
|
|
1555
|
-
if (suppressFocusOpen) return;
|
|
1727
|
+
if (suppressFocusOpen.get()) return;
|
|
1556
1728
|
setBranchInteraction(focusedBranches, node.key, true);
|
|
1557
1729
|
},
|
|
1558
1730
|
onFocusout: (event) => {
|
|
@@ -1605,104 +1777,23 @@ var IrisNavMenu = vue.defineComponent({
|
|
|
1605
1777
|
},
|
|
1606
1778
|
{ flush: "post" }
|
|
1607
1779
|
);
|
|
1608
|
-
const onKeydown = (
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
void vue.nextTick(() => {
|
|
1626
|
-
group?.querySelector("[data-iris-nav-children] [data-iris-nav-item]")?.focus();
|
|
1627
|
-
});
|
|
1628
|
-
return;
|
|
1629
|
-
}
|
|
1630
|
-
focusAt(idx < 0 ? 0 : idx + 1);
|
|
1631
|
-
return;
|
|
1632
|
-
}
|
|
1633
|
-
case "ArrowUp": {
|
|
1634
|
-
e.preventDefault();
|
|
1635
|
-
if (flyoutMode.value && node && core.isBranch(node) && horizontalBranchVisible(key, depth)) {
|
|
1636
|
-
setBranchInteraction(focusedBranches, key, false);
|
|
1637
|
-
setBranchInteraction(clickedBranches, key, false);
|
|
1638
|
-
return;
|
|
1639
|
-
}
|
|
1640
|
-
focusAt(idx < 0 ? buttons.length - 1 : idx - 1);
|
|
1641
|
-
return;
|
|
1642
|
-
}
|
|
1643
|
-
case "Home":
|
|
1644
|
-
e.preventDefault();
|
|
1645
|
-
buttons[0]?.focus();
|
|
1646
|
-
return;
|
|
1647
|
-
case "End":
|
|
1648
|
-
e.preventDefault();
|
|
1649
|
-
buttons[buttons.length - 1]?.focus();
|
|
1650
|
-
return;
|
|
1651
|
-
case "Escape": {
|
|
1652
|
-
if (flyoutMode.value) {
|
|
1653
|
-
const openKeys = [
|
|
1654
|
-
...hoveredBranches.value,
|
|
1655
|
-
...clickedBranches.value,
|
|
1656
|
-
...focusedBranches.value
|
|
1657
|
-
];
|
|
1658
|
-
if (openKeys.length > 0) {
|
|
1659
|
-
e.preventDefault();
|
|
1660
|
-
const openTop = openKeys.find((k) => core.findNavPath(props.items, k).length === 1);
|
|
1661
|
-
closeHorizontalMenus();
|
|
1662
|
-
if (openTop) {
|
|
1663
|
-
suppressFocusOpen = true;
|
|
1664
|
-
buttons.find((b) => b.getAttribute("data-key") === openTop)?.focus();
|
|
1665
|
-
void vue.nextTick(() => {
|
|
1666
|
-
suppressFocusOpen = false;
|
|
1667
|
-
});
|
|
1668
|
-
}
|
|
1669
|
-
}
|
|
1670
|
-
}
|
|
1671
|
-
return;
|
|
1672
|
-
}
|
|
1673
|
-
}
|
|
1674
|
-
if (props.collapsed || idx < 0 || !key || !node) return;
|
|
1675
|
-
if (e.key === "ArrowRight") {
|
|
1676
|
-
e.preventDefault();
|
|
1677
|
-
if (core.isBranch(node)) {
|
|
1678
|
-
if (flyoutMode.value || !expanded.value.includes(key)) {
|
|
1679
|
-
if (flyoutMode.value) openFlyout(key);
|
|
1680
|
-
else toggle(key);
|
|
1681
|
-
const group = buttons[idx].closest("[data-iris-nav-group]");
|
|
1682
|
-
void vue.nextTick(() => {
|
|
1683
|
-
group?.querySelector("[data-iris-nav-children] [data-iris-nav-item]")?.focus();
|
|
1684
|
-
});
|
|
1685
|
-
} else {
|
|
1686
|
-
focusAt(idx + 1);
|
|
1687
|
-
}
|
|
1688
|
-
}
|
|
1689
|
-
} else if (e.key === "ArrowLeft") {
|
|
1690
|
-
e.preventDefault();
|
|
1691
|
-
if (flyoutMode.value && core.isBranch(node)) {
|
|
1692
|
-
setBranchInteraction(focusedBranches, key, false);
|
|
1693
|
-
setBranchInteraction(clickedBranches, key, false);
|
|
1694
|
-
return;
|
|
1695
|
-
}
|
|
1696
|
-
if (core.isBranch(node) && expanded.value.includes(key)) {
|
|
1697
|
-
toggle(key);
|
|
1698
|
-
} else {
|
|
1699
|
-
const parentKey = core.findNavPath(props.items, key).at(-2)?.key;
|
|
1700
|
-
if (parentKey) {
|
|
1701
|
-
buttons.find((b) => b.getAttribute("data-key") === parentKey)?.focus();
|
|
1702
|
-
}
|
|
1703
|
-
}
|
|
1704
|
-
}
|
|
1705
|
-
};
|
|
1780
|
+
const onKeydown = createNavMenuKeydownHandler({
|
|
1781
|
+
items: props.items,
|
|
1782
|
+
flyoutMode: () => flyoutMode.value,
|
|
1783
|
+
expanded: () => expanded.value,
|
|
1784
|
+
toggle,
|
|
1785
|
+
openFlyout,
|
|
1786
|
+
closeHorizontalMenus,
|
|
1787
|
+
horizontalBranchVisible,
|
|
1788
|
+
setBranchInteraction,
|
|
1789
|
+
focusedBranches,
|
|
1790
|
+
hoveredBranches,
|
|
1791
|
+
clickedBranches,
|
|
1792
|
+
setSuppressFocusOpen: (v) => {
|
|
1793
|
+
flyout.setSuppressFocusOpen(v);
|
|
1794
|
+
},
|
|
1795
|
+
collapsed: props.collapsed
|
|
1796
|
+
});
|
|
1706
1797
|
const menuClass = [
|
|
1707
1798
|
"iris-nav-menu",
|
|
1708
1799
|
`iris-nav-menu--${props.orientation}`,
|
|
@@ -12414,8 +12505,8 @@ var IrisMenuSeparator = vue.defineComponent({
|
|
|
12414
12505
|
});
|
|
12415
12506
|
}
|
|
12416
12507
|
});
|
|
12417
|
-
var
|
|
12418
|
-
var
|
|
12508
|
+
var HOVER_OPEN_DELAY = 100;
|
|
12509
|
+
var HOVER_CLOSE_DELAY = 150;
|
|
12419
12510
|
var IrisMenuSub = vue.defineComponent({
|
|
12420
12511
|
name: "IrisMenuSub",
|
|
12421
12512
|
inheritAttrs: false,
|
|
@@ -12456,7 +12547,7 @@ var IrisMenuSub = vue.defineComponent({
|
|
|
12456
12547
|
openTimer = setTimeout(() => {
|
|
12457
12548
|
open.value = true;
|
|
12458
12549
|
openTimer = null;
|
|
12459
|
-
},
|
|
12550
|
+
}, HOVER_OPEN_DELAY);
|
|
12460
12551
|
};
|
|
12461
12552
|
const scheduleClose = () => {
|
|
12462
12553
|
clearTimer();
|
|
@@ -12465,7 +12556,7 @@ var IrisMenuSub = vue.defineComponent({
|
|
|
12465
12556
|
closeTimer = null;
|
|
12466
12557
|
keyboardManaged = false;
|
|
12467
12558
|
open.value = false;
|
|
12468
|
-
},
|
|
12559
|
+
}, HOVER_CLOSE_DELAY);
|
|
12469
12560
|
};
|
|
12470
12561
|
vue.onScopeDispose(() => {
|
|
12471
12562
|
clearTimer();
|