@progress/kendo-vue-layout
Version:
368 lines (367 loc) • 11.5 kB
JavaScript
/**
* @license
*-------------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the package root for more information
*-------------------------------------------------------------------------------------------
*/
import { defineComponent as c, createVNode as n, h as u } from "vue";
import { setRef as F, classNames as L, getRef as y, guid as D, getTemplate as m, Icon as C, getIconName as B } from "@progress/kendo-vue-common";
import { Popup as N } from "@progress/kendo-vue-popup";
import { isFirstItemFromSiblings as T, shouldOpenItem as S } from "../utils/itemsIdsUtils.mjs";
import { getDOMElementId as I, convertBoolDirectionToString as p, getPopupSettings as P } from "../utils/misc.mjs";
import { MenuItemLink as A } from "./MenuItemLink.mjs";
import { MenuItemArrow as E } from "./MenuItemArrow.mjs";
const K = /* @__PURE__ */ c({
name: "KendoMenuItemInternal",
emits: {
keydown: null,
mouseover: null,
mouseleave: null,
blur: null,
focus: null,
click: null,
mousedown: null
},
props: {
item: Object,
focusedItemId: String,
lastItemIdToBeOpened: String,
tabbableItemId: String,
itemRender: [String, Object, Function],
linkRender: [String, Object, Function],
isMenuVertical: Boolean,
isDirectionRightToLeft: Boolean,
menuGuid: String,
originalItemNeeded: Function
},
created() {
this.itemElement = null, this.prevFocusedItemId = this.$props.focusedItemId, this.isFirstRender = !0, this._anchor = D();
},
data() {
return {
opened: !1
};
},
mounted() {
this.itemElement = y(this, "kendoAnchor");
const e = this.$props.focusedItemId, t = this.$props.item.id;
e && e === t && this.itemElement && this.itemElement.focus(), this.isFirstRender = !1;
},
watch: {
focusedItemId: function(e, t) {
this.prevFocusedItemId = t;
}
},
updated() {
const e = this.$props.focusedItemId, t = this.$props.item.id;
e ? this.prevFocusedItemId !== e && e === t && !this.itemElement.contains(document.activeElement) && this.itemElement.focus() : document.activeElement === this.itemElement && this.itemElement.blur();
},
computed: {
hasItems() {
return this.$props.item.items.length > 0;
},
currentItemRender() {
return this.$props.item.render || this.$props.itemRender;
},
currentLinkRender() {
return this.$props.item.linkRender || this.$props.linkRender;
},
contentRender() {
return this.$props.item.contentParentItemId ? this.$props.item.contentRender : null;
},
currentOpened() {
const e = this.$props;
return this.hasItems && S(e.item.id, e.lastItemIdToBeOpened) && // HACK: Wait for the second render because otherwise the scenario of
// popup inside popup throws an error (for example, hover of item with id '0_0').
!this.isFirstRender;
},
currentFocused() {
const e = this.$props.focusedItemId, t = this.$props.item.id;
return e === t;
},
popupClassName() {
return L({
"k-menu-popup": !0,
"k-overflow-visible": !0,
"k-rtl": this.$props.isDirectionRightToLeft,
[this.item.popupClass]: this.item.popupClass
});
},
menuItemClassName() {
const e = this.$props.item;
return {
"k-item": !0,
"k-menu-item": !0,
"k-first": T(e.id),
"k-last": e.isLastFromSiblings,
"k-disabled": e.disabled,
[e.cssClass ? e.cssClass : ""]: e.cssClass
};
}
},
render() {
const {
icon: e,
svgIcon: t,
id: o,
contentParentItemId: l,
items: G,
text: a,
cssStyle: f,
disabled: $,
url: g,
separator: M
} = this.$props.item, s = o, k = function() {
const i = l;
return n("div", {
class: "k-content",
role: "presentation"
}, [function(r) {
return m.call(this, {
h: u,
template: this.contentRender,
additionalProps: r
});
}.call(this, {
item: this.handleOriginalItemNeeded(i),
itemId: i
})]);
}, b = function() {
return e || t ? n(C, {
name: B(e),
icon: t
}, null) : null;
}, R = function() {
return this.hasItems ? n(E, {
itemId: o,
verticalMenu: this.$props.isMenuVertical,
dir: p(this.$props.isDirectionRightToLeft),
key: "2"
}, null) : null;
}, h = this.$props.originalItemNeeded(o), v = function() {
const i = n("span", {
class: "k-menu-link-text"
}, [a]), d = m.call(this, {
h: u,
template: this.currentItemRender,
defaultRendering: i,
additionalProps: {
item: h,
itemId: o,
key: "1"
}
}), r = n(A, {
url: g,
opened: this.currentOpened,
focused: this.currentFocused
}, {
default: () => [[b.call(this), d, R.call(this)]]
});
return m.call(this, {
h: u,
template: this.currentLinkRender,
defaultRendering: r,
additionalProps: {
item: h,
itemId: o,
opened: this.currentOpened,
dir: p(this.$props.isDirectionRightToLeft)
}
});
}, O = function() {
const {
anchorAlign: i,
popupAlign: d,
collision: r
} = P(s, this.$props.isMenuVertical, this.$props.isDirectionRightToLeft);
return n(N, {
anchor: this._anchor,
show: this.currentOpened,
popupClass: this.popupClassName,
anchorAlign: i,
popupAlign: d,
collision: r,
animate: !1,
key: "1"
}, {
default: () => [n(V, {
parentItemId: s,
items: this.$props.item.items,
menuGuid: this.$props.menuGuid,
focusedItemId: this.$props.focusedItemId,
lastItemIdToBeOpened: this.$props.lastItemIdToBeOpened,
tabbableItemId: this.$props.tabbableItemId,
itemRender: this.$props.itemRender,
linkRender: this.$props.linkRender,
isMenuVertical: this.$props.isMenuVertical,
isDirectionRightToLeft: this.$props.isDirectionRightToLeft,
class: "k-group k-menu-group k-menu-group-md k-reset",
onMouseover: this.handleItemMouseOver,
onMouseleave: this.handleItemMouseLeave,
onMousedown: this.handleMouseDown,
onBlur: this.handleItemMouseBlur,
onFocus: this.handleItemMouseFocus,
onClick: this.handleClick,
onKeydown: this.handleKeyDown,
originalItemNeeded: this.handleOriginalItemNeeded
}, null)]
});
}, w = n("li", {
class: "k-separator k-item",
"aria-hidden": !0,
key: s
}, null);
return M ? w : n("li", {
class: this.menuItemClassName,
style: f,
tabindex: s === this.$props.tabbableItemId ? 0 : -1,
onMouseover: this.onMouseOver,
onMouseleave: this.onMouseLeave,
onMousedown: (i) => this.handleMouseDown(i),
onFocusout: () => this.handleBlur(s),
onFocusin: () => this.handleFocus(s),
onClick: (i) => this.handleClick(i, s),
onKeydown: this.handleKeyDown,
role: "menuitem",
"aria-disabled": $ ? !0 : void 0,
"aria-haspopup": this.hasItems ? !0 : void 0,
"aria-expanded": this.hasItems ? this.currentOpened : void 0,
"aria-label": a,
"aria-owns": this.currentOpened ? I(this.$props.menuGuid, s) : void 0,
ref: F(this, "kendoAnchor"),
key: "0"
}, [this.contentRender ? k.call(this) : v.call(this), O.call(this)]);
},
methods: {
handleKeyDown(e) {
this.$emit("keydown", e);
},
handleItemMouseOver(e) {
this.$emit("mouseover", e);
},
handleItemMouseLeave(e) {
this.$emit("mouseleave", e);
},
handleItemMouseBlur(e) {
this.$emit("blur", e);
},
handleItemMouseFocus(e) {
this.$emit("focus", e);
},
handleClick(e, t) {
this.$emit("click", e, t);
},
handleBlur(e) {
this.$emit("blur", e);
},
handleFocus(e) {
this.$emit("focus", e);
},
handleMouseDown(e) {
this.$emit("mousedown", e);
},
handleOriginalItemNeeded(e) {
return this.$props.originalItemNeeded(e);
},
onMouseOver(e) {
this.$emit("mouseover", this.$props.item.id), e.stopPropagation();
},
onMouseLeave(e) {
this.$emit("mouseleave", this.$props.item.id), e.stopPropagation();
}
}
}), V = /* @__PURE__ */ c({
name: "KendoMenuItemInternalsList",
emits: {
keydown: null,
mouseover: null,
mouseleave: null,
blur: null,
focus: null,
click: null,
mousedown: null
},
props: {
items: Array,
parentItemId: {
type: String,
default: void 0
},
focusedItemId: String,
lastItemIdToBeOpened: String,
tabbableItemId: String,
itemRender: [String, Object, Function],
linkRender: [String, Object, Function],
isMenuVertical: Boolean,
isDirectionRightToLeft: Boolean,
menuGuid: String,
originalItemNeeded: Function
},
render() {
const e = this.$props.parentItemId, t = function() {
return this.$props.items.length > 0 ? this.$props.items.map(function(o, l) {
return n(K, {
item: o,
isMenuVertical: this.$props.isMenuVertical,
isDirectionRightToLeft: this.$props.isDirectionRightToLeft,
focusedItemId: this.$props.focusedItemId,
lastItemIdToBeOpened: this.$props.lastItemIdToBeOpened,
tabbableItemId: this.$props.tabbableItemId,
itemRender: this.$props.itemRender,
linkRender: this.$props.linkRender,
menuGuid: this.$props.menuGuid,
onMouseover: this.handleItemMouseOver,
onMouseleave: this.handleItemMouseLeave,
onMousedown: this.handleItemMouseDown,
onKeydown: this.handleKeyDown,
onBlur: this.handleItemMouseBlur,
onFocus: this.handleItemMouseFocus,
onClick: this.handleItemMouseClick,
originalItemNeeded: this.handleOriginalItemNeeded,
key: l
}, null);
}, this) : null;
};
return n("ul", {
role: e !== void 0 ? "menu" : "menubar",
id: e !== void 0 ? I(this.$props.menuGuid, e) : void 0
}, [t.call(this)]);
},
methods: {
handleKeyDown(e) {
this.$emit("keydown", e);
},
handleOriginalItemNeeded(e) {
return this.$props.originalItemNeeded(e);
},
handleItemMouseOver(e) {
this.$emit("mouseover", e);
},
handleItemMouseLeave(e) {
this.$emit("mouseleave", e);
},
handleItemMouseDown(e) {
this.$emit("mousedown", e);
},
handleItemMouseBlur(e) {
this.$emit("blur", e);
},
handleItemMouseFocus(e) {
this.$emit("focus", e);
},
handleItemMouseClick(e, t) {
this.$emit("click", e, t);
},
onMouseOver(e) {
this.$props.parentItemId !== void 0 && (this.$emit("mouseover", this.$props.parentItemId), e.stopPropagation());
},
onMouseLeave(e) {
this.$props.parentItemId !== void 0 && (this.$emit("mouseleave", this.$props.parentItemId), e.stopPropagation());
}
}
});
export {
K as MenuItemInternal,
V as MenuItemInternalsList
};