@activecollab/components
Version:
ActiveCollab Components
126 lines • 4.39 kB
JavaScript
import React, { useState, useRef, useCallback, useMemo, Children, cloneElement, useEffect, useLayoutEffect } from "react";
import classNames from "classnames";
import { StyledNavListItemMore } from "./Item/Styles";
import { StyledNav, StyledNavAsSelect, StyledNavList } from "./Styles";
import { useResizeObserver } from "../../utils";
import { ExpandSingle } from "../Expanders/ExpandSingle";
import { Select } from "../Select/Select";
export const Nav = _ref => {
var _dimensions$width, _childDimensions$widt;
let {
children,
alignment = "left",
onSelect,
className,
role = "bold",
targetId
} = _ref;
const [active, setActive] = useState(0);
const [moreOpened, setMoreOpened] = useState(false);
const [type, setType] = useState("inline");
const setMoreOpen = useCallback(() => setMoreOpened(true), []);
const setMoreClose = useCallback(() => setMoreOpened(false), []);
const navItemNames = useMemo(() => {
return children ? Children.toArray(children).map(item => {
var _item$props;
return item == null || (_item$props = item.props) == null ? void 0 : _item$props.name;
}) : [];
}, [children]);
const allOptions = useMemo(() => {
return navItemNames == null ? void 0 : navItemNames.map((name, index) => {
return {
id: index,
name: name
};
});
}, [navItemNames]);
const navRef = useRef(null);
const wrapRef = useRef(null);
const dimensions = useResizeObserver(wrapRef);
const childDimensions = useResizeObserver(navRef);
const parentWidth = (_dimensions$width = dimensions == null ? void 0 : dimensions.width) != null ? _dimensions$width : 0;
const childWidth = (_childDimensions$widt = childDimensions == null ? void 0 : childDimensions.width) != null ? _childDimensions$widt : 0;
const [childrenWidth, setChildrenWidth] = useState(childWidth);
useLayoutEffect(() => {
if (type === "inline") setChildrenWidth(childWidth);
}, [childWidth, type]);
const onClick = useCallback(e => {
if (e.metaKey || e.ctrlKey) {
return;
}
if (e.target && e.currentTarget.dataset.index && !e.currentTarget.dataset.disabled) {
const index = Number(e.currentTarget.dataset.index);
setActive(index);
if (onSelect) {
onSelect(index);
}
}
}, [onSelect]);
const onMoreOptionClick = useCallback(id => {
setActive(id);
if (onSelect) {
onSelect(id);
}
}, [onSelect]);
useMemo(() => {
Children.forEach(children, (child, index) => {
if (child && child.props.active) {
setActive(index);
}
});
}, [children]);
const navAsSelect = useMemo(() => {
return /*#__PURE__*/React.createElement(StyledNavAsSelect, {
id: targetId,
$active: true
}, /*#__PURE__*/React.createElement("span", null, navItemNames[active]), /*#__PURE__*/React.createElement(ExpandSingle, {
expanded: moreOpened,
fill: "currentColor"
}));
}, [active, moreOpened, navItemNames, targetId]);
useEffect(() => {
if (!navRef.current || !wrapRef.current) return;
if (!childrenWidth || !parentWidth) return;
if (childrenWidth < parentWidth) {
setType("inline");
} else {
setType("dropdown");
}
}, [childrenWidth, parentWidth]);
if (!children) return;
return /*#__PURE__*/React.createElement(StyledNav, {
className: classNames("c-nav", className),
$align: alignment,
$role: role,
ref: wrapRef
}, /*#__PURE__*/React.createElement(StyledNavList, {
ref: navRef
}, type === "inline" && Children.toArray(children).map((child, index) => {
const element = child;
return /*#__PURE__*/cloneElement(element, {
active: index === active,
role,
onClick,
"data-index": index,
"data-disabled": element.props.disabled
});
}), type === "dropdown" ? /*#__PURE__*/React.createElement(StyledNavListItemMore, {
name: navItemNames[active],
role: role
}, /*#__PURE__*/React.createElement(Select, {
selected: active,
target: navAsSelect,
disabledInternalSort: true,
options: allOptions,
type: "single",
mode: "normal",
forceCloseMenu: true,
disableSearch: true,
keepSameOptionsOrder: true,
onChange: onMoreOptionClick,
onSelectOpen: setMoreOpen,
onSelectClose: setMoreClose
})) : null));
};
Nav.displayName = "Nav";
//# sourceMappingURL=Nav.js.map