UNPKG

@hitachivantara/uikit-react-core

Version:

Core React components for the NEXT Design System.

421 lines (420 loc) 13.7 kB
"use strict"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); const jsxRuntime = require("react/jsx-runtime"); const React = require("react"); const uikitReactUtils = require("@hitachivantara/uikit-react-utils"); const useForkRef = require("../../hooks/useForkRef.cjs"); const icons = require("../../icons.cjs"); const DescendantProvider = require("../../TreeView/internals/DescendantProvider.cjs"); const setId = require("../../utils/setId.cjs"); const VerticalNavigationContext = require("../VerticalNavigationContext.cjs"); const TreeViewContext = require("./TreeViewContext.cjs"); const TreeViewItem_styles = require("./TreeViewItem.styles.cjs"); const Tooltip = require("../../Tooltip/Tooltip.cjs"); const Typography = require("../../Typography/Typography.cjs"); const Avatar = require("../../Avatar/Avatar.cjs"); const OverflowTooltip = require("../../OverflowTooltip/OverflowTooltip.cjs"); const preventSelection = (event, disabled) => { if (event.shiftKey || event.ctrlKey || event.metaKey || disabled) { event.preventDefault(); } }; const HvVerticalNavigationTreeViewItem = React.forwardRef( function HvVerticalNavigationTreeViewItem2(props, ref) { const { id: idProp, className, classes: classesProp, disabled: disabledProp = false, selectable: selectableProp, nodeId, icon = null, label, href, target, payload, onClick, onMouseDown, onFocus, children, disableTooltip, ...others } = uikitReactUtils.useDefaultProps("HvVerticalNavigationTreeViewItem", props); const { classes, cx } = TreeViewItem_styles.useClasses(classesProp); const treeViewControlContext = React.useContext(TreeViewContext.TreeViewControlContext); const { isExpanded, isSelected, isFocused, isDisabled, isChildSelected } = React.useContext(TreeViewContext.TreeViewStateContext); const { treeId, mode, collapsible, toggleExpansion, multiSelect, selectNode, selectRange, disabledItemsFocusable, registerNode, unregisterNode, mapFirstChar, unMapFirstChar, focus } = treeViewControlContext; const treeviewMode = mode === "treeview"; let id = null; if (idProp != null) { id = idProp; } else if (treeId && nodeId) { id = `${treeId}-${nodeId}`; } const [treeitemElement, setTreeitemElement] = React.useState(); const contentRef = React.useRef(null); const handleRef = useForkRef.useForkRef(setTreeitemElement, ref); const descendant = React.useMemo( () => ({ element: treeitemElement, id: nodeId }), [nodeId, treeitemElement] ); const { isOpen, useIcons, hasAnyChildWithData } = React.useContext( VerticalNavigationContext.VerticalNavigationContext ); const { index, parentId, level } = DescendantProvider.useDescendant(descendant); const expandable = collapsible && Array.isArray(children); const expanded = isExpanded ? isExpanded(nodeId) : false; const focused = isFocused ? isFocused(nodeId) : false; const selected = isSelected ? isSelected(nodeId) : false; const disabled = isDisabled ? isDisabled(nodeId) : false; const selectable = selectableProp != null ? selectableProp : !collapsible || !expandable || !isOpen; React.useEffect(() => { if (registerNode && unregisterNode && index !== -1) { registerNode({ id: nodeId, idAttribute: id, index, parentId, selectable, expandable, disabled: disabledProp, onFocus, payload }); return () => { unregisterNode(nodeId); }; } return void 0; }, [ registerNode, unregisterNode, parentId, index, nodeId, expandable, disabledProp, id, selectable, onFocus, payload ]); React.useEffect(() => { if (mapFirstChar && unMapFirstChar && label && contentRef.current?.textContent) { mapFirstChar( nodeId, contentRef.current?.textContent.substring(0, 1).toLowerCase() ); return () => { unMapFirstChar(nodeId); }; } return void 0; }, [mapFirstChar, unMapFirstChar, nodeId, label]); let ariaSelected; if (multiSelect) { ariaSelected = selected; } else if (selected) { ariaSelected = true; } const handleFocus = React.useCallback( (event) => { if (event.target === event.currentTarget) { (event.target.ownerDocument || document).getElementById(treeId).focus({ preventScroll: true }); } const unfocusable = !disabledItemsFocusable && disabled; if (!focused && event.currentTarget === event.target && !unfocusable && focus) { focus(event, nodeId); } }, [disabled, disabledItemsFocusable, focus, focused, nodeId, treeId] ); const handleExpansion = React.useCallback( (event) => { if (!disabled) { if (treeviewMode && !focused && focus) { focus(event, nodeId); } const multiple = multiSelect && (event.shiftKey || event.ctrlKey || event.metaKey); if (expandable && isOpen && !(multiple && isExpanded && isExpanded(nodeId))) { if (toggleExpansion) toggleExpansion(event, nodeId); } } }, [ disabled, expandable, focus, focused, isExpanded, multiSelect, nodeId, toggleExpansion, treeviewMode, isOpen ] ); const handleSelection = React.useCallback( (event) => { if (selectable && !disabled) { if (treeviewMode && !focused && focus) { focus(event, nodeId); } const multiple = multiSelect && (event.shiftKey || event.ctrlKey || event.metaKey); if (multiple) { if (event.shiftKey) { if (selectRange) return selectRange(event, { end: nodeId }); } else if (selectNode) return selectNode(event, nodeId, true); } else if (selectNode) return selectNode(event, nodeId); } else { return false; } }, [ disabled, focus, focused, multiSelect, nodeId, selectNode, selectRange, selectable, treeviewMode ] ); const handleMouseDown = React.useCallback( (event) => { preventSelection(event, disabled); if (onMouseDown) { onMouseDown(event); } }, [disabled, onMouseDown] ); const handleClick = React.useCallback( (event) => { if (!disabled) { if (expandable && isOpen) { handleExpansion(event); } if (selectable) { handleSelection(event); } } if (onClick) { onClick(event); } }, [ disabled, expandable, handleExpansion, handleSelection, onClick, selectable, isOpen ] ); const handleKeyDown = React.useCallback( (event) => { let isEventHandled = false; const { key } = event; if (event.altKey || event.ctrlKey || event.metaKey || event.currentTarget !== event.target) { return; } if (contentRef.current === event.currentTarget) { if (key === "Enter" || key === " ") { if (expandable && isOpen) { isEventHandled = handleExpansion(event); } if (selectable) { isEventHandled = handleSelection(event); } } if (isEventHandled) { event.preventDefault(); event.stopPropagation(); } } }, [expandable, handleExpansion, handleSelection, selectable, isOpen] ); const renderedContent = React.useMemo(() => { const buttonLinkProps = { href, target }; const hasChildren = !!children; const showTooltip = !hasChildren && !isOpen && !disableTooltip; const isLink = href !== void 0 && !disabled; return /* @__PURE__ */ jsxRuntime.jsx(Tooltip.HvTooltip, { placement: "right", title: showTooltip && label, children: /* @__PURE__ */ jsxRuntime.jsxs( Typography.HvTypography, { id: setId.setId(id, "button"), component: isLink ? "a" : "div", ...isLink ? buttonLinkProps : null, ref: contentRef, classes: { root: cx(classes.content, { [classes.link]: isLink, [classes.minimized]: !isOpen }) }, variant: "body", disabled, onClick: handleClick, onMouseDown: handleMouseDown, style: { paddingLeft: (useIcons || !isOpen ? 0 : 10) + level * (collapsible ? 16 : 10) }, role: isLink ? void 0 : "button", ...treeviewMode ? { tabIndex: -1, onFocus: handleFocus } : { tabIndex: selectable || expandable ? 0 : -1, onKeyDown: handleKeyDown, "aria-current": selectable && selected || !isOpen && isChildSelected?.(nodeId) ? href ? "page" : true : void 0, "aria-expanded": expandable ? expanded : void 0, "aria-controls": isOpen && expandable ? setId.setId(id, "group") : void 0, "aria-label": payload?.label }, children: [ /* @__PURE__ */ jsxRuntime.jsxs( "div", { className: classes.icon, style: uikitReactUtils.mergeStyles(void 0, { "--icon-margin-left": hasAnyChildWithData ? "auto" : "unset" }), children: [ !icon && useIcons ? /* @__PURE__ */ jsxRuntime.jsx( Avatar.HvAvatar, { variant: "square", size: "xs", backgroundColor: "textSubtle", children: payload?.label?.substring(0, 1) } ) : useIcons && icon, hasChildren && !isOpen ? /* @__PURE__ */ jsxRuntime.jsx(icons.HvIcon, { name: "Forwards", size: "xs", compact: true }) : hasAnyChildWithData && !isOpen && /* @__PURE__ */ jsxRuntime.jsx("div", {}) ] } ), isOpen && /* @__PURE__ */ jsxRuntime.jsx( "div", { className: cx(classes.label, { [classes.labelIcon]: useIcons, [classes.labelExpandable]: !!expandable }), children: /* @__PURE__ */ jsxRuntime.jsx(OverflowTooltip.HvOverflowTooltip, { data: label }) } ), isOpen && expandable && /* @__PURE__ */ jsxRuntime.jsx(icons.HvIcon, { name: "CaretDown", size: "xs", rotate: expanded }) ] } ) }); }, [ href, target, children, isOpen, disableTooltip, disabled, label, id, cx, classes.content, classes.link, classes.minimized, classes.icon, classes.label, classes.labelIcon, classes.labelExpandable, handleClick, handleMouseDown, useIcons, level, collapsible, treeviewMode, handleFocus, selectable, expandable, handleKeyDown, selected, isChildSelected, nodeId, expanded, payload?.label, icon, hasAnyChildWithData ]); const renderedChildren = React.useMemo( () => children && /* @__PURE__ */ jsxRuntime.jsx( "ul", { id: setId.setId(id, "group"), className: classes.group, role: treeviewMode ? "group" : void 0, children } ), [children, classes?.group, id, treeviewMode] ); return /* @__PURE__ */ jsxRuntime.jsxs( "li", { ref: handleRef, id: id ?? void 0, className: cx( classes.node, { [classes.disabled]: disabled, [classes.expandable]: expandable, [classes.collapsed]: expandable && !expanded, [classes.expanded]: expandable && expanded, [classes.selectable]: selectable && !disabled, [classes.unselectable]: !disabled && !selectable, [classes.selected]: !disabled && selectable && selected || !isOpen && useIcons && isChildSelected && isChildSelected(nodeId), [classes.unselected]: !disabled && selectable && !selected, [classes.focused]: focused, [classes.hide]: !isOpen && !useIcons }, className ), "data-hasicon": icon != null ? true : void 0, ...mode === "treeview" && { role: "treeitem", "aria-selected": ariaSelected, "aria-expanded": expandable ? expanded : void 0, "aria-disabled": disabled ? true : void 0 }, ...others, children: [ renderedContent, isOpen && /* @__PURE__ */ jsxRuntime.jsx(DescendantProvider.DescendantProvider, { id: nodeId, level: level + 1, children: renderedChildren }) ] } ); } ); exports.treeViewItemClasses = TreeViewItem_styles.staticClasses; exports.HvVerticalNavigationTreeViewItem = HvVerticalNavigationTreeViewItem;