@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/admin.d.cts
CHANGED
|
@@ -200,6 +200,7 @@ declare const IrisAdminLayout: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
200
200
|
/** Public input/event surface inferred from the runtime Vue component. */
|
|
201
201
|
type IrisAdminLayoutProps = InstanceType<typeof IrisAdminLayout>['$props'];
|
|
202
202
|
|
|
203
|
+
/** Hover open/close latencies for flyouts (horizontal mode + collapsed rail). */
|
|
203
204
|
/**
|
|
204
205
|
* Data-driven nested navigation menu — the sidebar nav of the admin shell.
|
|
205
206
|
* Renders a normalized `NavNode[]` tree as an accordion of expandable branches
|
package/dist/admin.d.ts
CHANGED
|
@@ -200,6 +200,7 @@ declare const IrisAdminLayout: vue.DefineComponent<vue.ExtractPropTypes<{
|
|
|
200
200
|
/** Public input/event surface inferred from the runtime Vue component. */
|
|
201
201
|
type IrisAdminLayoutProps = InstanceType<typeof IrisAdminLayout>['$props'];
|
|
202
202
|
|
|
203
|
+
/** Hover open/close latencies for flyouts (horizontal mode + collapsed rail). */
|
|
203
204
|
/**
|
|
204
205
|
* Data-driven nested navigation menu — the sidebar nav of the admin shell.
|
|
205
206
|
* Renders a normalized `NavNode[]` tree as an accordion of expandable branches
|
package/dist/admin.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { IrisAdminBreadcrumb, IrisAdminLayout, IrisAdminTabs, IrisNavMenu, createAdminPreferences, createTabsNav, filterNavByAccess, findNavNode, findNavPath, firstLeaf, flattenNav, isBranch, isClosable, localStorageAdminPreferencesStorage, nodeAllowsRoles, useAdminPreferences, useAdminShell, useTabsNav, visibleNav } from './chunk-
|
|
1
|
+
export { IrisAdminBreadcrumb, IrisAdminLayout, IrisAdminTabs, IrisNavMenu, createAdminPreferences, createTabsNav, filterNavByAccess, findNavNode, findNavPath, firstLeaf, flattenNav, isBranch, isClosable, localStorageAdminPreferencesStorage, nodeAllowsRoles, useAdminPreferences, useAdminShell, useTabsNav, visibleNav } from './chunk-ASFDGYIR.js';
|
|
2
2
|
import './chunk-IPR5JAVF.js';
|
|
3
3
|
import './chunk-NNOF7KUH.js';
|
|
4
4
|
import './chunk-F77KIPOH.js';
|
|
@@ -6,8 +6,8 @@ import { IrisThemeKey } from './chunk-ZTPIXL7Q.js';
|
|
|
6
6
|
import { IrisSortable } from './chunk-W3B6E5GN.js';
|
|
7
7
|
import { useStore } from './chunk-75GSYEJS.js';
|
|
8
8
|
import { useI18n } from './chunk-TCAXRWT6.js';
|
|
9
|
-
import { defineComponent, inject, h, computed, shallowRef, onBeforeUnmount, watch,
|
|
10
|
-
import { visibleNav, findNavPath, createExpansion, branchTrail,
|
|
9
|
+
import { defineComponent, inject, h, computed, shallowRef, onBeforeUnmount, watch, provide, useId, ref, nextTick, Teleport, Fragment, watchEffect, toValue, onMounted } from 'vue';
|
|
10
|
+
import { visibleNav, findNavPath, createExpansion, branchTrail, createFloatingMachine, isBranch, findNavNode, firstLeaf, matchTypeahead, nextEnabledIndex, isClosable, createAdminShell } from '@iris-ui-kit/core';
|
|
11
11
|
export { createAdminPreferences, createTabsNav, filterNavByAccess, findNavNode, findNavPath, firstLeaf, flattenNav, isBranch, isClosable, localStorageAdminPreferencesStorage, nodeAllowsRoles, visibleNav } from '@iris-ui-kit/core';
|
|
12
12
|
import { defaultIconRegistry, resolveThemedIcon } from '@iris-ui-kit/icons';
|
|
13
13
|
|
|
@@ -348,10 +348,317 @@ function installNavMenuStyles() {
|
|
|
348
348
|
document.head.appendChild(style);
|
|
349
349
|
installed = true;
|
|
350
350
|
}
|
|
351
|
+
var HOVER_OPEN_DELAY_VAL = 60;
|
|
352
|
+
var HOVER_CLOSE_DELAY_VAL = 150;
|
|
353
|
+
function createNavMenuFlyout(ctx) {
|
|
354
|
+
const hovered = ref(null);
|
|
355
|
+
const hoveredBranches = ref([]);
|
|
356
|
+
const focusedBranches = ref([]);
|
|
357
|
+
const clickedBranches = ref([]);
|
|
358
|
+
let suppressFocusOpen = false;
|
|
359
|
+
let openTimer = null;
|
|
360
|
+
const closeTimers = /* @__PURE__ */ new Map();
|
|
361
|
+
const clearOpenTimer = () => {
|
|
362
|
+
if (openTimer) {
|
|
363
|
+
clearTimeout(openTimer);
|
|
364
|
+
openTimer = null;
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
const cancelClose = (key) => {
|
|
368
|
+
const timer = closeTimers.get(key);
|
|
369
|
+
if (timer) {
|
|
370
|
+
clearTimeout(timer);
|
|
371
|
+
closeTimers.delete(key);
|
|
372
|
+
}
|
|
373
|
+
};
|
|
374
|
+
const cancelAllTimers = () => {
|
|
375
|
+
clearOpenTimer();
|
|
376
|
+
for (const timer of closeTimers.values()) clearTimeout(timer);
|
|
377
|
+
closeTimers.clear();
|
|
378
|
+
};
|
|
379
|
+
onBeforeUnmount(cancelAllTimers);
|
|
380
|
+
const flyoutTriggers = /* @__PURE__ */ new Map();
|
|
381
|
+
const flyoutPanels = /* @__PURE__ */ new Map();
|
|
382
|
+
const setFlyoutRef = (map, key, el) => {
|
|
383
|
+
if (el instanceof HTMLElement) map.set(key, el);
|
|
384
|
+
else map.delete(key);
|
|
385
|
+
};
|
|
386
|
+
const positionFlyout = (key) => {
|
|
387
|
+
const trigger = flyoutTriggers.get(key);
|
|
388
|
+
const panel = flyoutPanels.get(key);
|
|
389
|
+
if (!trigger || !panel || typeof document === "undefined") return;
|
|
390
|
+
const rect = trigger.getBoundingClientRect();
|
|
391
|
+
const dir = getComputedStyle(trigger).direction;
|
|
392
|
+
panel.style.position = "fixed";
|
|
393
|
+
panel.style.top = `${ctx.collapsed ? rect.top : rect.bottom}px`;
|
|
394
|
+
if (dir === "rtl") {
|
|
395
|
+
panel.style.left = "";
|
|
396
|
+
panel.style.right = `${window.innerWidth - (ctx.collapsed ? rect.left : rect.right)}px`;
|
|
397
|
+
} else {
|
|
398
|
+
panel.style.right = "";
|
|
399
|
+
panel.style.left = `${ctx.collapsed ? rect.right : rect.left}px`;
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
onBeforeUnmount(() => {
|
|
403
|
+
detachViewportListeners();
|
|
404
|
+
flyoutTriggers.clear();
|
|
405
|
+
flyoutPanels.clear();
|
|
406
|
+
});
|
|
407
|
+
const isolateAtDepth = (key) => {
|
|
408
|
+
const depth = findNavPath(ctx.items, key).length - 1;
|
|
409
|
+
const isSameDepthOther = (k) => k !== key && findNavPath(ctx.items, k).length - 1 === depth;
|
|
410
|
+
for (const state of [hoveredBranches, clickedBranches, focusedBranches]) {
|
|
411
|
+
if (state.value.some(isSameDepthOther)) {
|
|
412
|
+
state.value = state.value.filter((k) => !isSameDepthOther(k));
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
const scheduleOpen = (key) => {
|
|
417
|
+
clearOpenTimer();
|
|
418
|
+
openTimer = setTimeout(() => {
|
|
419
|
+
openTimer = null;
|
|
420
|
+
isolateAtDepth(key);
|
|
421
|
+
setBranchInteraction(hoveredBranches, key, true);
|
|
422
|
+
}, HOVER_OPEN_DELAY_VAL);
|
|
423
|
+
};
|
|
424
|
+
const scheduleClose = (key) => {
|
|
425
|
+
cancelClose(key);
|
|
426
|
+
closeTimers.set(
|
|
427
|
+
key,
|
|
428
|
+
setTimeout(() => {
|
|
429
|
+
closeTimers.delete(key);
|
|
430
|
+
setBranchInteraction(hoveredBranches, key, false);
|
|
431
|
+
}, HOVER_CLOSE_DELAY_VAL)
|
|
432
|
+
);
|
|
433
|
+
};
|
|
434
|
+
const closeHorizontalMenus = () => {
|
|
435
|
+
if (!ctx.flyoutMode.value) return;
|
|
436
|
+
cancelAllTimers();
|
|
437
|
+
hovered.value = null;
|
|
438
|
+
hoveredBranches.value = [];
|
|
439
|
+
focusedBranches.value = [];
|
|
440
|
+
clickedBranches.value = [];
|
|
441
|
+
};
|
|
442
|
+
const select = (node) => {
|
|
443
|
+
if (node.disabled) return;
|
|
444
|
+
closeHorizontalMenus();
|
|
445
|
+
ctx.emitSelect(node.key, node);
|
|
446
|
+
};
|
|
447
|
+
const toggleFlyout = (key) => {
|
|
448
|
+
cancelAllTimers();
|
|
449
|
+
const current = clickedBranches.value;
|
|
450
|
+
if (current.includes(key)) {
|
|
451
|
+
clickedBranches.value = current.filter((k) => k !== key);
|
|
452
|
+
setBranchInteraction(hoveredBranches, key, false);
|
|
453
|
+
setBranchInteraction(focusedBranches, key, false);
|
|
454
|
+
} else {
|
|
455
|
+
isolateAtDepth(key);
|
|
456
|
+
clickedBranches.value = [...clickedBranches.value, key];
|
|
457
|
+
}
|
|
458
|
+
};
|
|
459
|
+
const openFlyout = (key) => {
|
|
460
|
+
cancelAllTimers();
|
|
461
|
+
isolateAtDepth(key);
|
|
462
|
+
setBranchInteraction(focusedBranches, key, true);
|
|
463
|
+
};
|
|
464
|
+
const setBranchInteraction = (state, key, enabled) => {
|
|
465
|
+
const current = state.value;
|
|
466
|
+
if (enabled) {
|
|
467
|
+
if (!current.includes(key)) state.value = [...current, key];
|
|
468
|
+
} else if (current.includes(key)) {
|
|
469
|
+
state.value = current.filter((item) => item !== key);
|
|
470
|
+
}
|
|
471
|
+
};
|
|
472
|
+
const keepsPointerInside = (container, event) => {
|
|
473
|
+
if (!container || !(container instanceof HTMLElement)) return false;
|
|
474
|
+
const next = event.relatedTarget;
|
|
475
|
+
return !!(next && next instanceof Node && container.contains(next));
|
|
476
|
+
};
|
|
477
|
+
const interactionKeyAtDepth = (keys, depth) => keys.find((key) => findNavPath(ctx.items, key).length === depth + 1);
|
|
478
|
+
const horizontalBranchVisible = (key, depth) => {
|
|
479
|
+
const hoveredAtDepth = interactionKeyAtDepth(hoveredBranches.value, depth);
|
|
480
|
+
if (hoveredAtDepth) return hoveredAtDepth === key;
|
|
481
|
+
const clickedAtDepth = interactionKeyAtDepth(clickedBranches.value, depth);
|
|
482
|
+
if (clickedAtDepth) return clickedAtDepth === key;
|
|
483
|
+
return interactionKeyAtDepth(focusedBranches.value, depth) === key;
|
|
484
|
+
};
|
|
485
|
+
const shownFlyoutKeys = computed(() => {
|
|
486
|
+
if (!ctx.flyoutMode.value) return [];
|
|
487
|
+
const keys = [];
|
|
488
|
+
for (const node of ctx.tree.value) {
|
|
489
|
+
if (isBranch(node) && horizontalBranchVisible(node.key, 0)) keys.push(node.key);
|
|
490
|
+
}
|
|
491
|
+
return keys;
|
|
492
|
+
});
|
|
493
|
+
const repositionOpenFlyouts = () => {
|
|
494
|
+
for (const key of shownFlyoutKeys.value) positionFlyout(key);
|
|
495
|
+
};
|
|
496
|
+
let viewportListenersActive = false;
|
|
497
|
+
const attachViewportListeners = () => {
|
|
498
|
+
if (viewportListenersActive || typeof document === "undefined") return;
|
|
499
|
+
viewportListenersActive = true;
|
|
500
|
+
document.addEventListener("scroll", repositionOpenFlyouts, true);
|
|
501
|
+
window.addEventListener("resize", repositionOpenFlyouts);
|
|
502
|
+
};
|
|
503
|
+
const detachViewportListeners = () => {
|
|
504
|
+
if (!viewportListenersActive || typeof document === "undefined") return;
|
|
505
|
+
viewportListenersActive = false;
|
|
506
|
+
document.removeEventListener("scroll", repositionOpenFlyouts, true);
|
|
507
|
+
window.removeEventListener("resize", repositionOpenFlyouts);
|
|
508
|
+
};
|
|
509
|
+
watch(
|
|
510
|
+
shownFlyoutKeys,
|
|
511
|
+
(keys, prev) => {
|
|
512
|
+
if (keys.length > 0 && prev.length === 0) attachViewportListeners();
|
|
513
|
+
else if (keys.length === 0 && prev.length > 0) detachViewportListeners();
|
|
514
|
+
for (const key of keys) positionFlyout(key);
|
|
515
|
+
},
|
|
516
|
+
{ flush: "post" }
|
|
517
|
+
);
|
|
518
|
+
return {
|
|
519
|
+
hovered,
|
|
520
|
+
hoveredBranches,
|
|
521
|
+
focusedBranches,
|
|
522
|
+
clickedBranches,
|
|
523
|
+
select,
|
|
524
|
+
toggleFlyout,
|
|
525
|
+
openFlyout,
|
|
526
|
+
closeHorizontalMenus,
|
|
527
|
+
setBranchInteraction,
|
|
528
|
+
keepsPointerInside,
|
|
529
|
+
interactionKeyAtDepth,
|
|
530
|
+
horizontalBranchVisible,
|
|
531
|
+
shownFlyoutKeys,
|
|
532
|
+
setFlyoutRef,
|
|
533
|
+
flyoutTriggers,
|
|
534
|
+
flyoutPanels,
|
|
535
|
+
suppressFocusOpen: { get: () => suppressFocusOpen },
|
|
536
|
+
setSuppressFocusOpen: (value) => {
|
|
537
|
+
suppressFocusOpen = value;
|
|
538
|
+
},
|
|
539
|
+
cancelClose,
|
|
540
|
+
scheduleOpen,
|
|
541
|
+
scheduleClose,
|
|
542
|
+
cancelAllTimers
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
function createNavMenuKeydownHandler(deps) {
|
|
546
|
+
const {
|
|
547
|
+
items,
|
|
548
|
+
flyoutMode,
|
|
549
|
+
expanded,
|
|
550
|
+
toggle,
|
|
551
|
+
openFlyout,
|
|
552
|
+
closeHorizontalMenus,
|
|
553
|
+
horizontalBranchVisible,
|
|
554
|
+
setBranchInteraction,
|
|
555
|
+
focusedBranches,
|
|
556
|
+
collapsed,
|
|
557
|
+
hoveredBranches,
|
|
558
|
+
clickedBranches,
|
|
559
|
+
setSuppressFocusOpen
|
|
560
|
+
} = deps;
|
|
561
|
+
return (e) => {
|
|
562
|
+
const root = e.currentTarget;
|
|
563
|
+
const buttons = Array.from(root.querySelectorAll("[data-iris-nav-item]")).filter(
|
|
564
|
+
(button) => !button.closest('[data-iris-nav-children][aria-hidden="true"]')
|
|
565
|
+
);
|
|
566
|
+
if (buttons.length === 0) return;
|
|
567
|
+
const idx = buttons.indexOf(document.activeElement);
|
|
568
|
+
const focusAt = (i) => buttons[(i + buttons.length) % buttons.length]?.focus();
|
|
569
|
+
const key = idx >= 0 ? buttons[idx]?.getAttribute("data-key") : void 0;
|
|
570
|
+
const node = key ? findNavNode(items, key) : void 0;
|
|
571
|
+
const depth = idx >= 0 ? Number(buttons[idx]?.getAttribute("data-depth") ?? 0) : 0;
|
|
572
|
+
switch (e.key) {
|
|
573
|
+
case "ArrowDown": {
|
|
574
|
+
e.preventDefault();
|
|
575
|
+
if (flyoutMode() && node && isBranch(node)) {
|
|
576
|
+
openFlyout(key);
|
|
577
|
+
const group = buttons[idx].closest("[data-iris-nav-group]");
|
|
578
|
+
void nextTick(() => {
|
|
579
|
+
group?.querySelector("[data-iris-nav-children] [data-iris-nav-item]")?.focus();
|
|
580
|
+
});
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
focusAt(idx < 0 ? 0 : idx + 1);
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
case "ArrowUp": {
|
|
587
|
+
e.preventDefault();
|
|
588
|
+
if (flyoutMode() && node && isBranch(node) && horizontalBranchVisible(key, depth)) {
|
|
589
|
+
setBranchInteraction(focusedBranches, key, false);
|
|
590
|
+
setBranchInteraction(clickedBranches, key, false);
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
focusAt(idx < 0 ? buttons.length - 1 : idx - 1);
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
case "Home":
|
|
597
|
+
e.preventDefault();
|
|
598
|
+
buttons[0]?.focus();
|
|
599
|
+
return;
|
|
600
|
+
case "End":
|
|
601
|
+
e.preventDefault();
|
|
602
|
+
buttons[buttons.length - 1]?.focus();
|
|
603
|
+
return;
|
|
604
|
+
case "Escape": {
|
|
605
|
+
if (flyoutMode()) {
|
|
606
|
+
const openKeys = [
|
|
607
|
+
...hoveredBranches.value,
|
|
608
|
+
...clickedBranches.value,
|
|
609
|
+
...focusedBranches.value
|
|
610
|
+
];
|
|
611
|
+
if (openKeys.length > 0) {
|
|
612
|
+
e.preventDefault();
|
|
613
|
+
const openTop = openKeys.find((k) => findNavPath(items, k).length === 1);
|
|
614
|
+
closeHorizontalMenus();
|
|
615
|
+
if (openTop) {
|
|
616
|
+
setSuppressFocusOpen(true);
|
|
617
|
+
buttons.find((b) => b.getAttribute("data-key") === openTop)?.focus();
|
|
618
|
+
void nextTick(() => {
|
|
619
|
+
setSuppressFocusOpen(false);
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
if (collapsed || idx < 0 || !key || !node) return;
|
|
628
|
+
if (e.key === "ArrowRight") {
|
|
629
|
+
e.preventDefault();
|
|
630
|
+
if (isBranch(node)) {
|
|
631
|
+
if (flyoutMode() || !expanded().includes(key)) {
|
|
632
|
+
if (flyoutMode()) openFlyout(key);
|
|
633
|
+
else toggle(key);
|
|
634
|
+
const group = buttons[idx].closest("[data-iris-nav-group]");
|
|
635
|
+
void nextTick(() => {
|
|
636
|
+
group?.querySelector("[data-iris-nav-children] [data-iris-nav-item]")?.focus();
|
|
637
|
+
});
|
|
638
|
+
} else {
|
|
639
|
+
focusAt(idx + 1);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
} else if (e.key === "ArrowLeft") {
|
|
643
|
+
e.preventDefault();
|
|
644
|
+
if (flyoutMode() && isBranch(node)) {
|
|
645
|
+
setBranchInteraction(focusedBranches, key, false);
|
|
646
|
+
setBranchInteraction(clickedBranches, key, false);
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
if (isBranch(node) && expanded().includes(key)) {
|
|
650
|
+
toggle(key);
|
|
651
|
+
} else {
|
|
652
|
+
const parentKey = findNavPath(items, key).at(-2)?.key;
|
|
653
|
+
if (parentKey) {
|
|
654
|
+
buttons.find((b) => b.getAttribute("data-key") === parentKey)?.focus();
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
}
|
|
351
660
|
|
|
352
661
|
// src/admin/NavMenu.ts
|
|
353
|
-
var HOVER_OPEN_DELAY = 100;
|
|
354
|
-
var HOVER_CLOSE_DELAY = 150;
|
|
355
662
|
var IrisNavMenu = defineComponent({
|
|
356
663
|
name: "IrisNavMenu",
|
|
357
664
|
inheritAttrs: false,
|
|
@@ -413,170 +720,35 @@ var IrisNavMenu = defineComponent({
|
|
|
413
720
|
emit("update:expandedKeys", model.get());
|
|
414
721
|
}
|
|
415
722
|
};
|
|
416
|
-
const
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
if (openTimer) {
|
|
425
|
-
clearTimeout(openTimer);
|
|
426
|
-
openTimer = null;
|
|
427
|
-
}
|
|
428
|
-
};
|
|
429
|
-
const cancelClose = (key) => {
|
|
430
|
-
const timer = closeTimers.get(key);
|
|
431
|
-
if (timer) {
|
|
432
|
-
clearTimeout(timer);
|
|
433
|
-
closeTimers.delete(key);
|
|
434
|
-
}
|
|
435
|
-
};
|
|
436
|
-
const cancelAllTimers = () => {
|
|
437
|
-
clearOpenTimer();
|
|
438
|
-
for (const timer of closeTimers.values()) clearTimeout(timer);
|
|
439
|
-
closeTimers.clear();
|
|
440
|
-
};
|
|
441
|
-
onBeforeUnmount(cancelAllTimers);
|
|
442
|
-
const flyoutTriggers = /* @__PURE__ */ new Map();
|
|
443
|
-
const flyoutPanels = /* @__PURE__ */ new Map();
|
|
444
|
-
const setFlyoutRef = (map, key, el) => {
|
|
445
|
-
if (el instanceof HTMLElement) map.set(key, el);
|
|
446
|
-
else map.delete(key);
|
|
447
|
-
};
|
|
448
|
-
const positionFlyout = (key) => {
|
|
449
|
-
const trigger = flyoutTriggers.get(key);
|
|
450
|
-
const panel = flyoutPanels.get(key);
|
|
451
|
-
if (!trigger || !panel || typeof document === "undefined") return;
|
|
452
|
-
const rect = trigger.getBoundingClientRect();
|
|
453
|
-
const dir = getComputedStyle(trigger).direction;
|
|
454
|
-
panel.style.position = "fixed";
|
|
455
|
-
panel.style.top = `${props.collapsed ? rect.top : rect.bottom}px`;
|
|
456
|
-
if (dir === "rtl") {
|
|
457
|
-
panel.style.left = "";
|
|
458
|
-
panel.style.right = `${window.innerWidth - (props.collapsed ? rect.left : rect.right)}px`;
|
|
459
|
-
} else {
|
|
460
|
-
panel.style.right = "";
|
|
461
|
-
panel.style.left = `${props.collapsed ? rect.right : rect.left}px`;
|
|
462
|
-
}
|
|
463
|
-
};
|
|
464
|
-
onBeforeUnmount(() => {
|
|
465
|
-
detachViewportListeners();
|
|
466
|
-
flyoutTriggers.clear();
|
|
467
|
-
flyoutPanels.clear();
|
|
723
|
+
const flyout = createNavMenuFlyout({
|
|
724
|
+
items: props.items,
|
|
725
|
+
tree,
|
|
726
|
+
expanded,
|
|
727
|
+
flyoutMode: { value: flyoutMode.value },
|
|
728
|
+
collapsed: props.collapsed,
|
|
729
|
+
toggle,
|
|
730
|
+
emitSelect: (key, node) => emit("select", key, node)
|
|
468
731
|
});
|
|
469
|
-
const
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
key,
|
|
490
|
-
setTimeout(() => {
|
|
491
|
-
closeTimers.delete(key);
|
|
492
|
-
setBranchInteraction(hoveredBranches, key, false);
|
|
493
|
-
}, HOVER_CLOSE_DELAY)
|
|
494
|
-
);
|
|
495
|
-
};
|
|
496
|
-
const closeHorizontalMenus = () => {
|
|
497
|
-
if (!flyoutMode.value) return;
|
|
498
|
-
cancelAllTimers();
|
|
499
|
-
hovered.value = null;
|
|
500
|
-
hoveredBranches.value = [];
|
|
501
|
-
focusedBranches.value = [];
|
|
502
|
-
clickedBranches.value = [];
|
|
503
|
-
};
|
|
504
|
-
const select = (node) => {
|
|
505
|
-
if (node.disabled) return;
|
|
506
|
-
closeHorizontalMenus();
|
|
507
|
-
emit("select", node.key, node);
|
|
508
|
-
};
|
|
509
|
-
const toggleFlyout = (key) => {
|
|
510
|
-
cancelAllTimers();
|
|
511
|
-
const current = clickedBranches.value;
|
|
512
|
-
if (current.includes(key)) {
|
|
513
|
-
clickedBranches.value = current.filter((k) => k !== key);
|
|
514
|
-
setBranchInteraction(hoveredBranches, key, false);
|
|
515
|
-
setBranchInteraction(focusedBranches, key, false);
|
|
516
|
-
} else {
|
|
517
|
-
isolateAtDepth(key);
|
|
518
|
-
clickedBranches.value = [...clickedBranches.value, key];
|
|
519
|
-
}
|
|
520
|
-
};
|
|
521
|
-
const openFlyout = (key) => {
|
|
522
|
-
cancelAllTimers();
|
|
523
|
-
isolateAtDepth(key);
|
|
524
|
-
setBranchInteraction(focusedBranches, key, true);
|
|
525
|
-
};
|
|
526
|
-
const setBranchInteraction = (state, key, enabled) => {
|
|
527
|
-
const current = state.value;
|
|
528
|
-
if (enabled) {
|
|
529
|
-
if (!current.includes(key)) state.value = [...current, key];
|
|
530
|
-
} else if (current.includes(key)) {
|
|
531
|
-
state.value = current.filter((item) => item !== key);
|
|
532
|
-
}
|
|
533
|
-
};
|
|
534
|
-
const keepsPointerInside = (container, event) => {
|
|
535
|
-
if (!container || !(container instanceof HTMLElement)) return false;
|
|
536
|
-
const next = event.relatedTarget;
|
|
537
|
-
return !!(next && next instanceof Node && container.contains(next));
|
|
538
|
-
};
|
|
539
|
-
const interactionKeyAtDepth = (keys, depth) => keys.find((key) => findNavPath(props.items, key).length === depth + 1);
|
|
540
|
-
const horizontalBranchVisible = (key, depth) => {
|
|
541
|
-
const hoveredAtDepth = interactionKeyAtDepth(hoveredBranches.value, depth);
|
|
542
|
-
if (hoveredAtDepth) return hoveredAtDepth === key;
|
|
543
|
-
const clickedAtDepth = interactionKeyAtDepth(clickedBranches.value, depth);
|
|
544
|
-
if (clickedAtDepth) return clickedAtDepth === key;
|
|
545
|
-
return interactionKeyAtDepth(focusedBranches.value, depth) === key;
|
|
546
|
-
};
|
|
547
|
-
const shownFlyoutKeys = computed(() => {
|
|
548
|
-
if (!flyoutMode.value) return [];
|
|
549
|
-
const keys = [];
|
|
550
|
-
for (const node of tree.value) {
|
|
551
|
-
if (isBranch(node) && horizontalBranchVisible(node.key, 0)) keys.push(node.key);
|
|
552
|
-
}
|
|
553
|
-
return keys;
|
|
554
|
-
});
|
|
555
|
-
const repositionOpenFlyouts = () => {
|
|
556
|
-
for (const key of shownFlyoutKeys.value) positionFlyout(key);
|
|
557
|
-
};
|
|
558
|
-
let viewportListenersActive = false;
|
|
559
|
-
const attachViewportListeners = () => {
|
|
560
|
-
if (viewportListenersActive || typeof document === "undefined") return;
|
|
561
|
-
viewportListenersActive = true;
|
|
562
|
-
document.addEventListener("scroll", repositionOpenFlyouts, true);
|
|
563
|
-
window.addEventListener("resize", repositionOpenFlyouts);
|
|
564
|
-
};
|
|
565
|
-
const detachViewportListeners = () => {
|
|
566
|
-
if (!viewportListenersActive || typeof document === "undefined") return;
|
|
567
|
-
viewportListenersActive = false;
|
|
568
|
-
document.removeEventListener("scroll", repositionOpenFlyouts, true);
|
|
569
|
-
window.removeEventListener("resize", repositionOpenFlyouts);
|
|
570
|
-
};
|
|
571
|
-
watch(
|
|
572
|
-
shownFlyoutKeys,
|
|
573
|
-
(keys, prev) => {
|
|
574
|
-
if (keys.length > 0 && prev.length === 0) attachViewportListeners();
|
|
575
|
-
else if (keys.length === 0 && prev.length > 0) detachViewportListeners();
|
|
576
|
-
for (const key of keys) positionFlyout(key);
|
|
577
|
-
},
|
|
578
|
-
{ flush: "post" }
|
|
579
|
-
);
|
|
732
|
+
const {
|
|
733
|
+
hovered,
|
|
734
|
+
hoveredBranches,
|
|
735
|
+
focusedBranches,
|
|
736
|
+
clickedBranches,
|
|
737
|
+
select,
|
|
738
|
+
toggleFlyout,
|
|
739
|
+
openFlyout,
|
|
740
|
+
closeHorizontalMenus,
|
|
741
|
+
setBranchInteraction,
|
|
742
|
+
keepsPointerInside,
|
|
743
|
+
horizontalBranchVisible,
|
|
744
|
+
setFlyoutRef,
|
|
745
|
+
flyoutTriggers,
|
|
746
|
+
flyoutPanels,
|
|
747
|
+
suppressFocusOpen,
|
|
748
|
+
cancelClose,
|
|
749
|
+
scheduleOpen,
|
|
750
|
+
scheduleClose
|
|
751
|
+
} = flyout;
|
|
580
752
|
const itemClass = (opts) => {
|
|
581
753
|
const depth = Math.min(9, opts.depth);
|
|
582
754
|
return [
|
|
@@ -712,7 +884,7 @@ var IrisNavMenu = defineComponent({
|
|
|
712
884
|
}
|
|
713
885
|
},
|
|
714
886
|
onFocusin: () => {
|
|
715
|
-
if (suppressFocusOpen) return;
|
|
887
|
+
if (suppressFocusOpen.get()) return;
|
|
716
888
|
setBranchInteraction(focusedBranches, node.key, true);
|
|
717
889
|
},
|
|
718
890
|
onFocusout: (event) => {
|
|
@@ -765,104 +937,23 @@ var IrisNavMenu = defineComponent({
|
|
|
765
937
|
},
|
|
766
938
|
{ flush: "post" }
|
|
767
939
|
);
|
|
768
|
-
const onKeydown = (
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
void nextTick(() => {
|
|
786
|
-
group?.querySelector("[data-iris-nav-children] [data-iris-nav-item]")?.focus();
|
|
787
|
-
});
|
|
788
|
-
return;
|
|
789
|
-
}
|
|
790
|
-
focusAt(idx < 0 ? 0 : idx + 1);
|
|
791
|
-
return;
|
|
792
|
-
}
|
|
793
|
-
case "ArrowUp": {
|
|
794
|
-
e.preventDefault();
|
|
795
|
-
if (flyoutMode.value && node && isBranch(node) && horizontalBranchVisible(key, depth)) {
|
|
796
|
-
setBranchInteraction(focusedBranches, key, false);
|
|
797
|
-
setBranchInteraction(clickedBranches, key, false);
|
|
798
|
-
return;
|
|
799
|
-
}
|
|
800
|
-
focusAt(idx < 0 ? buttons.length - 1 : idx - 1);
|
|
801
|
-
return;
|
|
802
|
-
}
|
|
803
|
-
case "Home":
|
|
804
|
-
e.preventDefault();
|
|
805
|
-
buttons[0]?.focus();
|
|
806
|
-
return;
|
|
807
|
-
case "End":
|
|
808
|
-
e.preventDefault();
|
|
809
|
-
buttons[buttons.length - 1]?.focus();
|
|
810
|
-
return;
|
|
811
|
-
case "Escape": {
|
|
812
|
-
if (flyoutMode.value) {
|
|
813
|
-
const openKeys = [
|
|
814
|
-
...hoveredBranches.value,
|
|
815
|
-
...clickedBranches.value,
|
|
816
|
-
...focusedBranches.value
|
|
817
|
-
];
|
|
818
|
-
if (openKeys.length > 0) {
|
|
819
|
-
e.preventDefault();
|
|
820
|
-
const openTop = openKeys.find((k) => findNavPath(props.items, k).length === 1);
|
|
821
|
-
closeHorizontalMenus();
|
|
822
|
-
if (openTop) {
|
|
823
|
-
suppressFocusOpen = true;
|
|
824
|
-
buttons.find((b) => b.getAttribute("data-key") === openTop)?.focus();
|
|
825
|
-
void nextTick(() => {
|
|
826
|
-
suppressFocusOpen = false;
|
|
827
|
-
});
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
return;
|
|
832
|
-
}
|
|
833
|
-
}
|
|
834
|
-
if (props.collapsed || idx < 0 || !key || !node) return;
|
|
835
|
-
if (e.key === "ArrowRight") {
|
|
836
|
-
e.preventDefault();
|
|
837
|
-
if (isBranch(node)) {
|
|
838
|
-
if (flyoutMode.value || !expanded.value.includes(key)) {
|
|
839
|
-
if (flyoutMode.value) openFlyout(key);
|
|
840
|
-
else toggle(key);
|
|
841
|
-
const group = buttons[idx].closest("[data-iris-nav-group]");
|
|
842
|
-
void nextTick(() => {
|
|
843
|
-
group?.querySelector("[data-iris-nav-children] [data-iris-nav-item]")?.focus();
|
|
844
|
-
});
|
|
845
|
-
} else {
|
|
846
|
-
focusAt(idx + 1);
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
} else if (e.key === "ArrowLeft") {
|
|
850
|
-
e.preventDefault();
|
|
851
|
-
if (flyoutMode.value && isBranch(node)) {
|
|
852
|
-
setBranchInteraction(focusedBranches, key, false);
|
|
853
|
-
setBranchInteraction(clickedBranches, key, false);
|
|
854
|
-
return;
|
|
855
|
-
}
|
|
856
|
-
if (isBranch(node) && expanded.value.includes(key)) {
|
|
857
|
-
toggle(key);
|
|
858
|
-
} else {
|
|
859
|
-
const parentKey = findNavPath(props.items, key).at(-2)?.key;
|
|
860
|
-
if (parentKey) {
|
|
861
|
-
buttons.find((b) => b.getAttribute("data-key") === parentKey)?.focus();
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
}
|
|
865
|
-
};
|
|
940
|
+
const onKeydown = createNavMenuKeydownHandler({
|
|
941
|
+
items: props.items,
|
|
942
|
+
flyoutMode: () => flyoutMode.value,
|
|
943
|
+
expanded: () => expanded.value,
|
|
944
|
+
toggle,
|
|
945
|
+
openFlyout,
|
|
946
|
+
closeHorizontalMenus,
|
|
947
|
+
horizontalBranchVisible,
|
|
948
|
+
setBranchInteraction,
|
|
949
|
+
focusedBranches,
|
|
950
|
+
hoveredBranches,
|
|
951
|
+
clickedBranches,
|
|
952
|
+
setSuppressFocusOpen: (v) => {
|
|
953
|
+
flyout.setSuppressFocusOpen(v);
|
|
954
|
+
},
|
|
955
|
+
collapsed: props.collapsed
|
|
956
|
+
});
|
|
866
957
|
const menuClass = [
|
|
867
958
|
"iris-nav-menu",
|
|
868
959
|
`iris-nav-menu--${props.orientation}`,
|
|
@@ -2033,5 +2124,5 @@ function useAdminPreferences(preferences, hydrate = true) {
|
|
|
2033
2124
|
}
|
|
2034
2125
|
|
|
2035
2126
|
export { DropdownContextKey, IrisAdminBreadcrumb, IrisAdminLayout, IrisAdminTabs, IrisBreadcrumb, IrisBreadcrumbItem, IrisDropdown, IrisDropdownItem, IrisDropdownMenu, IrisDropdownSeparator, IrisDropdownTrigger, IrisIcon, IrisNavMenu, useAdminPreferences, useAdminShell, useTabsNav };
|
|
2036
|
-
//# sourceMappingURL=chunk-
|
|
2037
|
-
//# sourceMappingURL=chunk-
|
|
2127
|
+
//# sourceMappingURL=chunk-ASFDGYIR.js.map
|
|
2128
|
+
//# sourceMappingURL=chunk-ASFDGYIR.js.map
|