UNPKG

@progress/kendo-react-layout

Version:

React Layout components enable you to create a perceptive and intuitive layout of web projects. KendoReact Layout package

256 lines (255 loc) 8.68 kB
/** * @license *------------------------------------------------------------------------------------------- * Copyright © 2026 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the package root for more information *------------------------------------------------------------------------------------------- */ import * as r from "react"; import u from "prop-types"; import { dispatchEvent as oe, Keys as B, classNames as ce } from "@progress/kendo-react-common"; import { ZERO_LEVEL_ZERO_ITEM_ID as A, EMPTY_ID as i, getRootParentId as _, isIdEmptyOrZeroLevel as P, getItemById as S, isIdZeroLevel as O, getDirectParentId as W } from "../utils/itemsIdsUtils.mjs"; import { prepareInputItemsForInternalWork as se } from "../utils/prepareInputItemsForInternalWork.mjs"; import { getNewItemIdUponKeyboardNavigation as Z } from "../utils/getNewItemIdUponKeyboardNavigation.mjs"; import { getHoverOpenDelay as ue, getHoverCloseDelay as ie } from "../utils/hoverDelay.mjs"; import { MenuItemInternalsList as le } from "./MenuItemInternal.mjs"; import { DirectionHolder as ae } from "../utils/DirectionHolder.mjs"; import { MouseOverHandler as de } from "../utils/MouseOverHandler.mjs"; const q = { focusedItemId: i, hoveredItemId: i, tabbableItemId: A }, j = r.forwardRef((o, x) => { const R = r.useRef(null), g = r.useRef(null), h = r.useRef(null), k = r.useRef(new ae()), D = r.useRef([]), F = r.useRef([]), l = r.useRef(o); l.current = o; const [f, L] = r.useState({ ...q }), C = r.useRef(f); C.current = f; const H = r.useRef(() => { }), p = r.useRef(new de(o.openOnClick, () => H.current())), { items: z, inputItems: G } = se( o.items, o.children ); D.current = z, F.current = G, k.current.setIsDirectionRightToLeft(U()); function U() { return !!(l.current.dir !== void 0 ? l.current.dir === "rtl" : R.current && getComputedStyle(R.current).direction === "rtl"); } const b = r.useCallback(() => { g.current && (clearTimeout(g.current), g.current = null), h.current && (clearTimeout(h.current), h.current = null); }, []), K = r.useCallback(() => { b(), L({ ...q }); }, [b]); H.current = K; const y = r.useRef({ get element() { return R.current; }, reset: () => H.current() }); r.useImperativeHandle(x, () => y.current, []); const m = r.useCallback((e) => { L((t) => { const n = e === i ? t.tabbableItemId : _(e); return { hoveredItemId: e === i || P(t.hoveredItemId) && P(e) ? t.hoveredItemId : i, focusedItemId: e, tabbableItemId: n }; }); }, []), a = r.useCallback((e) => { L((t) => P(e) && P(t.focusedItemId) ? { hoveredItemId: e, focusedItemId: t.focusedItemId, tabbableItemId: t.tabbableItemId } : { hoveredItemId: e, focusedItemId: i, tabbableItemId: A }); }, []), I = r.useCallback((e) => S(e, F.current), []), T = r.useCallback( (e, t) => { oe(l.current.onSelect, e, y.current, { item: I(t), itemId: t }); }, [I] ), E = r.useCallback((e) => !l.current.customCloseItemIds || l.current.customCloseItemIds.indexOf(e) === -1, []), N = r.useCallback( (e) => { var c, s; const t = l.current, n = C.current; if (t.openOnClick && n.hoveredItemId !== i) { const d = e.target; ((c = R.current) == null ? void 0 : c.contains(d)) === !1 && (t.id && ((s = d.closest) != null && s.call(d, `[id^="${t.id}_"]`)) || a(i)); } }, [a] ), Y = r.useCallback( (e) => { const t = C.current, n = l.current, c = D.current; if (t.focusedItemId !== i) { const s = S(t.focusedItemId, c); let d = Z( c, s.id, e.keyCode, e.key, n.vertical, k.current.getIsDirectionRightToLeft() ); const v = S(d, c); if (v != null && v.separator && (d = Z( c, d, e.keyCode, e.key, n.vertical, k.current.getIsDirectionRightToLeft() )), s.id !== d && (e.preventDefault(), m(d)), (e.keyCode === B.enter || e.keyCode === B.space) && !s.disabled && (p.current.handleItemSelectedViaKeyboard(), T(e, s.id), !e.isDefaultPrevented() && s.items.length === 0 && s.url && window.location.assign(s.url)), e.keyCode === B.esc && O(s.id) && n.onClose) { const w = I(s.id); n.onClose({ target: y.current, item: w, itemId: s.id }); } } }, [m, T, I] ), $ = r.useCallback( (e) => { const t = C.current, n = l.current, c = n.openOnClick && !O(e) && t.hoveredItemId !== i; (p.current.IsMouseOverEnabled || c) && (b(), g.current = window.setTimeout(() => { a(e), g.current = null; }, ue(n))); }, [b, a] ), J = r.useCallback( (e) => { const t = C.current, n = l.current, c = n.openOnClick && !O(e) && t.hoveredItemId !== i; (p.current.IsMouseOverEnabled || c) && E(e) && (b(), h.current = window.setTimeout(() => { a(c ? W(e) : i), h.current = null; }, ie(n))); }, [b, E, a] ), Q = r.useCallback( (e) => { C.current.hoveredItemId === i ? m(e) : L((n) => ({ focusedItemId: e, hoveredItemId: n.hoveredItemId, tabbableItemId: _(e) })); }, [m] ), X = r.useCallback( (e, t) => { const n = D.current, c = S(t, n), s = C.current, d = l.current; if (!c.disabled) { const v = O(t), w = !c.items || c.items.length === 0; v ? (m(t), w ? a(i) : d.openOnClick && s.hoveredItemId !== i && _(s.hoveredItemId) === t ? a(i) : a(t)) : w && (m(t), a(i)), T(e, t), !e.isDefaultPrevented() && c.url && window.location.assign(c.url); } }, [m, a, T] ), ee = r.useCallback( (e, t) => { const n = l.current; n.onClose && n.onClose({ target: y.current, item: I(e), itemId: e, popupCloseEvent: t }); }, [I] ), te = r.useCallback( (e, t) => { var c; const n = l.current; if (E(e) && m(i), ((c = t.relatedTarget) == null ? void 0 : c.nodeName) === "LI") { const s = t.relatedTarget.getAttribute("id"); if (s != null && s.includes(n.id)) return; } if (O(e) && n.onClose) { const s = I(e); n.onClose({ target: y.current, item: s, itemId: e }); } }, [E, m, I] ), V = r.useRef(o.vertical); r.useEffect(() => () => { b(); }, [b]), r.useEffect(() => (o.openOnClick && document.addEventListener("mousedown", N), () => { document.removeEventListener("mousedown", N); }), [o.openOnClick, N]), r.useEffect(() => { const e = !!V.current != !!o.vertical, t = k.current.hasDirectionChanged(); (e || t) && K(), p.current.OpenOnClick = o.openOnClick, V.current = o.vertical; }); const re = () => ce( "k-reset", "k-header", "k-menu", { "k-menu-horizontal": !o.vertical }, { "k-menu-vertical": o.vertical }, o.className ); let M; f.hoveredItemId ? M = f.hoveredItemId : f.focusedItemId ? M = W(f.focusedItemId) : M = i; const ne = o.animate !== void 0 ? o.animate : !0; return /* @__PURE__ */ r.createElement( "div", { id: o.id, onKeyDown: Y, style: o.style, className: k.current.getIsDirectionRightToLeft() ? "k-rtl" : void 0, ref: R }, /* @__PURE__ */ r.createElement( le, { className: re(), "aria-orientation": o.vertical ? "vertical" : void 0, items: D.current, animate: ne, isMenuVertical: o.vertical, isDirectionRightToLeft: k.current.getIsDirectionRightToLeft(), focusedItemId: f.focusedItemId, lastItemIdToBeOpened: M, tabbableItemId: f.tabbableItemId, itemRender: o.itemRender, linkRender: o.linkRender, menuGuid: o.id, onMouseLeave: J, onMouseOver: $, onFocus: Q, onClick: X, onBlur: te, onOriginalItemNeeded: I, onPopupClose: ee, role: o.role } ) ); }); j.propTypes = { vertical: u.bool, items: u.arrayOf(u.object), style: u.object, animate: u.oneOfType([ u.bool, u.shape({ openDuration: u.number, closeDuration: u.number }) ]), dir: u.string, hoverOpenDelay: u.number, hoverCloseDelay: u.number, openOnClick: u.bool, itemRender: u.any, linkRender: u.any, customCloseItemIds: u.arrayOf(u.string), onSelect: u.func, onClose: u.func, role: u.string }; j.displayName = "Menu"; export { j as Menu };