packageDocumentation module import "./Node.scss" ; import classnames from "classnames" ; import * as React from "react" ; import { Checkbox , CheckboxProps , ProgressRadial } from "@itwin/itwinui-react" ; import { CheckBoxState } from "../enums/CheckBoxState" ; import { CommonProps } from "../utils/Props" ; import { Omit } from "../utils/typeUtils" ; import { ExpansionToggle } from "./ExpansionToggle" ; public export type NodeCheckboxRenderProps = Omit < CheckboxProps , "onChange" | "onClick" > & { onChange : ( checked : boolean ) => void ; onClick : ( e : React . MouseEvent ) => void ; } ; public export type NodeCheckboxRenderer = ( props : NodeCheckboxRenderProps ) => React . ReactNode ; internal export const LEVEL_OFFSET = 20 ; const EXPANSION_TOGGLE_WIDTH = 24 ; public export interface NodeCheckboxProps { /** State of the checkbox */ state ? : CheckBoxState ; /** Click event callback */ onClick ? : ( newState : CheckBoxState ) => void ; /** Indicates whether checkbox is disabled */ isDisabled ? : boolean ; /** Tooltip to be displayed when mouse is hovered over checkbox */ tooltip ? : string ; } public export interface TreeNodeProps extends CommonProps { label : React . ReactNode ; level : number ; icon ? : React . ReactChild ; public checkboxProps ? : NodeCheckboxProps ; isLeaf ? : boolean ; isLoading ? : boolean ; isExpanded ? : boolean ; isFocused ? : boolean ; isSelected ? : boolean ; isHoverDisabled ? : boolean ; onClick ? : ( e : React . MouseEvent ) => void ; onContextMenu ? : ( e : React . MouseEvent ) => void ; onMouseMove ? : ( e : React . MouseEvent ) => void ; onMouseDown ? : ( e : React . MouseEvent ) => void ; onMouseUp ? : ( e : React . MouseEvent ) => void ; onClickExpansionToggle ? : ( ) => void ; children ? : React . ReactNode ; /** Contains render overrides for different pieces of the node component. */ renderOverrides ? : { /** Callback to render a checkbox. Only called when checkbox is displayed. */ renderCheckbox ? : NodeCheckboxRenderer ; } ; [ "data-testid" ] ? : string ; } public export class TreeNode extends React . Component < TreeNodeProps > { constructor ( props ) { super ( props ) ; } public override render ( ) { const className = classnames ( "core-tree-node" , this . props . isFocused && "is-focused" , this . props . isSelected && "is-selected" , this . props . isHoverDisabled && "is-hover-disabled" , this . props . className ) ; let offset = this . props . level * LEVEL_OFFSET ; if ( ! this . props . isLoading && this . props . isLeaf ) offset += EXPANSION_TOGGLE_WIDTH ; let checkbox ; if ( this . props . checkboxProps ) { const props = { label : "" , checked : this . props . checkboxProps . state === CheckBoxState . On , indeterminate : this . props . checkboxProps . state === CheckBoxState . Partial , disabled : this . props . checkboxProps . isDisabled , title : this . props . checkboxProps . tooltip , onClick : this . _onCheckboxClick , onChange : this . _onCheckboxChange } ; if ( this . props . renderOverrides && this . props . renderOverrides . renderCheckbox ) { checkbox = this . props . renderOverrides . renderCheckbox ( props ) ; } else { checkbox = ( < Checkbox { ... props } onChange = { ( e ) => this . _onCheckboxChange ( e . target . checked ) } data - testid = { this . createSubComponentTestId ( "checkbox" ) } />); } } const icon = this . props . icon ? ( < div className = "core-tree-node-icon" > { this . props . icon } < /div>) : undefined; const toggle = ( this . props . isLoading || this . props . isLeaf ) ? undefined : ( < ExpansionToggle className = "expansion-toggle" data - testid = { this . createSubComponentTestId ( "expansion-toggle" ) } onClick = { this . _onClickExpansionToggle } isExpanded = { this . props . isExpanded } / > ) ; return ( < div className = { className } style = { this . props . style } data - testid = { this . props [ "data-testid" ] } onClick = { this . _onClick } onContextMenu = { this . props . onContextMenu } onMouseDown = { this . props . onMouseDown } onMouseUp = { this . props . onMouseUp } onMouseMove = { this . props . onMouseMove } role = "treeitem" tabIndex = { - 1 } > < div className = "contents" style = { { marginLeft : offset } } data - testid = { this . createSubComponentTestId ( "contents" ) } > { this . props . isLoading && < ProgressRadial size = "x-small" indeterminate / > } { toggle } { checkbox } { icon } { this . props . label } < /div> { this . props . children } < /div>); } private createSubComponentTestId ( subId ) { if ( ! this . props [ "data-testid" ] ) return undefined ; return `${ this . props [ "data-testid" ] }-${ subId }` ; } private _onCheckboxChange = ( checked ) => { if ( this . props . checkboxProps && this . props . checkboxProps . onClick && ! this . props . checkboxProps . isDisabled ) this . props . checkboxProps . onClick ( checked ? CheckBoxState . On : CheckBoxState . Off ) ; } ; private _onCheckboxClick = ( e ) => { e . stopPropagation ( ) ; } ; private _onClickExpansionToggle = ( e ) => { e . stopPropagation ( ) ; if ( this . props . onClickExpansionToggle ) this . props . onClickExpansionToggle ( ) ; } ; private _onClick = ( e ) => { e . stopPropagation ( ) ; if ( this . props . onClick ) this . props . onClick ( e ) ; } ; }