import React, { ReactNode, useCallback, useEffect, useRef, useState, } from "react"; import TreeSelect, { TreeSelectProps as SelectProps } from "rc-tree-select"; import { TreeSelectContainer, DropdownStyles, StyledIcon, StyledLabel, TextLabelWrapper, } from "./index.styled"; import "rc-tree-select/assets/index.less"; import { DefaultValueType } from "rc-tree-select/lib/interface"; import { TreeNodeProps } from "rc-tree-select/lib/TreeNode"; import { CheckedStrategy } from "rc-tree-select/lib/utils/strategyUtil"; import { CANVAS_CLASSNAME, MODAL_PORTAL_CLASSNAME, TextSize, } from "constants/WidgetConstants"; import { Classes } from "@blueprintjs/core"; import Icon from "components/ads/Icon"; import { Colors } from "constants/Colors"; export interface TreeSelectProps extends Required< Pick< SelectProps, | "disabled" | "options" | "placeholder" | "loading" | "dropdownStyle" | "allowClear" > > { value?: DefaultValueType; onChange: (value?: DefaultValueType, labelList?: ReactNode[]) => void; expandAll: boolean; mode: CheckedStrategy; labelText?: string; labelTextColor?: string; labelTextSize?: TextSize; labelStyle?: string; compactMode: boolean; isValid: boolean; } const getSvg = (expanded: boolean) => ( ); const switcherIcon = (treeNode: TreeNodeProps) => { if (treeNode.isLeaf) { return ( ); } return getSvg(treeNode.expanded); }; function MultiTreeSelectComponent({ allowClear, compactMode, disabled, dropdownStyle, expandAll, isValid, labelStyle, labelText, labelTextColor, labelTextSize, loading, mode, onChange, options, placeholder, value, }: TreeSelectProps): JSX.Element { const [key, setKey] = useState(Math.random()); const _menu = useRef(null); // treeDefaultExpandAll is uncontrolled after first render, // using this to force render to respond to changes in expandAll useEffect(() => { setKey(Math.random()); }, [expandAll]); const getDropdownPosition = useCallback(() => { const node = _menu.current; if (Boolean(node?.closest(`.${MODAL_PORTAL_CLASSNAME}`))) { return document.querySelector( `.${MODAL_PORTAL_CLASSNAME}`, ) as HTMLElement; } return document.querySelector(`.${CANVAS_CLASSNAME}`) as HTMLElement; }, []); const onClear = useCallback(() => onChange([], []), []); return ( } > {labelText && ( {labelText} )} } disabled={disabled} dropdownClassName="tree-multiselect-dropdown" dropdownStyle={dropdownStyle} getPopupContainer={getDropdownPosition} inputIcon={ } key={key} loading={loading} maxTagCount={"responsive"} maxTagPlaceholder={(e) => `+${e.length} more`} multiple notFoundContent="No Results Found" onChange={onChange} onClear={onClear} placeholder={placeholder} removeIcon={ } showArrow showCheckedStrategy={mode} showSearch style={{ width: "100%" }} switcherIcon={switcherIcon} transitionName="rc-tree-select-dropdown-slide-up" treeCheckable={ } treeData={options} treeDefaultExpandAll={expandAll} treeIcon treeNodeFilterProp="label" value={value} /> ); } export default MultiTreeSelectComponent;