UNPKG

@veracity/vui

Version:

Veracity UI is a React component library crafted for use within Veracity applications and pages. Based on Styled Components and @xstyled.

235 lines (233 loc) 7.96 kB
import { generateMenuItemId } from "../utils/string.js"; import colors_default from "../theme/foundations/colors.js"; import { cs } from "../utils/styles.js"; import { omitThemingProps, th } from "../core/theme.js"; import styled from "../core/styled.js"; import vui from "../core/vui.js"; import { Box } from "../box/box.js"; import { Button } from "../button/button.js"; import Popover from "../popover/popover.js"; import { Tooltip } from "../tooltip/tooltip.js"; import SidemenuItemContent from "./SidemenuItemContent.js"; import useSidemenuItem from "./useSidemenuItem.js"; import { useCallback, useEffect, useMemo } from "react"; import { jsx, jsxs } from "react/jsx-runtime"; //#region src/sidemenuV2/sidemenuItemV2.tsx const PopoverHovered = styled.div` &:hover .vui-sidemenu-item-popover .vui-button.vui-button { background: ${(p) => th.color(p.hoverColor)}; } &:hover div:last-child .vui-sidemenu-item-content > .vui-box > .vui-button.vui-button { background: ${(p) => th.color(p.hoverColor)}; } `; const SidemenuPopover = ({ isDark, className, buttonStyles, isExactlyActive, icon, title, isMenuExpanded, children }) => /* @__PURE__ */ jsx(Popover, { offset: [0, 52 - 240 - 2], placement: "right-start", trigger: "mouseenter", children: ({ isOpen }) => /* @__PURE__ */ jsxs(PopoverHovered, { hoverColor: isDark ? colors_default.seaBlue.main : colors_default.skyBlue.selected, children: [/* @__PURE__ */ jsx(Popover.Trigger, { as: Box, className: cs("vui-sidemenu-item-popover", className), children: /* @__PURE__ */ jsx(Button, { ...buttonStyles, borderLeft: `3px solid ${isDark ? "digiGreen.main" : "seaBlue.main"}`, isActive: isExactlyActive, className: cs("focusAsBorder"), children: /* @__PURE__ */ jsx(SidemenuItemContent, { icon, iconSize: buttonStyles.iconSize, title, isMenuExpanded }) }) }), /* @__PURE__ */ jsx(Popover.Content, { elevation: "none", className: cs("vui-sidemenu-item-content", className), children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", justifyContent: "start", w: "100%", children: [/* @__PURE__ */ jsx(Button, { ...buttonStyles, borderLeftColor: "transparent!important", minW: "240px", isActive: isOpen && isExactlyActive, className: cs("focusAsBorder"), children: /* @__PURE__ */ jsx(SidemenuItemContent, { title, isInPopover: true }) }), children] }) })] }) }); /** A menu item. */ const SidemenuItemV2 = vui((props, ref) => { const { children, className, disabled = false, icon, isActive = false, isExpanded = true, itemId, level = 0, onBottom = false, onClick, onCollapse, onExpand, title, ...rest } = omitThemingProps(props); const computedItemId = itemId || generateMenuItemId(title, level) || `item-${Math.random().toString(36).substr(2, 9)}`; const { isDark, isMenuExpanded, styles, size, isSubmenuOpen, toggleSubmenu } = useSidemenuItem(computedItemId); const isExactlyActive = isActive; useEffect(() => { if (isMenuExpanded) { if (isSubmenuOpen) onExpand?.(); if (!isSubmenuOpen) onCollapse?.(); } }, [ isSubmenuOpen, onExpand, onCollapse, isMenuExpanded ]); const computedStates = useMemo(() => { const hasChildren = !!children; return { hasChildren, hasChildrenCollapsed: hasChildren && !isSubmenuOpen, hasChildrenExpanded: hasChildren && isSubmenuOpen && isMenuExpanded, shouldShowExpandButton: hasChildren && isMenuExpanded, buttonSize: level < 1 ? "lg" : "md", iconSize: level < 1 ? "sm" : "xs", isDisabled: disabled, shouldShowBorder: !hasChildren || isSubmenuOpen }; }, [ children, isSubmenuOpen, isMenuExpanded, disabled, size, level ]); const themeValues = useMemo(() => ({ activeColor: isDark ? "digiGreen.main" : "seaBlue.main" }), [isDark]); const handleClick = useCallback((event) => { if (!computedStates.isDisabled) { const targetTag = event.target; if ((targetTag.classList.contains("vui-tagText") || targetTag.classList.contains("vui-tag")) && typeof window !== "undefined" && (targetTag.parentElement?.dataset.link || targetTag?.dataset.link)) { const url = atob(targetTag.parentElement?.dataset.link ?? targetTag?.dataset.link ?? ""); window.open(url, "_blank", "noopener,noreferrer"); } else { event?.stopPropagation?.(); onClick?.(); } } toggleSubmenu?.(); }, [onClick, computedStates.isDisabled]); const buttonStyles = useMemo(() => ({ ...styles && "item" in styles && styles.item ? styles.item : {}, ...styles && "button" in styles && styles.button ? styles.button : {}, borderLeftColor: isExactlyActive ? themeValues.activeColor : "transparent", transitionProperty: "background-color, border-color, color, transform, opacity", size: computedStates.buttonSize, h: computedStates.buttonSize === "lg" ? 40 : 36, iconSize: computedStates.iconSize, variant: "tertiaryBrand", onClick: handleClick, disabled: computedStates.isDisabled, role: "button", tabIndex: computedStates.isDisabled ? -1 : 0, "aria-disabled": computedStates.isDisabled, "aria-pressed": isExactlyActive, ...rest }), [ styles, computedStates, isExactlyActive, themeValues, handleClick, rest ]); const expandButtonProps = useMemo(() => { const isExpanded = isSubmenuOpen; return { "aria-label": isExpanded ? "Collapse" : "Expand", className: "vui-sidemenu-item-expand", variant: "tertiaryBrand", icon: isExpanded ? "falChevronUp" : "falChevronDown", size: "sm", pl: "4px", pr: "16px", ml: "auto", h: "100%", border: "none", bg: "transparent", hoverBg: "transparent", activeBg: "transparent" }; }, [isSubmenuOpen]); const renderPopover = () => /* @__PURE__ */ jsx(SidemenuPopover, { isDark, className, buttonStyles, isExactlyActive, icon, title, isMenuExpanded, children: children ? children : void 0 }); const renderButton = () => { if (level === 0 && !isMenuExpanded) return /* @__PURE__ */ jsx(Tooltip, { text: title, placement: "right", offset: [0, -200], children: /* @__PURE__ */ jsxs(Button, { className: cs("vui-sidemenu-item focusAsBorder", isExactlyActive && "vui-sidemenu-item--active", className), ...buttonStyles, isActive: isExactlyActive, children: [ /* @__PURE__ */ jsx(SidemenuItemContent, { icon, iconSize: buttonStyles.iconSize }), isMenuExpanded && computedStates.shouldShowExpandButton && /* @__PURE__ */ jsx(Button, { ...expandButtonProps }), " " ] }) }); return /* @__PURE__ */ jsxs(Button, { className: cs("vui-sidemenu-item focusAsBorder", isExactlyActive && "vui-sidemenu-item--active", className), ...buttonStyles, isActive: isExactlyActive, title: !isMenuExpanded ? title : void 0, children: [ /* @__PURE__ */ jsx(SidemenuItemContent, { icon, iconSize: buttonStyles.iconSize, title, isMenuExpanded, badge: props.badge, badgeLinkUrl: props.badgeLinkUrl }), isMenuExpanded && computedStates.shouldShowExpandButton && /* @__PURE__ */ jsx(Button, { ...expandButtonProps }), " " ] }); }; const renderChildren = () => /* @__PURE__ */ jsx(Box, { flexDirection: "column", justifyContent: "start", w: "100%", children }); const shouldShowPopover = Boolean(!isMenuExpanded && level === 0 && !!children); const shouldShowChildren = computedStates.hasChildrenExpanded; return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", ref, w: "100%", mt: onBottom ? "auto" : 0, id: computedItemId, children: [ shouldShowPopover && renderPopover(), !shouldShowPopover && renderButton(), shouldShowChildren && renderChildren() ] }); }); SidemenuItemV2.displayName = "SidemenuItemV2"; //#endregion export { PopoverHovered, SidemenuItemV2, SidemenuItemV2 as default }; globalThis.__vuiVersion__ = "5.3.1" //# sourceMappingURL=sidemenuItemV2.js.map