@progress/kendo-react-layout
Version:
React Layout components enable you to create a perceptive and intuitive layout of web projects. KendoReact Layout package
243 lines (242 loc) • 9.45 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 * as s from "react";
import { getActiveElement as u, IconWrap as h, classNames as p } from "@progress/kendo-react-common";
import { Popup as c } from "@progress/kendo-react-popup";
import { shouldOpenItem as I, isFirstItemFromSiblings as M } from "../utils/itemsIdsUtils.mjs";
import { getDOMElementId as d, convertBoolDirectionToString as m, getPopupSettings as g } from "../utils/misc.mjs";
import { MenuItemLink as f } from "./MenuItemLink.mjs";
import { MenuItemArrow as v } from "./MenuItemArrow.mjs";
class k extends s.Component {
constructor() {
super(...arguments), this.onMouseOver = (e) => {
this.props.onMouseOver(this.props.parentItemId), e.stopPropagation();
}, this.onMouseLeave = (e) => {
this.props.onMouseLeave(this.props.parentItemId), e.stopPropagation();
};
}
render() {
const e = this.props.parentItemId;
return /* @__PURE__ */ s.createElement(
"ul",
{
className: this.props.className,
role: this.props.role ? this.props.role : e !== void 0 ? "menu" : "menubar",
id: e !== void 0 ? d(this.props.menuGuid, e) : void 0,
onMouseOver: e !== void 0 ? this.onMouseOver : void 0,
onMouseLeave: e !== void 0 ? this.onMouseLeave : void 0,
"aria-orientation": this.props["aria-orientation"]
},
this.renderChildItems()
);
}
renderChildItems() {
return this.props.items.length > 0 ? this.props.items.map((e, t) => /* @__PURE__ */ s.createElement(
O,
{
item: e,
animate: this.props.animate,
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.props.onMouseOver,
onMouseLeave: this.props.onMouseLeave,
onMouseDown: this.props.onMouseDown,
onBlur: this.props.onBlur,
onFocus: this.props.onFocus,
onClick: this.props.onClick,
onOriginalItemNeeded: this.props.onOriginalItemNeeded,
key: t
}
)) : null;
}
}
class O extends s.Component {
constructor(e) {
super(e), this.isFirstRender = !0, this.onMouseOver = (t) => {
this.props.onMouseOver(this.props.item.id), t.stopPropagation();
}, this.onMouseLeave = (t) => {
this.props.onMouseLeave(this.props.item.id), t.stopPropagation();
}, this.state = { opened: !1 };
}
componentDidMount() {
const e = this.props.focusedItemId, t = this.props.item.id;
e && e === t && this.itemElement.focus({ preventScroll: !0 }), this.isFirstRender = !1;
}
componentDidUpdate(e) {
const t = this.props.focusedItemId, o = this.props.item.id;
if (t) {
const n = u(document);
e.focusedItemId !== t && t === o && // https://github.com/telerik/kendo-react/issues/216 :
// No need to focus the wrapping menu item DOM element
// when a child DOM element was clicked.
!this.itemElement.contains(n) && this.itemElement.focus({ preventScroll: !0 });
}
}
render() {
const e = this.props.item, t = e.id, o = d(this.props.menuGuid, t), n = e.separator;
return /* @__PURE__ */ s.createElement(s.Fragment, null, n ? /* @__PURE__ */ s.createElement(
"li",
{
className: "k-separator k-item",
"aria-hidden": !0,
key: o,
id: o,
ref: (i) => {
this.itemElement = i;
}
}
) : /* @__PURE__ */ s.createElement(
"li",
{
id: o,
className: this.getMenuItemClassName(e),
style: e.cssStyle,
tabIndex: t === this.props.tabbableItemId ? 0 : -1,
onMouseOver: this.onMouseOver,
onMouseLeave: this.onMouseLeave,
onMouseDown: (i) => this.props.onMouseDown(i),
onBlur: (i) => this.props.onBlur(t, i),
onFocus: () => this.props.onFocus(t),
onClick: (i) => this.props.onClick(i, t),
role: "menuitem",
"aria-disabled": e.disabled ? !0 : void 0,
"aria-haspopup": e.items.length > 0 ? !0 : void 0,
"aria-expanded": e.items.length > 0 ? this.Opened : void 0,
"aria-label": e.text,
"aria-owns": this.Opened ? o : void 0,
ref: (i) => {
this.itemElement = i;
},
key: o
},
this.contentRender ? this.renderContent() : this.renderMenuItemLink()
), this.renderPopupIfOpened());
}
renderContent() {
const e = this.props.item.contentParentItemId;
return /* @__PURE__ */ s.createElement("div", { className: "k-content", role: "presentation" }, /* @__PURE__ */ s.createElement(this.contentRender, { item: this.props.onOriginalItemNeeded(e), itemId: e }));
}
renderMenuItemLink() {
const e = this.props.item;
if (this.linkRender)
return /* @__PURE__ */ s.createElement(
this.linkRender,
{
item: this.props.onOriginalItemNeeded(e.id),
itemId: e.id,
opened: this.Opened,
dir: m(this.props.isDirectionRightToLeft)
}
);
const t = this.itemRender ? /* @__PURE__ */ s.createElement(this.itemRender, { item: this.props.onOriginalItemNeeded(e.id), itemId: e.id, key: "1" }) : /* @__PURE__ */ s.createElement("span", { className: "k-menu-link-text" }, e.text);
return /* @__PURE__ */ s.createElement(f, { url: e.url, opened: this.Opened }, this.renderMenuIconIfApplicable(), t, this.renderArrowIfApplicable());
}
renderPopupIfOpened() {
const e = this.props.item.id, t = this.props.animate, { anchorAlign: o, popupAlign: n, collision: i, animationDirection: r } = g(
e,
this.props.isMenuVertical,
this.props.isDirectionRightToLeft
), l = t === !0 ? { openDuration: 300, closeDuration: 300, direction: r } : t === !1 ? !1 : {
openDuration: (t == null ? void 0 : t.openDuration) || 300,
closeDuration: (t == null ? void 0 : t.closeDuration) || 300,
direction: (t == null ? void 0 : t.direction) || r
};
return /* @__PURE__ */ s.createElement(
c,
{
anchor: this.itemElement,
show: this.Opened,
popupClass: this.getPopupClassName(),
anchorAlign: o,
popupAlign: n,
collision: i,
animate: l,
key: "1"
},
/* @__PURE__ */ s.createElement(
k,
{
parentItemId: e,
animate: this.props.animate,
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,
className: "k-group k-menu-group k-reset k-menu-group-md",
onMouseOver: this.props.onMouseOver,
onMouseLeave: this.props.onMouseLeave,
onMouseDown: this.props.onMouseDown,
onBlur: this.props.onBlur,
onFocus: this.props.onFocus,
onClick: this.props.onClick,
onOriginalItemNeeded: this.props.onOriginalItemNeeded
}
)
);
}
renderMenuIconIfApplicable() {
const { icon: e, svgIcon: t } = this.props.item;
return e || t ? /* @__PURE__ */ s.createElement(h, { name: e, icon: t, key: "0" }) : null;
}
renderArrowIfApplicable() {
return this.props.item.items.length > 0 ? /* @__PURE__ */ s.createElement("span", { className: "k-menu-expand-arrow", "aria-hidden": !0 }, /* @__PURE__ */ s.createElement(
v,
{
itemId: this.props.item.id,
verticalMenu: this.props.isMenuVertical,
dir: m(this.props.isDirectionRightToLeft),
key: "2"
}
)) : null;
}
get itemRender() {
return this.props.item.render || this.props.itemRender;
}
get linkRender() {
return this.props.item.linkRender || this.props.linkRender;
}
get contentRender() {
return this.props.item.contentParentItemId ? this.props.item.contentRender : null;
}
get Opened() {
const e = this.props;
return e.item.items.length > 0 && I(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;
}
getPopupClassName() {
return p("k-menu-popup", { "k-rtl": this.props.isDirectionRightToLeft });
}
getMenuItemClassName(e) {
return p(
"k-item",
"k-menu-item",
{
"k-first": M(e.id),
"k-last": e.isLastFromSiblings,
"k-disabled": e.disabled
},
e.cssClass
);
}
}
export {
O as MenuItemInternal,
k as MenuItemInternalsList
};