import React, { ChangeEvent, ReactNode, useCallback, useEffect, useMemo, 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 { Button, Classes, InputGroup } from "@blueprintjs/core"; import { WidgetContainerDiff } from "widgets/WidgetUtils"; import Icon from "components/ads/Icon"; import { Colors } from "constants/Colors"; export interface TreeSelectProps extends Required< Pick< SelectProps, | "disabled" | "placeholder" | "loading" | "dropdownStyle" | "allowClear" | "options" > > { value?: DefaultValueType; onChange: (value?: DefaultValueType, labelList?: ReactNode[]) => void; expandAll: boolean; mode: CheckedStrategy; labelText?: string; labelTextColor?: string; labelTextSize?: TextSize; labelStyle?: string; compactMode: boolean; dropDownWidth: number; width: number; isValid: boolean; filterText?: string; widgetId: string; isFilterable: boolean; } const getSvg = (expanded: boolean) => ( ); const switcherIcon = (treeNode: TreeNodeProps) => { if (treeNode.isLeaf) { return ( ); } return getSvg(treeNode.expanded); }; const FOCUS_TIMEOUT = 500; function MultiTreeSelectComponent({ allowClear, compactMode, disabled, dropdownStyle, dropDownWidth, expandAll, filterText, isFilterable, isValid, labelStyle, labelText, labelTextColor, labelTextSize, loading, mode, onChange, options, placeholder, value, widgetId, width, }: TreeSelectProps): JSX.Element { const [key, setKey] = useState(Math.random()); const [filter, setFilter] = useState(filterText ?? ""); const _menu = useRef(null); const labelRef = useRef(null); const inputRef = 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 clearButton = useMemo( () => filter ? (