@iris-ui-kit/vue 0.2.26 → 0.2.28
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 +363 -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-AMNHDYFY.js} +367 -268
- package/dist/chunk-AMNHDYFY.js.map +1 -0
- package/dist/index.cjs +367 -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
|
@@ -917,6 +917,7 @@ var CSS2 = `
|
|
|
917
917
|
--iris-nav-item-padding-block: 8px;
|
|
918
918
|
--iris-nav-item-border-radius: var(--iris-radius-md, 6px);
|
|
919
919
|
--iris-nav-item-hover: var(--iris-surface-hover, var(--iris-surface));
|
|
920
|
+
--iris-nav-item-active-hover: color-mix(in srgb, var(--iris-primary) 88%, black);
|
|
920
921
|
--iris-nav-item-height: 34px;
|
|
921
922
|
display: flex;
|
|
922
923
|
flex-direction: column;
|
|
@@ -1022,6 +1023,13 @@ var CSS2 = `
|
|
|
1022
1023
|
font-weight: 600;
|
|
1023
1024
|
}
|
|
1024
1025
|
|
|
1026
|
+
/* active \u9879\u7684 hover \u53CD\u9988\uFF1Aprimary \u52A0\u6DF1\u53D8\u4F53\uFF08\u76AE\u80A4\u53EF\u7528
|
|
1027
|
+
--iris-nav-item-active-hover \u8986\u76D6\uFF09\uFF1B\u7279\u5F02\u5EA6\u9AD8\u4E8E :hover/:where \u89C4\u5219 */
|
|
1028
|
+
.iris-nav-menu-item[data-active='true']:hover,
|
|
1029
|
+
.iris-nav-menu-item[data-active='true'].is-hovered:not([disabled], .is-disabled) {
|
|
1030
|
+
background: var(--iris-nav-item-active-hover, color-mix(in srgb, var(--iris-primary) 88%, black));
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1025
1033
|
:where(.iris-nav-menu-item[data-active-trail='true']) {
|
|
1026
1034
|
color: var(--iris-primary);
|
|
1027
1035
|
font-weight: 600;
|
|
@@ -1188,10 +1196,317 @@ function installNavMenuStyles() {
|
|
|
1188
1196
|
document.head.appendChild(style);
|
|
1189
1197
|
installed2 = true;
|
|
1190
1198
|
}
|
|
1199
|
+
var HOVER_OPEN_DELAY_VAL = 60;
|
|
1200
|
+
var HOVER_CLOSE_DELAY_VAL = 150;
|
|
1201
|
+
function createNavMenuFlyout(ctx) {
|
|
1202
|
+
const hovered = vue.ref(null);
|
|
1203
|
+
const hoveredBranches = vue.ref([]);
|
|
1204
|
+
const focusedBranches = vue.ref([]);
|
|
1205
|
+
const clickedBranches = vue.ref([]);
|
|
1206
|
+
let suppressFocusOpen = false;
|
|
1207
|
+
let openTimer = null;
|
|
1208
|
+
const closeTimers = /* @__PURE__ */ new Map();
|
|
1209
|
+
const clearOpenTimer = () => {
|
|
1210
|
+
if (openTimer) {
|
|
1211
|
+
clearTimeout(openTimer);
|
|
1212
|
+
openTimer = null;
|
|
1213
|
+
}
|
|
1214
|
+
};
|
|
1215
|
+
const cancelClose = (key) => {
|
|
1216
|
+
const timer = closeTimers.get(key);
|
|
1217
|
+
if (timer) {
|
|
1218
|
+
clearTimeout(timer);
|
|
1219
|
+
closeTimers.delete(key);
|
|
1220
|
+
}
|
|
1221
|
+
};
|
|
1222
|
+
const cancelAllTimers = () => {
|
|
1223
|
+
clearOpenTimer();
|
|
1224
|
+
for (const timer of closeTimers.values()) clearTimeout(timer);
|
|
1225
|
+
closeTimers.clear();
|
|
1226
|
+
};
|
|
1227
|
+
vue.onBeforeUnmount(cancelAllTimers);
|
|
1228
|
+
const flyoutTriggers = /* @__PURE__ */ new Map();
|
|
1229
|
+
const flyoutPanels = /* @__PURE__ */ new Map();
|
|
1230
|
+
const setFlyoutRef = (map, key, el) => {
|
|
1231
|
+
if (el instanceof HTMLElement) map.set(key, el);
|
|
1232
|
+
else map.delete(key);
|
|
1233
|
+
};
|
|
1234
|
+
const positionFlyout = (key) => {
|
|
1235
|
+
const trigger = flyoutTriggers.get(key);
|
|
1236
|
+
const panel = flyoutPanels.get(key);
|
|
1237
|
+
if (!trigger || !panel || typeof document === "undefined") return;
|
|
1238
|
+
const rect = trigger.getBoundingClientRect();
|
|
1239
|
+
const dir = getComputedStyle(trigger).direction;
|
|
1240
|
+
panel.style.position = "fixed";
|
|
1241
|
+
panel.style.top = `${ctx.collapsed ? rect.top : rect.bottom}px`;
|
|
1242
|
+
if (dir === "rtl") {
|
|
1243
|
+
panel.style.left = "";
|
|
1244
|
+
panel.style.right = `${window.innerWidth - (ctx.collapsed ? rect.left : rect.right)}px`;
|
|
1245
|
+
} else {
|
|
1246
|
+
panel.style.right = "";
|
|
1247
|
+
panel.style.left = `${ctx.collapsed ? rect.right : rect.left}px`;
|
|
1248
|
+
}
|
|
1249
|
+
};
|
|
1250
|
+
vue.onBeforeUnmount(() => {
|
|
1251
|
+
detachViewportListeners();
|
|
1252
|
+
flyoutTriggers.clear();
|
|
1253
|
+
flyoutPanels.clear();
|
|
1254
|
+
});
|
|
1255
|
+
const isolateAtDepth = (key) => {
|
|
1256
|
+
const depth = core.findNavPath(ctx.items, key).length - 1;
|
|
1257
|
+
const isSameDepthOther = (k) => k !== key && core.findNavPath(ctx.items, k).length - 1 === depth;
|
|
1258
|
+
for (const state of [hoveredBranches, clickedBranches, focusedBranches]) {
|
|
1259
|
+
if (state.value.some(isSameDepthOther)) {
|
|
1260
|
+
state.value = state.value.filter((k) => !isSameDepthOther(k));
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
};
|
|
1264
|
+
const scheduleOpen = (key) => {
|
|
1265
|
+
clearOpenTimer();
|
|
1266
|
+
openTimer = setTimeout(() => {
|
|
1267
|
+
openTimer = null;
|
|
1268
|
+
isolateAtDepth(key);
|
|
1269
|
+
setBranchInteraction(hoveredBranches, key, true);
|
|
1270
|
+
}, HOVER_OPEN_DELAY_VAL);
|
|
1271
|
+
};
|
|
1272
|
+
const scheduleClose = (key) => {
|
|
1273
|
+
cancelClose(key);
|
|
1274
|
+
closeTimers.set(
|
|
1275
|
+
key,
|
|
1276
|
+
setTimeout(() => {
|
|
1277
|
+
closeTimers.delete(key);
|
|
1278
|
+
setBranchInteraction(hoveredBranches, key, false);
|
|
1279
|
+
}, HOVER_CLOSE_DELAY_VAL)
|
|
1280
|
+
);
|
|
1281
|
+
};
|
|
1282
|
+
const closeHorizontalMenus = () => {
|
|
1283
|
+
if (!ctx.flyoutMode.value) return;
|
|
1284
|
+
cancelAllTimers();
|
|
1285
|
+
hovered.value = null;
|
|
1286
|
+
hoveredBranches.value = [];
|
|
1287
|
+
focusedBranches.value = [];
|
|
1288
|
+
clickedBranches.value = [];
|
|
1289
|
+
};
|
|
1290
|
+
const select = (node) => {
|
|
1291
|
+
if (node.disabled) return;
|
|
1292
|
+
closeHorizontalMenus();
|
|
1293
|
+
ctx.emitSelect(node.key, node);
|
|
1294
|
+
};
|
|
1295
|
+
const toggleFlyout = (key) => {
|
|
1296
|
+
cancelAllTimers();
|
|
1297
|
+
const current = clickedBranches.value;
|
|
1298
|
+
if (current.includes(key)) {
|
|
1299
|
+
clickedBranches.value = current.filter((k) => k !== key);
|
|
1300
|
+
setBranchInteraction(hoveredBranches, key, false);
|
|
1301
|
+
setBranchInteraction(focusedBranches, key, false);
|
|
1302
|
+
} else {
|
|
1303
|
+
isolateAtDepth(key);
|
|
1304
|
+
clickedBranches.value = [...clickedBranches.value, key];
|
|
1305
|
+
}
|
|
1306
|
+
};
|
|
1307
|
+
const openFlyout = (key) => {
|
|
1308
|
+
cancelAllTimers();
|
|
1309
|
+
isolateAtDepth(key);
|
|
1310
|
+
setBranchInteraction(focusedBranches, key, true);
|
|
1311
|
+
};
|
|
1312
|
+
const setBranchInteraction = (state, key, enabled) => {
|
|
1313
|
+
const current = state.value;
|
|
1314
|
+
if (enabled) {
|
|
1315
|
+
if (!current.includes(key)) state.value = [...current, key];
|
|
1316
|
+
} else if (current.includes(key)) {
|
|
1317
|
+
state.value = current.filter((item) => item !== key);
|
|
1318
|
+
}
|
|
1319
|
+
};
|
|
1320
|
+
const keepsPointerInside = (container, event) => {
|
|
1321
|
+
if (!container || !(container instanceof HTMLElement)) return false;
|
|
1322
|
+
const next = event.relatedTarget;
|
|
1323
|
+
return !!(next && next instanceof Node && container.contains(next));
|
|
1324
|
+
};
|
|
1325
|
+
const interactionKeyAtDepth = (keys, depth) => keys.find((key) => core.findNavPath(ctx.items, key).length === depth + 1);
|
|
1326
|
+
const horizontalBranchVisible = (key, depth) => {
|
|
1327
|
+
const hoveredAtDepth = interactionKeyAtDepth(hoveredBranches.value, depth);
|
|
1328
|
+
if (hoveredAtDepth) return hoveredAtDepth === key;
|
|
1329
|
+
const clickedAtDepth = interactionKeyAtDepth(clickedBranches.value, depth);
|
|
1330
|
+
if (clickedAtDepth) return clickedAtDepth === key;
|
|
1331
|
+
return interactionKeyAtDepth(focusedBranches.value, depth) === key;
|
|
1332
|
+
};
|
|
1333
|
+
const shownFlyoutKeys = vue.computed(() => {
|
|
1334
|
+
if (!ctx.flyoutMode.value) return [];
|
|
1335
|
+
const keys = [];
|
|
1336
|
+
for (const node of ctx.tree.value) {
|
|
1337
|
+
if (core.isBranch(node) && horizontalBranchVisible(node.key, 0)) keys.push(node.key);
|
|
1338
|
+
}
|
|
1339
|
+
return keys;
|
|
1340
|
+
});
|
|
1341
|
+
const repositionOpenFlyouts = () => {
|
|
1342
|
+
for (const key of shownFlyoutKeys.value) positionFlyout(key);
|
|
1343
|
+
};
|
|
1344
|
+
let viewportListenersActive = false;
|
|
1345
|
+
const attachViewportListeners = () => {
|
|
1346
|
+
if (viewportListenersActive || typeof document === "undefined") return;
|
|
1347
|
+
viewportListenersActive = true;
|
|
1348
|
+
document.addEventListener("scroll", repositionOpenFlyouts, true);
|
|
1349
|
+
window.addEventListener("resize", repositionOpenFlyouts);
|
|
1350
|
+
};
|
|
1351
|
+
const detachViewportListeners = () => {
|
|
1352
|
+
if (!viewportListenersActive || typeof document === "undefined") return;
|
|
1353
|
+
viewportListenersActive = false;
|
|
1354
|
+
document.removeEventListener("scroll", repositionOpenFlyouts, true);
|
|
1355
|
+
window.removeEventListener("resize", repositionOpenFlyouts);
|
|
1356
|
+
};
|
|
1357
|
+
vue.watch(
|
|
1358
|
+
shownFlyoutKeys,
|
|
1359
|
+
(keys, prev) => {
|
|
1360
|
+
if (keys.length > 0 && prev.length === 0) attachViewportListeners();
|
|
1361
|
+
else if (keys.length === 0 && prev.length > 0) detachViewportListeners();
|
|
1362
|
+
for (const key of keys) positionFlyout(key);
|
|
1363
|
+
},
|
|
1364
|
+
{ flush: "post" }
|
|
1365
|
+
);
|
|
1366
|
+
return {
|
|
1367
|
+
hovered,
|
|
1368
|
+
hoveredBranches,
|
|
1369
|
+
focusedBranches,
|
|
1370
|
+
clickedBranches,
|
|
1371
|
+
select,
|
|
1372
|
+
toggleFlyout,
|
|
1373
|
+
openFlyout,
|
|
1374
|
+
closeHorizontalMenus,
|
|
1375
|
+
setBranchInteraction,
|
|
1376
|
+
keepsPointerInside,
|
|
1377
|
+
interactionKeyAtDepth,
|
|
1378
|
+
horizontalBranchVisible,
|
|
1379
|
+
shownFlyoutKeys,
|
|
1380
|
+
setFlyoutRef,
|
|
1381
|
+
flyoutTriggers,
|
|
1382
|
+
flyoutPanels,
|
|
1383
|
+
suppressFocusOpen: { get: () => suppressFocusOpen },
|
|
1384
|
+
setSuppressFocusOpen: (value) => {
|
|
1385
|
+
suppressFocusOpen = value;
|
|
1386
|
+
},
|
|
1387
|
+
cancelClose,
|
|
1388
|
+
scheduleOpen,
|
|
1389
|
+
scheduleClose,
|
|
1390
|
+
cancelAllTimers
|
|
1391
|
+
};
|
|
1392
|
+
}
|
|
1393
|
+
function createNavMenuKeydownHandler(deps) {
|
|
1394
|
+
const {
|
|
1395
|
+
items,
|
|
1396
|
+
flyoutMode,
|
|
1397
|
+
expanded,
|
|
1398
|
+
toggle,
|
|
1399
|
+
openFlyout,
|
|
1400
|
+
closeHorizontalMenus,
|
|
1401
|
+
horizontalBranchVisible,
|
|
1402
|
+
setBranchInteraction,
|
|
1403
|
+
focusedBranches,
|
|
1404
|
+
collapsed,
|
|
1405
|
+
hoveredBranches,
|
|
1406
|
+
clickedBranches,
|
|
1407
|
+
setSuppressFocusOpen
|
|
1408
|
+
} = deps;
|
|
1409
|
+
return (e) => {
|
|
1410
|
+
const root = e.currentTarget;
|
|
1411
|
+
const buttons = Array.from(root.querySelectorAll("[data-iris-nav-item]")).filter(
|
|
1412
|
+
(button) => !button.closest('[data-iris-nav-children][aria-hidden="true"]')
|
|
1413
|
+
);
|
|
1414
|
+
if (buttons.length === 0) return;
|
|
1415
|
+
const idx = buttons.indexOf(document.activeElement);
|
|
1416
|
+
const focusAt = (i) => buttons[(i + buttons.length) % buttons.length]?.focus();
|
|
1417
|
+
const key = idx >= 0 ? buttons[idx]?.getAttribute("data-key") : void 0;
|
|
1418
|
+
const node = key ? core.findNavNode(items, key) : void 0;
|
|
1419
|
+
const depth = idx >= 0 ? Number(buttons[idx]?.getAttribute("data-depth") ?? 0) : 0;
|
|
1420
|
+
switch (e.key) {
|
|
1421
|
+
case "ArrowDown": {
|
|
1422
|
+
e.preventDefault();
|
|
1423
|
+
if (flyoutMode() && node && core.isBranch(node)) {
|
|
1424
|
+
openFlyout(key);
|
|
1425
|
+
const group = buttons[idx].closest("[data-iris-nav-group]");
|
|
1426
|
+
void vue.nextTick(() => {
|
|
1427
|
+
group?.querySelector("[data-iris-nav-children] [data-iris-nav-item]")?.focus();
|
|
1428
|
+
});
|
|
1429
|
+
return;
|
|
1430
|
+
}
|
|
1431
|
+
focusAt(idx < 0 ? 0 : idx + 1);
|
|
1432
|
+
return;
|
|
1433
|
+
}
|
|
1434
|
+
case "ArrowUp": {
|
|
1435
|
+
e.preventDefault();
|
|
1436
|
+
if (flyoutMode() && node && core.isBranch(node) && horizontalBranchVisible(key, depth)) {
|
|
1437
|
+
setBranchInteraction(focusedBranches, key, false);
|
|
1438
|
+
setBranchInteraction(clickedBranches, key, false);
|
|
1439
|
+
return;
|
|
1440
|
+
}
|
|
1441
|
+
focusAt(idx < 0 ? buttons.length - 1 : idx - 1);
|
|
1442
|
+
return;
|
|
1443
|
+
}
|
|
1444
|
+
case "Home":
|
|
1445
|
+
e.preventDefault();
|
|
1446
|
+
buttons[0]?.focus();
|
|
1447
|
+
return;
|
|
1448
|
+
case "End":
|
|
1449
|
+
e.preventDefault();
|
|
1450
|
+
buttons[buttons.length - 1]?.focus();
|
|
1451
|
+
return;
|
|
1452
|
+
case "Escape": {
|
|
1453
|
+
if (flyoutMode()) {
|
|
1454
|
+
const openKeys = [
|
|
1455
|
+
...hoveredBranches.value,
|
|
1456
|
+
...clickedBranches.value,
|
|
1457
|
+
...focusedBranches.value
|
|
1458
|
+
];
|
|
1459
|
+
if (openKeys.length > 0) {
|
|
1460
|
+
e.preventDefault();
|
|
1461
|
+
const openTop = openKeys.find((k) => core.findNavPath(items, k).length === 1);
|
|
1462
|
+
closeHorizontalMenus();
|
|
1463
|
+
if (openTop) {
|
|
1464
|
+
setSuppressFocusOpen(true);
|
|
1465
|
+
buttons.find((b) => b.getAttribute("data-key") === openTop)?.focus();
|
|
1466
|
+
void vue.nextTick(() => {
|
|
1467
|
+
setSuppressFocusOpen(false);
|
|
1468
|
+
});
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
return;
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
if (collapsed || idx < 0 || !key || !node) return;
|
|
1476
|
+
if (e.key === "ArrowRight") {
|
|
1477
|
+
e.preventDefault();
|
|
1478
|
+
if (core.isBranch(node)) {
|
|
1479
|
+
if (flyoutMode() || !expanded().includes(key)) {
|
|
1480
|
+
if (flyoutMode()) openFlyout(key);
|
|
1481
|
+
else toggle(key);
|
|
1482
|
+
const group = buttons[idx].closest("[data-iris-nav-group]");
|
|
1483
|
+
void vue.nextTick(() => {
|
|
1484
|
+
group?.querySelector("[data-iris-nav-children] [data-iris-nav-item]")?.focus();
|
|
1485
|
+
});
|
|
1486
|
+
} else {
|
|
1487
|
+
focusAt(idx + 1);
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
} else if (e.key === "ArrowLeft") {
|
|
1491
|
+
e.preventDefault();
|
|
1492
|
+
if (flyoutMode() && core.isBranch(node)) {
|
|
1493
|
+
setBranchInteraction(focusedBranches, key, false);
|
|
1494
|
+
setBranchInteraction(clickedBranches, key, false);
|
|
1495
|
+
return;
|
|
1496
|
+
}
|
|
1497
|
+
if (core.isBranch(node) && expanded().includes(key)) {
|
|
1498
|
+
toggle(key);
|
|
1499
|
+
} else {
|
|
1500
|
+
const parentKey = core.findNavPath(items, key).at(-2)?.key;
|
|
1501
|
+
if (parentKey) {
|
|
1502
|
+
buttons.find((b) => b.getAttribute("data-key") === parentKey)?.focus();
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
};
|
|
1507
|
+
}
|
|
1191
1508
|
|
|
1192
1509
|
// src/admin/NavMenu.ts
|
|
1193
|
-
var HOVER_OPEN_DELAY = 100;
|
|
1194
|
-
var HOVER_CLOSE_DELAY = 150;
|
|
1195
1510
|
var IrisNavMenu = vue.defineComponent({
|
|
1196
1511
|
name: "IrisNavMenu",
|
|
1197
1512
|
inheritAttrs: false,
|
|
@@ -1253,170 +1568,35 @@ var IrisNavMenu = vue.defineComponent({
|
|
|
1253
1568
|
emit("update:expandedKeys", model.get());
|
|
1254
1569
|
}
|
|
1255
1570
|
};
|
|
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;
|
|
1571
|
+
const flyout = createNavMenuFlyout({
|
|
1572
|
+
items: props.items,
|
|
1573
|
+
tree,
|
|
1574
|
+
expanded,
|
|
1575
|
+
flyoutMode: { value: flyoutMode.value },
|
|
1576
|
+
collapsed: props.collapsed,
|
|
1577
|
+
toggle,
|
|
1578
|
+
emitSelect: (key, node) => emit("select", key, node)
|
|
1394
1579
|
});
|
|
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
|
-
);
|
|
1580
|
+
const {
|
|
1581
|
+
hovered,
|
|
1582
|
+
hoveredBranches,
|
|
1583
|
+
focusedBranches,
|
|
1584
|
+
clickedBranches,
|
|
1585
|
+
select,
|
|
1586
|
+
toggleFlyout,
|
|
1587
|
+
openFlyout,
|
|
1588
|
+
closeHorizontalMenus,
|
|
1589
|
+
setBranchInteraction,
|
|
1590
|
+
keepsPointerInside,
|
|
1591
|
+
horizontalBranchVisible,
|
|
1592
|
+
setFlyoutRef,
|
|
1593
|
+
flyoutTriggers,
|
|
1594
|
+
flyoutPanels,
|
|
1595
|
+
suppressFocusOpen,
|
|
1596
|
+
cancelClose,
|
|
1597
|
+
scheduleOpen,
|
|
1598
|
+
scheduleClose
|
|
1599
|
+
} = flyout;
|
|
1420
1600
|
const itemClass = (opts) => {
|
|
1421
1601
|
const depth = Math.min(9, opts.depth);
|
|
1422
1602
|
return [
|
|
@@ -1552,7 +1732,7 @@ var IrisNavMenu = vue.defineComponent({
|
|
|
1552
1732
|
}
|
|
1553
1733
|
},
|
|
1554
1734
|
onFocusin: () => {
|
|
1555
|
-
if (suppressFocusOpen) return;
|
|
1735
|
+
if (suppressFocusOpen.get()) return;
|
|
1556
1736
|
setBranchInteraction(focusedBranches, node.key, true);
|
|
1557
1737
|
},
|
|
1558
1738
|
onFocusout: (event) => {
|
|
@@ -1605,104 +1785,23 @@ var IrisNavMenu = vue.defineComponent({
|
|
|
1605
1785
|
},
|
|
1606
1786
|
{ flush: "post" }
|
|
1607
1787
|
);
|
|
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
|
-
};
|
|
1788
|
+
const onKeydown = createNavMenuKeydownHandler({
|
|
1789
|
+
items: props.items,
|
|
1790
|
+
flyoutMode: () => flyoutMode.value,
|
|
1791
|
+
expanded: () => expanded.value,
|
|
1792
|
+
toggle,
|
|
1793
|
+
openFlyout,
|
|
1794
|
+
closeHorizontalMenus,
|
|
1795
|
+
horizontalBranchVisible,
|
|
1796
|
+
setBranchInteraction,
|
|
1797
|
+
focusedBranches,
|
|
1798
|
+
hoveredBranches,
|
|
1799
|
+
clickedBranches,
|
|
1800
|
+
setSuppressFocusOpen: (v) => {
|
|
1801
|
+
flyout.setSuppressFocusOpen(v);
|
|
1802
|
+
},
|
|
1803
|
+
collapsed: props.collapsed
|
|
1804
|
+
});
|
|
1706
1805
|
const menuClass = [
|
|
1707
1806
|
"iris-nav-menu",
|
|
1708
1807
|
`iris-nav-menu--${props.orientation}`,
|
|
@@ -12414,8 +12513,8 @@ var IrisMenuSeparator = vue.defineComponent({
|
|
|
12414
12513
|
});
|
|
12415
12514
|
}
|
|
12416
12515
|
});
|
|
12417
|
-
var
|
|
12418
|
-
var
|
|
12516
|
+
var HOVER_OPEN_DELAY = 100;
|
|
12517
|
+
var HOVER_CLOSE_DELAY = 150;
|
|
12419
12518
|
var IrisMenuSub = vue.defineComponent({
|
|
12420
12519
|
name: "IrisMenuSub",
|
|
12421
12520
|
inheritAttrs: false,
|
|
@@ -12456,7 +12555,7 @@ var IrisMenuSub = vue.defineComponent({
|
|
|
12456
12555
|
openTimer = setTimeout(() => {
|
|
12457
12556
|
open.value = true;
|
|
12458
12557
|
openTimer = null;
|
|
12459
|
-
},
|
|
12558
|
+
}, HOVER_OPEN_DELAY);
|
|
12460
12559
|
};
|
|
12461
12560
|
const scheduleClose = () => {
|
|
12462
12561
|
clearTimer();
|
|
@@ -12465,7 +12564,7 @@ var IrisMenuSub = vue.defineComponent({
|
|
|
12465
12564
|
closeTimer = null;
|
|
12466
12565
|
keyboardManaged = false;
|
|
12467
12566
|
open.value = false;
|
|
12468
|
-
},
|
|
12567
|
+
}, HOVER_CLOSE_DELAY);
|
|
12469
12568
|
};
|
|
12470
12569
|
vue.onScopeDispose(() => {
|
|
12471
12570
|
clearTimer();
|