import React, { ComponentType, createContext, FC, useContext, ReactNode, } from 'react'; import classnames from 'classnames'; import { Button } from './Button'; import { Spinner } from './Spinner'; import { useControlledValue, useEventCallback } from './hooks'; import { TreeContext } from './Tree'; /** * */ const TreeNodeLevelContext = createContext(1); /** * */ export type TreeNodeProps = { className?: string; label?: string | JSX.Element; defaultOpened?: boolean; opened?: boolean; selected?: boolean; leaf?: boolean; loading?: boolean; level?: number; disabled?: boolean; children?: ReactNode; onClick?: (e: React.MouseEvent) => void; onLabelClick?: (e: React.MouseEvent) => void; onToggle?: (e: React.MouseEvent) => void; itemRender?: ComponentType; }; /** * */ const TreeNodeItem: FC = (props) => { const { className, label, icon = 'chevronright', loading, selected, leaf, opened, level = 0, children, itemRender: ItemRender, onClick, onToggle, onLabelClick, ...rprops } = props; const itmClassNames = classnames(className, 'slds-tree__item', { 'slds-is-open': opened, 'slds-is-selected': selected, }); const spinnerClassNames = classnames( 'react-slds-spinner', 'slds-m-right_x-small' ); const loadingPositionStyle = { left: `${level}rem`, }; return (
{loading && ( )} {!leaf ? (
); }; /** * */ export const TreeNode: FC = (props) => { const { defaultOpened, opened: opened_, leaf, selected, disabled, children, onClick: onClick_, onToggle: onToggle_, onLabelClick: onLabelClick_, ...rprops } = props; const { toggleOnNodeClick, onNodeClick, onNodeLabelClick, onNodeToggle } = useContext(TreeContext); const level = useContext(TreeNodeLevelContext); const [opened, setOpened] = useControlledValue( opened_, defaultOpened ?? false ); const onToggle = useEventCallback((e: React.MouseEvent) => { onToggle_?.(e); onNodeToggle?.(e, props); setOpened((opened) => !opened); }); const onLabelClick = useEventCallback((e: React.MouseEvent) => { onLabelClick_?.(e); onNodeLabelClick?.(e, props); }); const onClick = useEventCallback((e: React.MouseEvent) => { onClick_?.(e); onNodeClick?.(e, props); if (toggleOnNodeClick) { onToggle(e); } }); const grpClassNames = classnames('slds-tree__group', { 'slds-nested': !leaf, 'is-expanded': opened, 'slds-show': opened, 'slds-hide': !opened, }); const labelText = typeof rprops.label === 'string' ? rprops.label : 'Tree Branch'; const ariaLabel = !leaf ? labelText : undefined; return (
  • {!leaf ? (
      {children}
    ) : undefined}
  • ); };