@redocly/theme
Version:
Shared UI components lib
85 lines • 4.3 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.useNestedMenu = useNestedMenu;
const react_router_dom_1 = require("react-router-dom");
const react_1 = require("react");
const use_menu_item_expanded_1 = require("./use-menu-item-expanded");
const use_collapse_1 = require("./use-collapse");
const load_and_navigate_1 = require("../../utils/load-and-navigate");
const urls_1 = require("../../utils/urls");
function useNestedMenu({ item, labelRef, nestedMenuRef }) {
const [isExpanded, setIsExpanded] = (0, use_menu_item_expanded_1.useMenuItemExpanded)(item);
// we need to know when the item is collapsed after transition to remove children from DOM
const [canUnmount, setCanUnmount] = (0, react_1.useState)(!isExpanded);
const navigate = (0, react_router_dom_1.useNavigate)();
const location = (0, react_router_dom_1.useLocation)();
const { style } = (0, use_collapse_1.useCollapse)({
isExpanded,
collapseElRef: nestedMenuRef || { current: null },
onTransitionStateChange: (state) => {
var _a;
if (state === 'collapseEnd') {
setCanUnmount(true);
}
if (state === 'expandStart') {
setCanUnmount(false);
}
// signal that used in e2e tests to wait for the item to be expanded
if (state === 'expandEnd') {
(_a = labelRef === null || labelRef === void 0 ? void 0 : labelRef.current) === null || _a === void 0 ? void 0 : _a.dispatchEvent(new CustomEvent('menu:expand-end', { bubbles: true }));
}
},
});
function scrollIfNeeded(el, centerIfNeeded = false) {
const rect = el.getBoundingClientRect();
const isInViewport = rect.top >= 0 &&
rect.left >= 0 &&
rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.right <= (window.innerWidth || document.documentElement.clientWidth);
// Only scroll if element is in viewport to prevent page jumping
// @ts-ignore
if (isInViewport && typeof el.scrollIntoViewIfNeeded === 'function') {
// @ts-ignore
el.scrollIntoViewIfNeeded(centerIfNeeded);
}
}
// scroll to active element if needed
(0, react_1.useEffect)(() => {
if (item.active && labelRef && labelRef.current) {
scrollIfNeeded(labelRef.current, true); // center item on the first scroll
}
}, [labelRef, item.active]);
// scroll to expanded element if needed (position could change after collapse)
(0, react_1.useEffect)(() => {
if (item.active && isExpanded && labelRef && labelRef.current) {
scrollIfNeeded(labelRef.current);
}
}, [labelRef, isExpanded, item.active]);
const handleExpand = (0, react_1.useCallback)(() => __awaiter(this, void 0, void 0, function* () {
if (item.expanded === 'always' ||
(item.link && item.hasActiveSubItem && item.link !== (0, urls_1.withoutPathPrefix)(location.pathname))) {
return;
}
const [firstChild] = item.items;
if (!isExpanded && item.selectFirstItemOnExpand && firstChild.link) {
yield (0, load_and_navigate_1.loadAndNavigate)({ navigate, to: (0, urls_1.withPathPrefix)(firstChild.link) });
}
setIsExpanded(!isExpanded);
}), [item, isExpanded, navigate, location.pathname, setIsExpanded]);
return {
isExpanded,
canUnmount,
style,
handleExpand,
};
}
//# sourceMappingURL=use-nested-menu.js.map