import React, { useState, useMemo, useRef, useCallback, useEffect } from 'react'; import ReactDOM from 'react-dom'; import { Icon, Input, Button, Form, Popover, Tag, Typography, CheckboxGroup, TagInput, Switch } from '../../index'; import TreeSelect from '../index'; import { flattenDeep, without } from 'lodash'; import CustomTrigger from './CustomTrigger'; import { IconCreditCard, IconChevronDown, IconClose, IconPlus, IconMinus } from '@douyinfe/semi-icons'; import copy from 'fast-copy'; const TreeNode = TreeSelect.TreeNode; const { Title } = Typography; export default { title: 'TreeSelect', parameters: { chromatic: { disableSnapshot: true }, }, } const treeData1 = [ { label: 'Node1', value: '0-0', key: '0-0', children: [ { label: 'Child Node1', value: '0-0-1', key: '0-0-1', }, { label: 'Child Node2', value: '0-0-2', key: '0-0-2', }, ], }, { label: 'Node2', value: '0-1', key: '0-1', }, ]; const treeData2 = [ { label: '亚洲', value: 'yazhou', key: 'yazhou', children: [ { label: '中国', value: 'zhongguo', key: 'zhongguo', children: [ { label: '北京', value: 'beijing', key: 'beijing', }, { label: '上海', value: 'shanghai', key: 'shanghai', }, ], }, // { // label: '日本', // value: 'riben', // key: 'riben', // children: [ // { // label: '东京', // value: 'dongjing', // key: 'dongjing' // }, // { // label: '大阪', // value: 'daban', // key: 'daban' // } // ] // }, ], }, { label: '北美洲', value: 'beimeizhou', key: 'beimeizhou', children: [ { label: '美国', value: 'meiguo', key: 'meiguo', }, { label: '加拿大', value: 'jianada', key: 'jianada', }, ], }, ]; const treeData3 = [ { label: 'Node1', value: '0-0', key: '0-0', children: [ { label: 'Child Node1', value: '0-0-1', key: '0-0-1', }, { label: 'Child Node2', value: '0-0-2', key: '0-0-2', }, { label: 'Child Node3', value: '0-0-3', key: '0-0-3', }, { label: 'Child Node4', value: '0-0-4', key: '0-0-4', }, { label: 'Child Node5', value: '0-0-5', key: '0-0-5', }, { label: 'Child Node6', value: '0-0-6', key: '0-0-6', }, { label: 'Child Node7', value: '0-0-7', key: '0-0-7', }, { label: 'Child Node8', value: '0-0-8', key: '0-0-8', }, { label: 'Child Node9', value: '0-0-9', key: '0-0-9', }, { label: 'Child Node10', value: '0-0-10', key: '0-0-10', }, ], }, { label: 'Node2', value: '0-1', key: '0-1', }, ]; const treeDataWithoutValue = [ { label: '亚洲', key: 'yazhou', children: [ { label: '中国', key: 'zhongguo', disabled: true, children: [ { label: '北京', key: 'beijing', }, { label: '上海', key: 'shanghai', }, ], }, { label: '日本', key: 'riben', children: [ { label: '东京', key: 'dongjing', }, { label: '大阪', key: 'daban', }, ], }, ], }, { label: '北美洲', key: 'beimeizhou', children: [ { label: '美国', key: 'meiguo', }, { label: '加拿大', key: 'jianada', }, ], }, ]; const specialTreeData = [ { label1: '亚洲', // value1: 'Yazhou', key1: 'yazhou', children1: [ { label1: '中国', // value1: 'Zhongguo', key1: 'zhongguo', disabled1: true, children1: [ { label1: '北京', // value1: 'Beijing', key1: 'beijing', }, { label1: '上海', // value1: 'Shanghai', key1: 'shanghai', }, ], }, { label1: '日本', // value1: 'Riben', key1: 'riben', children1: [ { label1: '东京', // value1: 'Dongjing', key1: 'dongjing', }, { label1: '大阪', // value1: 'Daban', key1: 'daban', }, ], }, ], }, { label1: '北美洲', // value1: 'Beimeizhou', key1: 'beimeizhou', children1: [ { label1: '美国', // value1: 'Meiguo', key1: 'meiguo', }, { label1: '加拿大', // value1: 'Jianada', key1: 'jianada', }, ], }, ]; const treeDataEn = [ { label: 'Asia', value: 'Asia', key: '0', children: [ { label: 'China', value: 'China', key: '0-0', children: [ { label: 'Beijing', value: 'Beijing', key: '0-0-0', }, { label: 'Shanghai', value: 'Shanghai', key: '0-0-1', }, { label: 'Chengdu', value: 'Chengdu', key: '0-0-2', }, ], }, { label: 'Japan', value: 'Japan', key: '0-1', children: [ { label: 'Osaka', value: 'Osaka', key: '0-1-0' } ] }, ], }, { label: 'North America', value: 'North America', key: '1', children: [ { label: 'United States', value: 'United States', key: '1-0' }, { label: 'Canada', value: 'Canada', key: '1-1' } ] } ]; export const TreeSelectWrapper = () => (
github issue 750 修改测试用例
); TreeSelectWrapper.story = { name: 'treeSelect wrapper', }; class SimpleTree extends React.Component { render() { return (
console.log('expand', e, expanded, node)} onSelect={(e, bool) => console.log('select', e, bool)} onChange={(e, node) => console.log('change', e, node)} />

); } } export const _TreeSelect = () => { const treeData = [ { label: '亚洲', value: 'Asia', key: '0', children: [ { label: '中国', value: 'China', key: '0-0', children: [ { label: '北京', value: 'Beijing', key: '0-0-0', }, { label: '上海', value: 'Shanghai', key: '0-0-1', }, ], }, ], }, { label: '北美洲', value: 'North America', key: '1', }, ]; return ( ); }; _TreeSelect.story = { name: 'tree select', }; export const Searchable = () => (




); Searchable.story = { name: 'searchable', }; export const SearchPosition = () => (






); SearchPosition.story = { name: 'searchPosition', }; export const PrefixSuffixInsetLabel = () => (
} treeNodeFilterProp="value" placeholder="Please select" />







1234} dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} treeData={treeData2} placeholder="Please select" />
); PrefixSuffixInsetLabel.story = { name: 'prefix suffix insetLabel', }; PrefixSuffixInsetLabel.parameters = { chromatic: { disableSnapshot: false }, } export const ValidateStatus = () => (
console.log('expand', e, expanded, node)} onSelect={(e, bool) => console.log('select', e, bool)} onChange={e => console.log('change', e)} />

); ValidateStatus.story = { name: 'validate status', }; ValidateStatus.parameters = { chromatic: { disableSnapshot: false }, } export const Multiple = () => (
console.log('expand', e, expanded, node)} onSelect={(e, bool) => console.log('select', e, bool)} onChange={e => console.log('change', e)} />

); Multiple.story = { name: 'multiple', }; export const MaxTagCount = () => (
{/*

*/}
); MaxTagCount.story = { name: 'maxTagCount', }; export const MultipleSearchable = () => (
); MultipleSearchable.story = { name: 'multiple searchable', }; export const DefaultValues = () => (






); DefaultValues.story = { name: 'default values', }; export const Disabled = () => (




); Disabled.story = { name: 'disabled', }; Disabled.parameters = { chromatic: { disableSnapshot: false }, } export const OptionLabelProp = () => ( <> ); OptionLabelProp.story = { name: 'optionLabelProp', }; export const ValueInArray = () => ( <> console.log(args)} treeNodeFilterProp="value" treeNodeLabelProp="value" placeholder="Please select" /> ); ValueInArray.story = { name: 'valueInArray', }; export const OnBlurOnFocus = () => ( <>
single
console.log('blur', args)} onFocus={(...args) => console.log('focus', args)} placeholder="Please select" />
multiple
console.log('blur', args)} onFocus={(...args) => console.log('focus', args)} placeholder="Please select" />
single, filterTreeNode, searchPosition=dropdown
console.log('blur', args)} onFocus={(...args) => console.log('focus', args)} placeholder="Please select" />
multiple, filterTreeNode, searchPosition=dropdown
console.log('blur', args)} onFocus={(...args) => console.log('focus', args)} placeholder="Please select" />
single, filterTreeNode, searchPosition=trigger
console.log('blur', args)} onFocus={(...args) => console.log('focus', args)} placeholder="Please select" />
multiple, filterTreeNode, searchPosition=trigger
console.log('blur', args)} onFocus={(...args) => console.log('focus', args)} placeholder="Please select" /> ); OnBlurOnFocus.story = { name: 'onBlur/onFocus', }; export const LeafOnly = () => (
console.log('expand', e, expanded, node)} onSelect={(e, bool) => console.log('select', e, bool)} onChange={e => console.log('change', e)} />
); LeafOnly.story = { name: 'leafOnly', }; class Demo extends React.Component { constructor() { super(); this.state = { value: 'shanghai', }; } onChange(value) { this.setState({ value }); } render() { return ( this.onChange(e)} /> ); } } export const ControlledComponentSingle = () => ; ControlledComponentSingle.story = { name: 'controlled Component single', }; class Demo2 extends React.Component { constructor() { super(); this.state = { value: ['Shanghai'], }; } onChange(value) { this.setState({ value }); } render() { console.log(this.state.value); const treeData = [ { label: '亚洲', value: 'Asia', key: '0', children: [ { label: '中国', value: 'China', key: '0-0', children: [ { label: '北京', value: 'Beijing', key: '0-0-0', }, { label: '上海', value: 'Shanghai', key: '0-0-1', }, ], }, ], }, { label: '北美洲', value: 'North America', key: '1', }, ]; return ( this.onChange(e)} /> ); } } export const ControlledComponentMultiple = () => ; ControlledComponentMultiple.story = { name: 'controlled Component multiple', }; class Demo3 extends React.Component { constructor() { super(); this.state = { value: ['Shanghai'], }; } // 获取最底层值 getDeepChildrensByNode = node => { return flattenDeep( node.map(item => { if (item.children) { return this.getDeepChildrensByNode(item.children); } return item.value; }) ); }; onChange(value, node) { console.log('onchange', value); value = this.getDeepChildrensByNode(node); console.log('modifiled', value); this.setState({ value }); } render() { const treeData = [ { label: '亚洲', value: 'Asia', key: '0', children: [ { label: '中国', value: 'China', key: '0-0', children: [ { label: '北京', value: 'Beijing', key: '0-0-0', }, { label: '上海', value: 'Shanghai', key: '0-0-1', }, ], }, ], }, { label: '北美洲', value: 'North America', key: '1', }, ]; return ( this.onChange(e, node)} /> ); } } export const ControlledComponentMultipleValueModified = () => ; ControlledComponentMultipleValueModified.story = { name: 'controlled Component multiple value modified', }; class ConvertDemo extends React.Component { constructor(props) { super(props); this.formApi = null; } handleChange = val => { let finalVal = val; let firstClassOption = ['Asia', 'North America']; // 在这里去做你的value替换逻辑 console.log('originVal:' + val); if (val.length === 1) { // do nothing } else { if (val.every(item => firstClassOption.includes(item))) { finalVal = val[val.length - 1]; } } console.log('finalVal:' + finalVal); return finalVal; }; render() { const treeData = [ { label: '亚洲', value: 'Asia', key: '0', children: [ { label: '中国', value: 'China', key: '0-0', children: [ { label: '北京', value: 'Beijing', key: '0-0-0', }, { label: '上海', value: 'Shanghai', key: '0-0-1', }, ], }, ], }, { label: '北美洲', value: 'North America', key: '1', }, ]; return (
); } } export const _ConvertDemo = () => ; _ConvertDemo.story = { name: 'convert demo', }; export const TreeselectDefaultOpenInPopover = () => ( this.onChange(e, node)} /> } > ); TreeselectDefaultOpenInPopover.story = { name: 'treeselect defaultOpen in popover', }; export const CustomTriggerDemo = () => ; CustomTriggerDemo.story = { name: 'custom trigger' }; const AutoParentDemo = () => { const [expandedKeys, setExpandedKeys] = useState(['beimeizhou']); const [selectedKeys, setSelectedKeys] = useState(['beimeizhou']); const [autoExpandParent, setAutoExpandParent] = useState(true); const onExpand = expandedKeys => { console.log('onExpand', expandedKeys); // if not set autoExpandParent to false, if children expanded, parent can not collapse. // or, you can remove all expanded children keys. setExpandedKeys(expandedKeys); setAutoExpandParent(false); }; const onSelect = (selectedKeys, info) => { console.log('onSelect:', info); setSelectedKeys(selectedKeys); }; return (
); }; export const AutoExpandParent = () => ( <> ); AutoExpandParent.story = { name: 'autoExpandParent', }; export const TreeWithoutValueProps = () => ( console.log(args)} /> ); TreeWithoutValueProps.story = { name: 'tree without value props', }; export const TreeSelectRenderSelectedItem = () => { const treeData = [ { label: '亚洲', value: 'Asia', key: '0', children: [ { label: '中国', value: 'China', key: '0-0', children: [ { label: '北京', value: 'Beijing', key: '0-0-0', }, { label: '上海', value: 'Shanghai', key: '0-0-1', }, ], }, ], }, { label: '北美洲', value: 'North America', key: '1', }, { label: '南美洲', value: 'South America', key: '2', }, { label: '南极洲', value: 'Antarctica', key: '3', }, ]; return ( <>

单选

`${item.value}-${item.label}`} />

多选

({ content: `${item.value}-${item.label}`, isRenderInTag: true, })} />

多选 + isRenderInTag=false

({ content: ( {item.value} ), isRenderInTag: false, })} /> ); }; TreeSelectRenderSelectedItem.story = { name: 'treeSelect renderSelectedItem', }; const DisableStrictlyDemo = () => { const [value, setValue] = useState(['Shanghai']); const treeData = [ { label: '亚洲', value: 'Asia', key: '0', children: [ { label: '中国', value: 'China', key: '0-0', disabled: true, children: [ { label: '北京', value: 'Beijing', key: '0-0-0', }, { label: '上海', value: 'Shanghai', key: '0-0-1', }, ], }, { label: '日本', value: 'Japan', key: '0-1', }, ], }, { label: '北美洲', value: 'North America', key: '1', }, ]; return (
setValue(value)} />
); }; export const DisabledStrictly = () => ( <> ); DisabledStrictly.story = { name: 'disabledStrictly', }; export const CheckRelationDemo = () => { const treeData = treeDataEn; const [value, setValue] = useState('China'); const [value2, setValue2] = useState(); const [value3, setValue3] = useState(); const style = { width: 300, }; const dropdownStyle = { maxHeight: 400, overflow: 'auto' }; const handleChange = value => { console.log(value); setValue(value); }; const handleChange2 = value => { console.log(value); setValue2(value); }; const handleChange3 = value => { console.log(value); setValue3(value); }; return ( <>
checkRelation='unRelated'


checkRelation='unRelated' + maxTagCount=2


checkRelation='unRelated' + maxTagCount=2 + 开启搜索


checkRelation='unRelated' + maxTagCount=2 + 开启搜索 + searchBox in trigger


checkRelation='unRelated' + 中国节点为 disabled


checkRelation='unRelated' + 中国节点为 disabled + 严格禁用


checkRelation='unRelated' + defaultValue 为 China


checkRelation='unRelated' + defaultValue 为 China + 开启搜索


多选 + checkRelation='unRelated' + defaultValue 为 China + 开启搜索 + searchBox in trigger + showClear


单选 + checkRelation='unRelated' + defaultValue 为 China + 开启搜索 + searchBox in trigger + showClear


checkRelation='unRelated' + 受控 + value 初始为 China


checkRelation='unRelated' + 受控 + onChangeWithObject


checkRelation='unRelated' + 受控 + leafOnly,此时 leafOnly 失效


checkRelation='unRelated' + onSelect
console.log('select', value, status, node)} /> ); }; export const SearchableAndExpandedKeys = () => { const [expandedKeys1, setExpandedKeys1] = useState([]); const [expandedKeys2, setExpandedKeys2] = useState([]); const [expandedKeys3, setExpandedKeys3] = useState([]); return ( <> expandedKeys 受控 { console.log('onExpand value: ', v); setExpandedKeys1(v); }} /> expandedKeys 受控 + 开启搜索 { console.log('onExpand value: ', v); setExpandedKeys2(v); }} /> expandedKeys 受控 + 开启搜索 + 搜索时更新 expandedKeys { console.log('onExpand value: ', v); setExpandedKeys3(v) }} onSearch={(input, filterExpandedKeys) => { console.log('onExpand filterExpandedKeys: ', filterExpandedKeys); setExpandedKeys3(filterExpandedKeys); }} /> ) } export const loadData = () => { const initialData = [ { label: 'Expand to load', value: '0', key: '0', }, { label: 'Expand to load', value: '1', key: '1', }, { label: 'Leaf Node', value: '2', key: '2', isLeaf: true, }, ]; const [treeData, setTreeData] = useState(initialData); const [loadedKeys, setLoadedKeys] = useState(['2']); function updateTreeData(list, key, children) { return list.map(node => { if (node.key === key) { return { ...node, children }; } if (node.children) { return { ...node, children: updateTreeData(node.children, key, children) }; } return node; }); } function onLoadData({ key, children }) { return new Promise(resolve => { if (children) { resolve(); return; } setTimeout(() => { setTreeData(origin => updateTreeData(origin, key, [ { label: 'Child Node', key: `${key}-0`, }, { label: 'Child Node', key: `${key}-1`, }, ]), ); resolve(); }, 1000); }); } return ( ); } export const loadDataAndLoadedkeys = () => { const initialData = [ { label: 'Expand to load', value: '0', key: '0', }, { label: 'Expand to load', value: '1', key: '1', }, { label: 'Leaf Node', value: '2', key: '2', isLeaf: true, }, ]; const [treeData, setTreeData] = useState(initialData); const [loadedKeys, setLoadedKeys] = useState(['2']); function updateTreeData(list, key, children) { return list.map(node => { if (node.key === key) { return { ...node, children }; } if (node.children) { return { ...node, children: updateTreeData(node.children, key, children) }; } return node; }); } function updateLoadedKeys(key) { if(!loadedKeys.includes(key)){ setLoadedKeys([...loadedKeys, key]); console.log('[...loadedKeys, key]', [...loadedKeys, key]); } } function onLoadData({ key, children }) { return new Promise(resolve => { if (children) { resolve(); return; } setTimeout(() => { setTreeData(origin => updateTreeData(origin, key, [ { label: 'Child Node', key: `${key}-0`, }, { label: 'Child Node', key: `${key}-1`, }, ]), ); // updateLoadedKeys(key); resolve(); }, 1000); }); } return ( ); } export const size = () => { const props = { style: { width: 300 }, dropdownStyle: { maxHeight: 400, overflow: 'auto' }, defaultValue: ['0-0-1', '0-0-2', '0-0-3', '0-0-4', '0-0-5', '0-0-6', '0-0-7'], treeData: treeData3, multiple: true, filterTreeNode: true, searchPosition: "trigger" }; return (<>



); } export const valueNotInTreeDataIssue = () => { const treeData = [ { key: "test", label: "测试标签", children: [ { key: "test_2", label: "测试二级标签" }, { key: "jzr_test", label: "之睿测试" } ] }, { key: "create", label: "创作构思", children: [ { key: "material", label: "素材积累" }, { key: "lens_script", label: "分镜脚本" } ] } ]; const treeDataWithValue = [ { value: "test", key: "0", label: "测试标签", children: [ { value: "test_2", key: "0-1", label: "测试二级标签" }, { value: "jzr_test", key: "0-2", label: "之睿测试" } ] }, { value: "create", key: "1", label: "创作构思", children: [ { value: "material", key: "1-1", label: "素材积累" }, { value: "lens_script", key: "1-2", label: "分镜脚本" } ] } ]; const commonProps = useMemo(() => { return { multiple: true, style: { width: 300 }, dropdownStyle: { maxHeight: 400, overflow: 'auto' }, onChange: (value) => { console.log('onChange', value); }, onSelect: (value) => { console.log('onSelect', value); }, }; }, []); return ( <>

多选,无 value

checkRelation='related'

checkRelation='unRelated'

onChangeWithObject, checkRelation='related'

onChangeWithObject, checkRelation='unRelated'

多选,有 value

checkRelation='related'

checkRelation='unRelated'

onChangeWithObject, checkRelation='unRelated'

onChangeWithObject, checkRelation='unRelated'

单选,无 value

onChangeWithObject

单选,有 value

onChangeWithObject

); }; class ValueTypeIsNumber extends React.Component { constructor() { super(); this.state = { value: 1 }; } onChange(value) { console.log('onChange', value); this.setState({ value }); } render() { const treeData = [ { label: '北美洲', value: 'North America', key: '1', }, { label: '亚洲', value: 'Asia', key: '0', children: [ { label: '中国', value: 'China', key: '0-0', children: [ { label: '北京', value: 'Beijing', key: '0-0-0', }, { label: '上海', value: 'Shanghai', key: '0-0-1', }, ], }, ], }, ]; return ( this.onChange(e)} /> ); } } export const valueIsNumber = () => export const searchPositionInTriggerAndVirtualize = () => { return ( <> ); }; export const clickTriggerToHide = () => ( <>

clickTriggerToHide 未设置,默认为 true

clickTriggerToHide 设置为 false

); export const triggerRenderAddMethod = () => { const treeData = useMemo(() => [ { label: '亚洲', value: '亚洲', key: '0', children: [ { label: '中国', value: '中国', key: '0-0', children: [ { label: '北京', value: '北京', key: '0-0-0', }, { label: '上海', value: '上海', key: '0-0-1', }, ], }, ], }, { label: '北美洲', value: '北美洲', key: '1', } ], []); const onValueChange = useCallback((value) => { console.log('onChange', value); }); const closeIcon = useCallback((value, onClear) => { return value && value.length ? : ; }, []); const renderTagItem = useCallback((item, onRemove) => ( { onRemove(item.key); }}>{item.label} ), []); const renderTrigger1 = useCallback((props) => { const { value, placeholder, onClear } = props; return ( ); }, []); const renderTrigger2 = useCallback((props) => { const { value, onSearch, onRemove, onClear } = props; return (
{value && value.length > 0 &&
{value.map(item => renderTagItem(item, onRemove))}
} {closeIcon(value, onClear)}
); }, []); const renderTrigger3 = useCallback((props) => { const { value, onSearch, onRemove, inputValue } = props; const tagInputValue = value.map(item => item.key); const renderTagInMultiple = (key) => { const label = value.find(item => item.key === key).label; const onCloseTag = (value, e, tagKey) => { onRemove(tagKey); } return {label} } return ( ) }, []); return ( <>



); } export const AutoSearchFocusPlusPreventScroll = () => { return (
我是一个高度和视窗高度一致的div。
由于 TreeSelect 设置了 searchAutoFocus 以及 preventScroll,
符合预期的情况是在没有滚动屏幕情况下,你不会看到 TreeSelect 的 trigger
); }; export const LongLabel = () => { const treeData = [ { label: '这是一个超长的中文测试用标题这是一个超长的中文测试用标题这是一个超长的中文测试用标题这是一个超长的中文测试用标题', value: 'v1', key: '0', }, { label: 'ThisISAVeryLongTestSentenceThisISAVeryLongTestSentenceThisISAVeryLongTestSentence', value: 'v2', key: '1', } ]; return ( <>

单选

单选,可搜索, searchPosition='trigger'

单选,可搜索, searchPosition='dropDown'

单选

单选,可搜索, searchPosition='trigger'

单选,可搜索, searchPosition='dropDown'

); } export const UnRelatedAndAsyncLoad = () => { const initialData = [ { label: 'Expand to load0', value: '0', key: '0', }, { label: 'Expand to load1', value: '1', key: '1', }, { label: 'Leaf Node', value: '2', key: '2', isLeaf: true, }, ]; const [treeData, setTreeData] = useState(initialData); function updateTreeData(list, key, children) { return list.map(node => { if (node.key === key) { return { ...node, children }; } if (node.children) { return { ...node, children: updateTreeData(node.children, key, children) }; } return node; }); } function onLoadData({ key, children }) { return new Promise(resolve => { if (children) { resolve(); return; } setTimeout(() => { setTreeData(origin => updateTreeData(origin, key, [ { label: `Child Node${key}-0`, key: `${key}-0`, }, { label: `Child Node${key}-1`, key: `${key}-1`, }, ]), ); resolve(); }, 1000); }); } return ( <> issue 1852: checkRelation='unRelated', 异步加载数据 ); }; const constructLargeData = () => { const newArray = (new Array(10)).fill(0).map((item, m) => { const parent = { key: `key-${m}`, label: `node-${m}`, children: [] } new Array(100).fill(0).map((item, n) => { const children = { key: `key-${m}-${n}`, label: `value-${m}-${n}`, children: [] } new Array(10).fill(0).map((item, o) => { const grandChildren = { key: `key-${m}-${n}-${o}`, label: `value-${m}-${n}-${o}`, } children.children.push(grandChildren); }); parent.children.push(children); }); return parent; }); return newArray; } export const ChangeTreeData = () => { const [sign, setSign] = useState(true); const treeData1 = useMemo(() => { return constructLargeData(); }, []); const treeData2 = useMemo(() => { return constructLargeData(); }, []); const onButtonClick = useCallback(() => { setSign((sign) => { return !sign; }) }, []); return <>

} export const KeyMaps = () => { const [withObject, setWithObject] = useState(false); const [value1, setValue1] = useState(undefined); const [value2, setValue2] = useState(undefined); const [expandKeys, setExpandedKeys] = useState(["yazhou", 'zhongguo']); const switchChange = useCallback((checked) => { setWithObject(checked); setValue1(undefined); setValue2(undefined); }, []); const onSingleChange = useCallback((value) => { console.log('onSingleChange', value); setValue1(value); }, []); const onMultipleChange = useCallback((value) => { console.log('onMultipleChange', value); setValue2(value); }, []); const normalChange = useCallback((value) => { console.log('onChange', value); }, []); const normalExpand = useCallback((expandedKeys, {expanded, node}) => { console.log('onExpanded', expandedKeys, expanded, copy(node)); }, []); const keyMaps = useMemo(() => { return { // value: 'value1', key: 'key1', label: 'label1', children: 'children1', disabled: 'disabled1' }; }, []); const regularTreeProps = useMemo(() => ({ keyMaps: keyMaps, treeData: specialTreeData, style: { width: 300 }, dropdownStyle: { maxHeight: 400, overflow: 'auto' }, onChange: normalChange, onExpand: normalExpand, onChangeWithObject: withObject, }), [withObject]); const defaultSelectedObj = { label1: '北京', // value1: 'Beijing', key1: 'beijing', }; return ( <> onChangeWithObject
Single select
Single select, onSearch, filterTreeNode, treeNodeFilterProp
{ console.log("filterTreeNode", inputValue, treeNodeString, data); return treeNodeString.includes(inputValue); }} treeNodeFilterProp={"key1"} onSearch={(input, filteredExpandedKeys) => { console.log('onSearch', input, filteredExpandedKeys); }} />
Single select, controlled
Multiple select
Multiple select, controlled
Multiple select, disableStrictly
Multiple, 展开受控
{ console.log('onExpanded', expandedKeys, expanded, copy(node)); setExpandedKeys(expandedKeys); }} />
); } export const Issue1542 = () => { const [expandedKeys, setExpandedKeys] = useState([]); const treeData = treeDataEn; const onExpand = useCallback((expandedKeys) => { setExpandedKeys(expandedKeys); }, [expandedKeys]); const onSearch = useCallback((inputValue, filteredExpandedKeys) => { const set = new Set([...filteredExpandedKeys, ...expandedKeys]); setExpandedKeys(Array.from(set)); }, [setExpandedKeys]); return ( <> ); }; class WebComponentWrapper extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); } connectedCallback() { ReactDOM.render(<_TreeSelect />, this.shadowRoot); } } customElements.define('my-web-component', WebComponentWrapper); export const WebCompTestOutside = () => { return ( ); }; export const CustomSelectAll = () => { const [value, setValue] = useState([]); const [filteredNodes, setFilteredNodes] = useState([]) const treeData = treeDataEn; const onSearch = useCallback((inputValue, filteredExpandedKeys, _filteredNodes) => { setFilteredNodes(_filteredNodes) }, []); const handleOnChange = useCallback((value) => { setValue(value); }, []) // 是否全选 const allSelected = useMemo(() => { if (!filteredNodes.length) { return false; } const optionValues = filteredNodes.map(i => i.value); return !without(optionValues, ...value).length; }, [filteredNodes, value]); const handleOnAllSelect = useCallback(() => { const optionValues = filteredNodes.map(i => i.value); handleOnChange(allSelected ? [] : optionValues); }, [allSelected, handleOnChange, filteredNodes]); const outerBottomSlot = useMemo(() => { if (!filteredNodes.length) { // 未筛选状态下不展示按钮 return null; } return (
{allSelected ? '取消全选' : '全选'}
); }, [allSelected, handleOnAllSelect, filteredNodes]); return ( <> 本用例借助 onSearch 的第三个参数_filteredNodes 自定义搜索全选功能
); }; export const AutoMerge = () => { const [value, setValue] = useState([]); const onChange = useCallback((val) => { console.log('onChange', val); setValue(val); }, []); return ( <> ) } export const showFilteredOnly = () => { return ( <> searchPosition="trigger", showFilteredOnly, multiple
); } export const EmptyContent = () => { const treeData = [ { label: '亚洲', value: 'Asia', key: '0', children: [ { label: '中国', value: 'China', key: '0-0', children: [ { label: '北京', value: 'Beijing', key: '0-0-0', }, { label: '上海', value: 'Shanghai', key: '0-0-1', }, ], }, ], }, { label: '北美洲', value: 'North America', key: '1', } ]; return ( <>

); } export const filterAndKeyMaps = () => { const treeData = [ { name: 'Asia', value: 'Asia', key: '0', children: [ { name: 'China', value: 'China', key: '0-0', children: [ { name: 'Beijing', value: 'Beijing', key: '0-0-0', }, { name: 'Shanghai', value: 'Shanghai', key: '0-0-1', }, ], }, { name: 'Japan', value: 'Japan', key: '0-1', children: [ { name: 'Osaka', value: 'Osaka', key: '0-1-0' } ] }, ], }, { name: 'North America', value: 'North America', key: '1', children: [ { name: 'United States', value: 'United States', key: '1-0' }, { name: 'Canada', value: 'Canada', key: '1-1' } ] } ]; return ( ) } export const CustomExpandIcon = () => { const expandIconFunc = useCallback((props) => { const { expanded, onClick, className } = props; if (expanded) { return } else { return } }); return ( <>

expandIcon 是 ReactNode

} multiple defaultExpandedKeys={['yazhou']} treeData={treeData2} />

expandIcon 是函数

); }