tree.stories.js 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172
  1. import React, { useRef, useState } from 'react';
  2. import Tree from '../index';
  3. import AutoSizer from '../autoSizer';
  4. import { Button, ButtonGroup, Input, Popover, Toast } from '../../index';
  5. import BigTree from './BigData';
  6. import testData from './data';
  7. import { cloneDeep, difference, isEqual } from 'lodash';
  8. import { IconEdit, IconMapPin, IconMore } from '@douyinfe/semi-icons';
  9. const TreeNode = Tree.TreeNode;
  10. export default {
  11. title: 'Tree'
  12. }
  13. const treeChildren = [
  14. {
  15. label: '北京',
  16. value: 'beijing',
  17. key: 'beijing',
  18. },
  19. {
  20. label: '上海',
  21. value: 'shanghai',
  22. key: 'shanghai',
  23. },
  24. ];
  25. const treeData1 = [
  26. {
  27. label: '亚洲',
  28. value: 'yazhou',
  29. key: 'yazhou',
  30. children: [
  31. {
  32. label: '中国',
  33. value: 'zhongguo',
  34. key: 'zhongguo',
  35. disabled: true,
  36. children: treeChildren,
  37. },
  38. {
  39. label: '日本',
  40. value: 'riben',
  41. key: 'riben',
  42. children: [
  43. {
  44. label: '东京',
  45. value: 'dongjing',
  46. key: 'dongjing',
  47. },
  48. {
  49. label: '大阪',
  50. value: 'daban',
  51. key: 'daban',
  52. },
  53. ],
  54. },
  55. ],
  56. },
  57. {
  58. label: '北美洲',
  59. value: 'beimeizhou',
  60. key: 'beimeizhou',
  61. children: [
  62. {
  63. label: '美国',
  64. value: 'meiguo',
  65. key: 'meiguo',
  66. },
  67. {
  68. label: '加拿大',
  69. value: 'jianada',
  70. key: 'jianada',
  71. },
  72. ],
  73. },
  74. ];
  75. const treeDataWithoutValue = [
  76. {
  77. label: '亚洲',
  78. key: 'yazhou',
  79. children: [
  80. {
  81. label: '中国',
  82. key: 'zhongguo',
  83. disabled: true,
  84. children: treeChildren,
  85. },
  86. {
  87. label: '日本',
  88. key: 'riben',
  89. children: [
  90. {
  91. label: '东京',
  92. key: 'dongjing',
  93. },
  94. {
  95. label: '大阪',
  96. key: 'daban',
  97. },
  98. ],
  99. },
  100. ],
  101. },
  102. {
  103. label: '北美洲',
  104. key: 'beimeizhou',
  105. children: [
  106. {
  107. label: '美国',
  108. key: 'meiguo',
  109. },
  110. {
  111. label: '加拿大',
  112. key: 'jianada',
  113. },
  114. ],
  115. },
  116. ];
  117. const treeDataWithIcon = [
  118. {
  119. label: 'Asia',
  120. value: 'Asia',
  121. key: '0',
  122. icon: <IconMapPin style={{ color: 'var(--semi-color-text-2)' }} />,
  123. children: [
  124. {
  125. label: 'China',
  126. value: 'China',
  127. key: '0-0',
  128. icon: <IconMapPin style={{ color: 'var(--semi-color-text-2)' }} />,
  129. },
  130. {
  131. label: 'Japan',
  132. value: 'Japan',
  133. key: '0-1',
  134. icon: <IconMapPin style={{ color: 'var(--semi-color-text-2)' }} />,
  135. },
  136. ],
  137. },
  138. ];
  139. let opts = {
  140. content: 'Hi, Bytedance dance dance',
  141. duration: 3,
  142. };
  143. const treeDataWithNode = [
  144. {
  145. label: (
  146. <span>
  147. <span style={{ marginRight: 30 }}>亚洲</span>
  148. <Button
  149. style={{ zIndex: 2 }}
  150. onClick={e => {
  151. Toast.info(opts);
  152. e.stopPropagation();
  153. }}
  154. >
  155. Display Toast
  156. </Button>
  157. </span>
  158. ),
  159. value: 'yazhou',
  160. key: 'yazhou',
  161. children: [
  162. {
  163. label: '中国',
  164. value: 'zhongguo',
  165. key: 'zhongguo',
  166. children: [
  167. {
  168. label: '北京',
  169. value: 'beijing',
  170. key: 'beijing',
  171. },
  172. {
  173. label: '上海',
  174. value: 'shanghai',
  175. key: 'shanghai',
  176. },
  177. ],
  178. },
  179. {
  180. label: '日本',
  181. value: 'riben',
  182. key: 'riben',
  183. },
  184. ],
  185. },
  186. {
  187. label: '北美洲',
  188. value: 'beimeizhou',
  189. key: 'beimeizhou',
  190. children: [
  191. {
  192. label: '美国',
  193. value: 'meiguo',
  194. key: 'meiguo',
  195. },
  196. {
  197. label: '加拿大',
  198. value: 'jianada',
  199. key: 'jianada',
  200. },
  201. ],
  202. },
  203. ];
  204. const treeJson = {
  205. Node1: {
  206. Child1: '0-0-1',
  207. Child2: '0-0-2',
  208. },
  209. Node2: '0-1',
  210. };
  211. const benchmarkSet = size => {
  212. console.time('benchmarkSet');
  213. var set = new Set();
  214. for (var i = 0; i < size; i++) set.add(i);
  215. for (var i = 0; i < size; i++) set.has(i);
  216. console.timeEnd('benchmarkSet');
  217. };
  218. const benchmarkArr = size => {
  219. console.time('benchmarkArr');
  220. var arr = [];
  221. for (var i = 0; i < size; i++) arr.push(i);
  222. for (var i = 0; i < size; i++) arr.indexOf(i);
  223. console.timeEnd('benchmarkArr');
  224. };
  225. export const BenchMark = () => {
  226. const size = 100000;
  227. benchmarkSet(size);
  228. benchmarkArr(size);
  229. return <div>check console please</div>;
  230. };
  231. BenchMark.story = {
  232. name: 'bench mark',
  233. };
  234. export const SimpleTree = () => (
  235. <Tree
  236. treeData={treeData1}
  237. // onExpand={(e, { expanded, node }) => console.log('expand', e, expanded, node)}
  238. // onSelect={(e, bool, node) => console.log('select', e, bool, node)}
  239. // onChange={e => console.log('change', e)}
  240. onContextMenu={(e, node) => console.log(e.currentTarget, node)}
  241. onDoubleClick={(e, node) => console.log(e, node)}
  242. motion={true}
  243. />
  244. );
  245. SimpleTree.story = {
  246. name: 'simple tree',
  247. };
  248. export const MultipleTree = () => (
  249. <Tree
  250. treeData={treeData1}
  251. multiple
  252. labelInValue
  253. // onExpand={(e, { expanded, node }) => console.log('expand', e, expanded, node)}
  254. // onSelect={(e, bool) => console.log('select', e, bool)}
  255. onContextMenu={(e, node) => console.log(e, node)}
  256. onDoubleClick={(e, node) => console.log(e, node)}
  257. onChange={e => console.log('change', e)}
  258. />
  259. );
  260. MultipleTree.story = {
  261. name: 'multiple tree',
  262. };
  263. export const SearchableTree = () => (
  264. <Tree
  265. treeData={treeData1}
  266. filterTreeNode
  267. treeNodeFilterProp="value"
  268. multiple
  269. searchStyle={{ width: '300px' }}
  270. />
  271. );
  272. SearchableTree.story = {
  273. name: 'searchable tree',
  274. };
  275. export const DisabledTree = () => (
  276. <Tree treeData={treeData1} defaultValue={['dongjing', 'daban']} multiple disabled />
  277. );
  278. DisabledTree.story = {
  279. name: 'disabled tree',
  280. };
  281. export const DefaultTree = () => (
  282. <div>
  283. <Tree treeData={treeData1} defaultValue={['zhongguo']} />
  284. <br />
  285. <Tree
  286. treeData={treeData1}
  287. multiple
  288. defaultValue={['shanghai', 'dongjing', 'beijing', 'daban']}
  289. onChange={e => console.log(e)}
  290. onSelect={e => console.log(e)}
  291. />
  292. </div>
  293. );
  294. DefaultTree.story = {
  295. name: 'default tree',
  296. };
  297. export const ExpandAction = () => (
  298. <div>
  299. <Tree treeData={treeData1} defaultValue={['zhongguo']} />
  300. <br />
  301. <Tree
  302. treeData={treeData1}
  303. //multiple
  304. defaultValue={['shanghai', 'dongjing', 'beijing', 'daban']}
  305. expandAction="click"
  306. onDoubleClick={e => console.log(e.detail)}
  307. />
  308. <br />
  309. <Tree
  310. treeData={treeData1}
  311. multiple
  312. defaultValue={['shanghai', 'dongjing', 'beijing', 'daban']}
  313. expandAction="doubleClick"
  314. />
  315. </div>
  316. );
  317. ExpandAction.story = {
  318. name: 'expandAction',
  319. };
  320. class Demo extends React.Component {
  321. constructor() {
  322. super();
  323. this.state = {
  324. value: 'shanghai',
  325. };
  326. }
  327. onChange(value) {
  328. this.setState({ value });
  329. }
  330. render() {
  331. return (
  332. <Tree
  333. style={{ width: 300 }}
  334. dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
  335. treeData={treeData1}
  336. value={this.state.value}
  337. placeholder="Please select"
  338. onChange={e => this.onChange(e)}
  339. />
  340. );
  341. }
  342. }
  343. export const ControlledComponentSingle = () => <Demo />;
  344. ControlledComponentSingle.story = {
  345. name: 'controlled Component single',
  346. };
  347. class Demo2 extends React.Component {
  348. constructor() {
  349. super();
  350. this.state = {
  351. value: ['shanghai', 'beijing', 'zhongguo'],
  352. };
  353. }
  354. onChange(value) {
  355. console.log(value);
  356. this.setState({ value });
  357. }
  358. render() {
  359. console.log(this.state.value);
  360. return (
  361. <Tree
  362. style={{ width: 300 }}
  363. multiple
  364. dropdownStyle={{ maxHeight: 200, overflow: 'auto' }}
  365. treeData={treeData1}
  366. value={this.state.value}
  367. placeholder="Please select"
  368. onChange={e => this.onChange(e)}
  369. />
  370. );
  371. }
  372. }
  373. export const ControlledComponentMultiple = () => <Demo2 />;
  374. ControlledComponentMultiple.story = {
  375. name: 'controlled Component multiple',
  376. };
  377. export const JsonTree = () => (
  378. <div>
  379. <Tree
  380. treeDataSimpleJson={treeJson}
  381. onChange={e => console.log('change', e)}
  382. onSelect={e => console.log('select', e)}
  383. />
  384. <br />
  385. <Tree
  386. treeDataSimpleJson={treeJson}
  387. multiple
  388. onChange={e => console.log(e)}
  389. onSelect={e => console.log(e)}
  390. />
  391. </div>
  392. );
  393. JsonTree.story = {
  394. name: 'json tree',
  395. };
  396. export const IconTree = () => (
  397. <div>
  398. <Tree treeData={treeDataWithIcon} />
  399. <br />
  400. <Tree treeData={treeDataWithIcon} multiple blockNode />
  401. </div>
  402. );
  403. IconTree.story = {
  404. name: 'icon tree',
  405. };
  406. export const DirectoryTree = () => <Tree treeData={treeData1} directory multiple blockNode />;
  407. DirectoryTree.story = {
  408. name: 'directory tree',
  409. };
  410. const button = (
  411. <ButtonGroup size="small" theme="borderless">
  412. <Button
  413. onClick={e => {
  414. Toast.info(opts);
  415. e.stopPropagation();
  416. }}
  417. >
  418. 提示
  419. </Button>
  420. <Button>点击</Button>
  421. </ButtonGroup>
  422. );
  423. const style = {
  424. display: 'flex',
  425. justifyContent: 'space-between',
  426. alignItems: 'center',
  427. };
  428. const treeDataWithNode2 = [
  429. {
  430. label: (
  431. <div style={style}>
  432. <span>亚洲</span>
  433. <ButtonGroup size="small" theme="borderless">
  434. {button}
  435. </ButtonGroup>
  436. </div>
  437. ),
  438. value: 'yazhou',
  439. key: 'yazhou',
  440. children: [
  441. {
  442. label: (
  443. <div style={style}>
  444. <span>中国</span>
  445. {button}
  446. </div>
  447. ),
  448. value: 'zhongguo',
  449. key: 'zhongguo',
  450. children: [
  451. {
  452. label: (
  453. <div style={style}>
  454. <span>test</span>
  455. {button}
  456. </div>
  457. ),
  458. value: 'test',
  459. key: 'test',
  460. },
  461. ],
  462. },
  463. {
  464. label: (
  465. <div style={style}>
  466. <span>日本</span>
  467. {button}
  468. </div>
  469. ),
  470. value: 'riben',
  471. key: 'riben',
  472. },
  473. ],
  474. },
  475. ];
  476. export const TreeLabelUsingNode = () => (
  477. <div>
  478. <Tree treeData={treeDataWithNode2} blockNode defaultExpandAll />
  479. </div>
  480. );
  481. TreeLabelUsingNode.story = {
  482. name: 'tree label using node',
  483. };
  484. const treeDataTest = [
  485. {
  486. value: '一级标签1',
  487. label: '一级标签1',
  488. id: 1,
  489. key: '1',
  490. },
  491. ];
  492. class TagSideSheet2 extends React.Component {
  493. constructor() {
  494. super();
  495. this.state = {
  496. tagList: [],
  497. visibles: false,
  498. };
  499. this.onVisible = this.onVisible.bind(this);
  500. this.renderLabel = this.renderLabel.bind(this);
  501. this.transLabel = this.transLabel.bind(this);
  502. }
  503. componentDidMount() {
  504. let tagList = [...treeDataTest];
  505. this.setState({
  506. tagList,
  507. });
  508. }
  509. onVisible(visibles) {
  510. this.setState({
  511. visibles,
  512. });
  513. }
  514. renderLabel(item) {
  515. const { visibles } = this.state;
  516. console.log('rendering label', visibles);
  517. return (
  518. <Popover trigger="custom" position="bottomLeft" visible={visibles} content={'测试popover'}>
  519. <Button
  520. icon={<IconEdit />}
  521. onClick={e => {
  522. e.stopPropagation();
  523. this.onVisible(!visibles);
  524. }}
  525. >
  526. {item.label}
  527. </Button>
  528. </Popover>
  529. );
  530. }
  531. transLabel(list) {
  532. // list = cloneDeep(list);
  533. list.forEach(item => {
  534. item.label = this.renderLabel(item);
  535. // item.key += Math.random().toString().slice(0, 5);
  536. });
  537. return list;
  538. }
  539. render() {
  540. const { tagList = [] } = this.state;
  541. const transformedTags = this.transLabel(cloneDeep(tagList));
  542. console.log('transformedTags', transformedTags, treeDataTest);
  543. return <Tree treeData={transformedTags} />;
  544. }
  545. }
  546. export const TreeLabelUsingPopover = () => <TagSideSheet2 />;
  547. TreeLabelUsingPopover.story = {
  548. name: 'tree label using popover',
  549. };
  550. export const DefaultExpandKeysTree = () => (
  551. <>
  552. <Tree treeData={treeData1} defaultExpandedKeys={['zhongguo', 'beimeizhou']} blockNode />
  553. <Tree treeData={treeData1} defaultExpandAll blockNode />
  554. <Tree treeData={treeData1} defaultExpandAll multiple blockNode />
  555. </>
  556. );
  557. DefaultExpandKeysTree.story = {
  558. name: 'defaultExpandKeys tree',
  559. };
  560. export const LabelInValueTree = () => (
  561. <>
  562. <Tree treeData={treeData1} labelInValue onChange={e => console.log(e)} />
  563. <Tree treeData={treeData1} labelInValue onChange={e => console.log(e)} multiple />
  564. <Tree treeData={treeDataWithIcon} labelInValue onChange={e => console.log(e)} multiple />
  565. </>
  566. );
  567. LabelInValueTree.story = {
  568. name: 'labelInValue tree',
  569. };
  570. class Test extends React.Component {
  571. constructor() {
  572. super();
  573. this.state = {
  574. loading: false,
  575. };
  576. }
  577. componentDidMount() {
  578. setTimeout(() => {
  579. console.log('set loading');
  580. this.setState({ loading: true });
  581. }, 5000);
  582. }
  583. render() {
  584. const treeDataWithNode2 = [
  585. {
  586. label: (
  587. <div style={style}>
  588. <span>亚洲</span>
  589. <ButtonGroup size="small" theme="borderless">
  590. {button}
  591. </ButtonGroup>
  592. </div>
  593. ),
  594. value: 'yazhou',
  595. key: 'yazhou',
  596. children: [
  597. {
  598. label: (
  599. <div style={style}>
  600. <span>中国</span>
  601. {button}
  602. </div>
  603. ),
  604. value: 'zhongguo',
  605. key: 'zhongguo',
  606. children: [
  607. {
  608. label: (
  609. <div style={style}>
  610. <span>test</span>
  611. {button}
  612. </div>
  613. ),
  614. value: 'test',
  615. key: 'test',
  616. },
  617. ],
  618. },
  619. {
  620. label: (
  621. <div style={style}>
  622. <span>日本</span>
  623. {button}
  624. </div>
  625. ),
  626. value: 'riben',
  627. key: 'riben',
  628. },
  629. ],
  630. },
  631. ];
  632. return <Tree treeData={treeDataWithNode2} />;
  633. }
  634. }
  635. export const SetStateAfter5S = () => <Test />;
  636. SetStateAfter5S.story = {
  637. name: 'setState after 5s',
  638. };
  639. class DemoExpandedKeys extends React.Component {
  640. constructor() {
  641. super();
  642. this.state = {
  643. expand: ['zhongguo', 'beimeizhou'],
  644. };
  645. }
  646. onExpand(expand) {
  647. console.log(expand);
  648. this.setState({ expand });
  649. }
  650. render() {
  651. return (
  652. <Tree
  653. style={{ width: 300 }}
  654. dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
  655. treeData={treeData1}
  656. expandedKeys={this.state.expand}
  657. placeholder="Please select"
  658. onExpand={(e, rest) => this.onExpand(e, rest)}
  659. />
  660. );
  661. }
  662. }
  663. class DemoExpandeKeysMulti extends React.Component {
  664. constructor() {
  665. super();
  666. this.state = {
  667. expand: ['zhongguo'],
  668. };
  669. }
  670. onExpand(expand) {
  671. console.log(expand);
  672. this.setState({ expand });
  673. }
  674. render() {
  675. return (
  676. <Tree
  677. style={{ width: 300 }}
  678. multiple
  679. dropdownStyle={{ maxHeight: 400, overflow: 'auto' }}
  680. treeData={treeData1}
  681. expandedKeys={this.state.expand}
  682. placeholder="Please select"
  683. onExpand={e => this.onExpand(e)}
  684. />
  685. );
  686. }
  687. }
  688. export const ExpandedKeys = () => (
  689. <>
  690. <DemoExpandedKeys />
  691. <br />
  692. <DemoExpandeKeysMulti />
  693. </>
  694. );
  695. ExpandedKeys.story = {
  696. name: 'expandedKeys',
  697. };
  698. class DmExpandedKeys extends React.Component {
  699. constructor() {
  700. super();
  701. this.state = {
  702. treeData: [
  703. {
  704. key: '0',
  705. label: 'item-0',
  706. value: '0',
  707. },
  708. ],
  709. };
  710. this.add = this.add.bind(this);
  711. }
  712. add() {
  713. let itemLength = Math.floor(Math.random() * 5) + 1;
  714. let treeData = new Array(itemLength).fill(0).map((v, i) => {
  715. let length = Math.floor(Math.random() * 3);
  716. let children = new Array(length).fill(0).map((cv, ci) => {
  717. let child = {
  718. key: `${i}-${ci}`,
  719. label: `Leaf-${i}-${ci}`,
  720. value: `${i}-${ci}`,
  721. };
  722. return child;
  723. });
  724. let item = {
  725. key: `${i}`,
  726. label: `Item-${i}`,
  727. value: `${i}`,
  728. children,
  729. };
  730. return item;
  731. });
  732. this.setState({ treeData });
  733. }
  734. render() {
  735. const { treeData } = this.state;
  736. return (
  737. <>
  738. <Tree treeData={this.state.treeData} expandedKeys={['0', '1']} />
  739. <br />
  740. <Button onClick={this.add}>动态改变数据</Button>
  741. </>
  742. );
  743. }
  744. }
  745. export const DynamicExpandKeys = () => (
  746. <>
  747. <DmExpandedKeys />
  748. </>
  749. );
  750. DynamicExpandKeys.story = {
  751. name: 'dynamic expandKeys',
  752. };
  753. class DmSelectedKeys extends React.Component {
  754. constructor() {
  755. super();
  756. this.state = {
  757. treeData: [
  758. {
  759. key: '0',
  760. label: 'item-0',
  761. value: '0',
  762. },
  763. ],
  764. };
  765. this.add = this.add.bind(this);
  766. }
  767. add() {
  768. let itemLength = Math.floor(Math.random() * 5) + 1;
  769. let treeData = new Array(itemLength).fill(0).map((v, i) => {
  770. let length = Math.floor(Math.random() * 3);
  771. let children = new Array(length).fill(0).map((cv, ci) => {
  772. let child = {
  773. key: `${i}-${ci}`,
  774. label: `Leaf-${i}-${ci}`,
  775. value: `${i}-${ci}`,
  776. };
  777. return child;
  778. });
  779. let item = {
  780. key: `${i}`,
  781. label: `Item-${i}`,
  782. value: `${i}`,
  783. children,
  784. };
  785. return item;
  786. });
  787. this.setState({ treeData });
  788. }
  789. render() {
  790. const { treeData } = this.state;
  791. return (
  792. <>
  793. <Tree treeData={treeData} value={['0-0']} onChange={e => console.log(e)} />
  794. <br />
  795. <Button onClick={this.add}>动态改变数据</Button>
  796. </>
  797. );
  798. }
  799. }
  800. export const DynamicSelectedKey = () => (
  801. <>
  802. <DmSelectedKeys />
  803. </>
  804. );
  805. DynamicSelectedKey.story = {
  806. name: 'dynamic selectedKey',
  807. };
  808. export const LargeAmountOfData = () => (
  809. <>
  810. <BigTree />
  811. </>
  812. );
  813. LargeAmountOfData.story = {
  814. name: 'large amount of data',
  815. };
  816. export const Autosizer = () => (
  817. <div
  818. style={{
  819. boxSizing: 'border-box',
  820. height: 400,
  821. width: 200,
  822. }}
  823. >
  824. <div
  825. style={{
  826. boxSizing: 'border-box',
  827. height: '50%',
  828. width: 200,
  829. }}
  830. >
  831. <AutoSizer
  832. // defaultHeight={defaultHeight}
  833. // defaultWidth={defaultWidth}
  834. >
  835. {({ height, width }) => (
  836. <div
  837. style={{
  838. width: width,
  839. height: height,
  840. }}
  841. >
  842. {`width:${width}, height:${height}`}
  843. </div>
  844. )}
  845. </AutoSizer>
  846. </div>
  847. </div>
  848. );
  849. Autosizer.story = {
  850. name: 'autosizer',
  851. };
  852. const MotionCustomLabelDemo = () => {
  853. const treeData = [
  854. {
  855. label: '亚洲',
  856. value: 'Asia',
  857. key: '0',
  858. children: [
  859. {
  860. label: '中国',
  861. value: 'China',
  862. key: '0-0',
  863. children: [
  864. {
  865. label: '北京',
  866. value: 'Beijing',
  867. key: '0-0-0',
  868. },
  869. {
  870. label: '上海',
  871. value: 'Shanghai',
  872. key: '0-0-1',
  873. },
  874. ],
  875. },
  876. ],
  877. },
  878. {
  879. label: '北美洲',
  880. value: 'North America',
  881. key: '1',
  882. },
  883. ];
  884. const [hoverKey, setHoverKey] = useState();
  885. const cusLabel = (list = []) => {
  886. const recusive = (list = []) => {
  887. if (!list.length) {
  888. return;
  889. }
  890. list.forEach(item => {
  891. const { type, label, key } = item;
  892. item.label = (
  893. <div onMouseEnter={() => setHoverKey(key)}>
  894. {label}
  895. {hoverKey === key ? <IconMore /> : null}
  896. </div>
  897. );
  898. recusive(item.children);
  899. });
  900. };
  901. recusive(list);
  902. return list;
  903. };
  904. return <Tree treeData={cusLabel(treeData)} defaultExpandAll />;
  905. };
  906. export const MotionCustomLabel = () => <MotionCustomLabelDemo />;
  907. MotionCustomLabel.story = {
  908. name: 'motion custom label',
  909. };
  910. const AutoParentDemo = () => {
  911. const [expandedKeys, setExpandedKeys] = useState(['beimeizhou']);
  912. const [selectedKeys, setSelectedKeys] = useState(['beimeizhou']);
  913. const [autoExpandParent, setAutoExpandParent] = useState(true);
  914. const onExpand = expandedKeys => {
  915. console.log('onExpand', expandedKeys);
  916. // if not set autoExpandParent to false, if children expanded, parent can not collapse.
  917. // or, you can remove all expanded children keys.
  918. setExpandedKeys(expandedKeys);
  919. setAutoExpandParent(false);
  920. };
  921. const onSelect = (selectedKeys, info) => {
  922. console.log('onSelect:', info);
  923. setSelectedKeys(selectedKeys);
  924. };
  925. return (
  926. <div>
  927. <Button
  928. onClick={() => {
  929. setSelectedKeys(['riben']);
  930. setExpandedKeys(['riben']);
  931. setAutoExpandParent(true);
  932. }}
  933. >
  934. Update
  935. </Button>
  936. <Tree
  937. onExpand={onExpand}
  938. expandedKeys={expandedKeys}
  939. autoExpandParent={autoExpandParent}
  940. onChange={onSelect}
  941. value={selectedKeys}
  942. treeData={treeData1}
  943. multiple
  944. />
  945. </div>
  946. );
  947. };
  948. export const AutoExpandParent = () => (
  949. <>
  950. <AutoParentDemo />
  951. </>
  952. );
  953. AutoExpandParent.story = {
  954. name: 'autoExpandParent',
  955. };
  956. const findDescendantKeys = node => {
  957. let res = [node.key];
  958. const findChild = item => {
  959. if (!item) return;
  960. const { children } = item;
  961. if (children && children.length) {
  962. children.forEach(child => {
  963. res.push(child.key);
  964. findChild(child);
  965. });
  966. }
  967. };
  968. findChild(node);
  969. return res;
  970. };
  971. class DyTreeWithExpandControlled extends React.Component {
  972. constructor() {
  973. super();
  974. this.state = {
  975. treeData: [
  976. {
  977. key: '0',
  978. label: 'item-0',
  979. value: '0',
  980. },
  981. ],
  982. expandedKeys: [],
  983. autoExpandParent: false,
  984. inputValue: '',
  985. collapsedKeys: new Set([]),
  986. };
  987. }
  988. componentDidUpdate(prevProps, prevState) {
  989. if (
  990. !isEqual(prevState.treeData, this.state.treeData) ||
  991. !isEqual(prevState.inputValue, this.state.inputValue)
  992. ) {
  993. const { treeData, inputValue, collapsedKeys } = this.state;
  994. let filteredKeys = [];
  995. const findFilteredKey = arr => {
  996. arr.forEach(item => {
  997. if (item.label.indexOf(inputValue) > -1) {
  998. filteredKeys.push(item.key);
  999. }
  1000. if (item.children) {
  1001. findFilteredKey(item.children);
  1002. }
  1003. });
  1004. };
  1005. findFilteredKey(treeData);
  1006. const expanded = difference(filteredKeys, [...collapsedKeys]);
  1007. this.setState({
  1008. expandedKeys: expanded,
  1009. autoExpandParent: true,
  1010. });
  1011. }
  1012. }
  1013. add = () => {
  1014. let itemLength = Math.floor(Math.random() * 5) + 1;
  1015. let treeData = new Array(itemLength).fill(0).map((v, i) => {
  1016. let length = Math.floor(Math.random() * 3) + 1;
  1017. let children = new Array(length).fill(0).map((cv, ci) => {
  1018. let child = {
  1019. key: `${i}-${ci}`,
  1020. label: `Leaf-${i}-${ci}`,
  1021. value: `${i}-${ci}`,
  1022. };
  1023. return child;
  1024. });
  1025. let item = {
  1026. key: `${i}`,
  1027. label: `Item-${i}`,
  1028. value: `${i}`,
  1029. children,
  1030. };
  1031. return item;
  1032. });
  1033. this.setState({ treeData });
  1034. };
  1035. search = val => {
  1036. this.setState({ inputValue: val });
  1037. };
  1038. onExpand = (keys, { expanded, node }) => {
  1039. let collapsed = this.state.collapsedKeys;
  1040. let desKeys = findDescendantKeys(node);
  1041. if (!expanded) {
  1042. desKeys.forEach(key => collapsed.add(key));
  1043. } else {
  1044. desKeys.forEach(key => collapsed.has(key) && collapsed.delete(key));
  1045. }
  1046. this.setState({
  1047. expandedKeys: keys,
  1048. autoExpandParent: false,
  1049. collapsedKeys: collapsed,
  1050. });
  1051. };
  1052. render() {
  1053. const { treeData, expandedKeys, autoExpandParent } = this.state;
  1054. return (
  1055. <div>
  1056. <Tree
  1057. treeData={treeData}
  1058. filterTreeNode
  1059. autoExpandParent={autoExpandParent}
  1060. expandedKeys={expandedKeys}
  1061. onSearch={this.search}
  1062. onExpand={this.onExpand}
  1063. />
  1064. <br />
  1065. <Button onClick={this.add} style={{ margin: 20 }}>
  1066. 动态改变数据
  1067. </Button>
  1068. </div>
  1069. );
  1070. }
  1071. }
  1072. export const DynamicTreeDataWithSearchValueAndControlledExpand = () => (
  1073. <DyTreeWithExpandControlled />
  1074. );
  1075. DynamicTreeDataWithSearchValueAndControlledExpand.story = {
  1076. name: 'dynamic treeData with searchValue and controlled expand',
  1077. };
  1078. const CusSearchRender = () => {
  1079. const [inputValue, setInputValue] = useState('');
  1080. const ref = useRef();
  1081. const setValue = value => {
  1082. setInputValue(value);
  1083. ref.current.search(value);
  1084. };
  1085. return (
  1086. <Tree
  1087. ref={ref}
  1088. treeData={treeData1}
  1089. filterTreeNode
  1090. showFilteredOnly
  1091. searchRender={({ prefix, placeholder }) => (
  1092. <Input
  1093. prefix={prefix}
  1094. placeholder={placeholder}
  1095. value={inputValue}
  1096. onChange={value => setValue(value)}
  1097. />
  1098. )}
  1099. />
  1100. );
  1101. };
  1102. export const _CusSearchRender = () => (
  1103. <>
  1104. <CusSearchRender />
  1105. </>
  1106. );
  1107. _CusSearchRender.story = {
  1108. name: 'CusSearchRender',
  1109. };
  1110. const RefSearch = () => {
  1111. const ref = useRef();
  1112. const treeData = [
  1113. {
  1114. label: 'Asia',
  1115. value: 'Asia',
  1116. key: '0',
  1117. children: [
  1118. {
  1119. label: 'China',
  1120. value: 'China',
  1121. key: '0-0',
  1122. children: [
  1123. {
  1124. label: 'Beijing',
  1125. value: 'Beijing',
  1126. key: '0-0-0',
  1127. },
  1128. {
  1129. label: 'Shanghai',
  1130. value: 'Shanghai',
  1131. key: '0-0-1',
  1132. },
  1133. ],
  1134. },
  1135. {
  1136. label: 'Japan',
  1137. value: 'Japan',
  1138. key: '0-1',
  1139. children: [
  1140. {
  1141. label: 'Osaka',
  1142. value: 'Osaka',
  1143. key: '0-1-0',
  1144. },
  1145. ],
  1146. },
  1147. ],
  1148. },
  1149. {
  1150. label: 'North America',
  1151. value: 'North America',
  1152. key: '1',
  1153. children: [
  1154. {
  1155. label: 'United States',
  1156. value: 'United States',
  1157. key: '1-0',
  1158. },
  1159. {
  1160. label: 'Canada',
  1161. value: 'Canada',
  1162. key: '1-1',
  1163. },
  1164. ],
  1165. },
  1166. ];
  1167. return (
  1168. <div>
  1169. <Input aria-label='filter tree' onChange={v => ref.current.search(v)} />
  1170. <Tree
  1171. treeData={treeData}
  1172. defaultValue="Shanghai"
  1173. blockNode={false}
  1174. ref={ref}
  1175. filterTreeNode
  1176. searchRender={() => null}
  1177. />
  1178. </div>
  1179. );
  1180. };
  1181. export const _RefSearch = () => (
  1182. <>
  1183. <RefSearch />
  1184. </>
  1185. );
  1186. _RefSearch.story = {
  1187. name: 'RefSearch',
  1188. };
  1189. const initTreeDate = [
  1190. {
  1191. label: 'Expand to load',
  1192. key: '0',
  1193. },
  1194. {
  1195. label: 'Expand to load',
  1196. key: '1',
  1197. },
  1198. {
  1199. label: 'Tree Node',
  1200. key: '2',
  1201. isLeaf: true,
  1202. },
  1203. ];
  1204. function updateTreeData(list, key, children) {
  1205. return list.map(node => {
  1206. if (node.key === key) {
  1207. return { ...node, children };
  1208. }
  1209. if (node.children) {
  1210. return { ...node, children: updateTreeData(node.children, key, children) };
  1211. }
  1212. return node;
  1213. });
  1214. }
  1215. const LoadingTreeDemo = () => {
  1216. const [treeData, setTreeData] = useState(initTreeDate);
  1217. function onLoadData({ key, children }) {
  1218. return new Promise(resolve => {
  1219. if (children) {
  1220. resolve();
  1221. return;
  1222. }
  1223. setTimeout(() => {
  1224. setTreeData(origin =>
  1225. updateTreeData(origin, key, [
  1226. {
  1227. label: 'Child Node',
  1228. key: `${key}-0`,
  1229. },
  1230. {
  1231. label: 'Child Node',
  1232. key: `${key}-1`,
  1233. },
  1234. ])
  1235. );
  1236. resolve();
  1237. }, 1000);
  1238. });
  1239. }
  1240. return <Tree loadData={onLoadData} treeData={cloneDeep(treeData)} />;
  1241. };
  1242. export const Loading = () => (
  1243. <>
  1244. <LoadingTreeDemo />
  1245. </>
  1246. );
  1247. Loading.story = {
  1248. name: 'loading',
  1249. };
  1250. const LoadingWithSearch = () => {
  1251. const [treeData, setTreeData] = useState(initTreeDate);
  1252. function onLoadData({ key, children }) {
  1253. return new Promise(resolve => {
  1254. if (children) {
  1255. resolve();
  1256. return;
  1257. }
  1258. setTimeout(() => {
  1259. setTreeData(origin =>
  1260. updateTreeData(origin, key, [
  1261. {
  1262. label: 'Child Node',
  1263. key: `${key}-0`,
  1264. },
  1265. {
  1266. label: 'Child Node',
  1267. key: `${key}-1`,
  1268. },
  1269. ])
  1270. );
  1271. resolve();
  1272. }, 1000);
  1273. });
  1274. }
  1275. return <Tree loadData={onLoadData} treeData={cloneDeep(treeData)} filterTreeNode />;
  1276. };
  1277. export const _LoadingWithSearch = () => (
  1278. <>
  1279. <LoadingWithSearch />
  1280. </>
  1281. );
  1282. _LoadingWithSearch.story = {
  1283. name: 'Loading with search',
  1284. };
  1285. const DisabledStrictly = () => {
  1286. return (
  1287. <>
  1288. <span> disable shanghai(checked), China </span>
  1289. <Tree
  1290. treeData={[
  1291. {
  1292. label: 'Asia',
  1293. value: 'Asia',
  1294. key: '0',
  1295. children: [
  1296. {
  1297. label: 'China',
  1298. value: 'China',
  1299. key: '0-0',
  1300. disabled: true,
  1301. children: [
  1302. {
  1303. label: 'Beijing',
  1304. value: 'Beijing',
  1305. key: '0-0-0',
  1306. },
  1307. {
  1308. label: 'Shanghai',
  1309. value: 'Shanghai',
  1310. key: '0-0-1',
  1311. disabled: true,
  1312. },
  1313. ],
  1314. },
  1315. {
  1316. label: 'Japan',
  1317. value: 'Japan',
  1318. key: '0-1',
  1319. children: [
  1320. {
  1321. label: 'Osaka',
  1322. value: 'Osaka',
  1323. key: '0-1-0',
  1324. },
  1325. ],
  1326. },
  1327. ],
  1328. },
  1329. ]}
  1330. defaultValue="Shanghai"
  1331. multiple
  1332. defaultExpandAll
  1333. disableStrictly
  1334. />
  1335. <br />
  1336. <span> disable shanghai(checked), beijing(checked) </span>
  1337. <Tree
  1338. treeData={[
  1339. {
  1340. label: 'Asia',
  1341. value: 'Asia',
  1342. key: '0',
  1343. children: [
  1344. {
  1345. label: 'China',
  1346. value: 'China',
  1347. key: '0-0',
  1348. children: [
  1349. {
  1350. label: 'Beijing',
  1351. value: 'Beijing',
  1352. key: '0-0-0',
  1353. disabled: true,
  1354. },
  1355. {
  1356. label: 'Shanghai',
  1357. value: 'Shanghai',
  1358. key: '0-0-1',
  1359. disabled: true,
  1360. },
  1361. ],
  1362. },
  1363. {
  1364. label: 'Japan',
  1365. value: 'Japan',
  1366. key: '0-1',
  1367. children: [
  1368. {
  1369. label: 'Osaka',
  1370. value: 'Osaka',
  1371. key: '0-1-0',
  1372. },
  1373. ],
  1374. },
  1375. ],
  1376. },
  1377. ]}
  1378. defaultValue={['Shanghai', 'Beijing']}
  1379. multiple
  1380. defaultExpandAll
  1381. disableStrictly
  1382. />
  1383. <span> disable shanghai(checked) </span>
  1384. <Tree
  1385. treeData={[
  1386. {
  1387. label: 'Asia',
  1388. value: 'Asia',
  1389. key: '0',
  1390. children: [
  1391. {
  1392. label: 'China',
  1393. value: 'China',
  1394. key: '0-0',
  1395. children: [
  1396. {
  1397. label: 'Beijing',
  1398. value: 'Beijing',
  1399. key: '0-0-0',
  1400. },
  1401. {
  1402. label: 'Shanghai',
  1403. value: 'Shanghai',
  1404. key: '0-0-1',
  1405. disabled: true,
  1406. },
  1407. ],
  1408. },
  1409. {
  1410. label: 'Japan',
  1411. value: 'Japan',
  1412. key: '0-1',
  1413. children: [
  1414. {
  1415. label: 'Osaka',
  1416. value: 'Osaka',
  1417. key: '0-1-0',
  1418. },
  1419. ],
  1420. },
  1421. ],
  1422. },
  1423. ]}
  1424. defaultValue={['Shanghai']}
  1425. multiple
  1426. defaultExpandAll
  1427. disableStrictly
  1428. />
  1429. <br />
  1430. <span> disable shanghai </span>
  1431. <Tree
  1432. treeData={[
  1433. {
  1434. label: 'Asia',
  1435. value: 'Asia',
  1436. key: '0',
  1437. children: [
  1438. {
  1439. label: 'China',
  1440. value: 'China',
  1441. key: '0-0',
  1442. children: [
  1443. {
  1444. label: 'Beijing',
  1445. value: 'Beijing',
  1446. key: '0-0-0',
  1447. },
  1448. {
  1449. label: 'Chengdu',
  1450. value: 'Chengdu',
  1451. key: '0-0-2',
  1452. },
  1453. {
  1454. label: 'Shanghai',
  1455. value: 'Shanghai',
  1456. key: '0-0-1',
  1457. disabled: true,
  1458. },
  1459. ],
  1460. },
  1461. {
  1462. label: 'Japan',
  1463. value: 'Japan',
  1464. key: '0-1',
  1465. children: [
  1466. {
  1467. label: 'Osaka',
  1468. value: 'Osaka',
  1469. key: '0-1-0',
  1470. },
  1471. ],
  1472. },
  1473. ],
  1474. },
  1475. ]}
  1476. multiple
  1477. defaultExpandAll
  1478. disableStrictly
  1479. />
  1480. <span> disable China(checked) - Shanghai </span>
  1481. <Tree
  1482. treeData={[
  1483. {
  1484. label: 'Asia',
  1485. value: 'Asia',
  1486. key: '0',
  1487. children: [
  1488. {
  1489. label: 'China',
  1490. value: 'China',
  1491. key: '0-0',
  1492. disabled: true,
  1493. children: [
  1494. {
  1495. label: 'Beijing',
  1496. value: 'Beijing',
  1497. key: '0-0-0',
  1498. },
  1499. {
  1500. label: 'Shanghai',
  1501. value: 'Shanghai',
  1502. key: '0-0-1',
  1503. disabled: true,
  1504. },
  1505. ],
  1506. },
  1507. {
  1508. label: 'Japan',
  1509. value: 'Japan',
  1510. key: '0-1',
  1511. children: [
  1512. {
  1513. label: 'Osaka',
  1514. value: 'Osaka',
  1515. key: '0-1-0',
  1516. },
  1517. ],
  1518. },
  1519. ],
  1520. },
  1521. ]}
  1522. defaultValue="China"
  1523. multiple
  1524. defaultExpandAll
  1525. disableStrictly
  1526. />
  1527. <span> disable China </span>
  1528. <Tree
  1529. treeData={[
  1530. {
  1531. label: 'Asia',
  1532. value: 'Asia',
  1533. key: '0',
  1534. children: [
  1535. {
  1536. label: 'China',
  1537. value: 'China',
  1538. key: '0-0',
  1539. disabled: true,
  1540. children: [
  1541. {
  1542. label: 'Beijing',
  1543. value: 'Beijing',
  1544. key: '0-0-0',
  1545. },
  1546. {
  1547. label: 'Shanghai',
  1548. value: 'Shanghai',
  1549. key: '0-0-1',
  1550. },
  1551. ],
  1552. },
  1553. {
  1554. label: 'Japan',
  1555. value: 'Japan',
  1556. key: '0-1',
  1557. children: [
  1558. {
  1559. label: 'Osaka',
  1560. value: 'Osaka',
  1561. key: '0-1-0',
  1562. },
  1563. ],
  1564. },
  1565. ],
  1566. },
  1567. ]}
  1568. multiple
  1569. defaultExpandAll
  1570. disableStrictly
  1571. />
  1572. </>
  1573. );
  1574. };
  1575. export const DisableStrictly = () => <DisabledStrictly />;
  1576. DisableStrictly.story = {
  1577. name: 'disableStrictly',
  1578. };
  1579. const ActionTree = () => {
  1580. let initData = [
  1581. {
  1582. label: 'Asia',
  1583. value: 'Asia',
  1584. key: 'asia',
  1585. children: [
  1586. {
  1587. label: 0,
  1588. value: `${0}`,
  1589. key: `${0}`,
  1590. },
  1591. {
  1592. label: 1,
  1593. value: `${1}`,
  1594. key: `${1}`,
  1595. },
  1596. {
  1597. label: 2,
  1598. value: `${2}`,
  1599. key: `${2}`,
  1600. },
  1601. {
  1602. label: 3,
  1603. value: `${3}`,
  1604. key: `${3}`,
  1605. },
  1606. {
  1607. label: 4,
  1608. value: `${4}`,
  1609. key: `${4}`,
  1610. },
  1611. ],
  1612. },
  1613. ];
  1614. const [data, setData] = useState(initData);
  1615. const remove = key => {
  1616. let ind = data[0].children.findIndex(item => item.key === key);
  1617. if (ind >= 0) {
  1618. let items = cloneDeep(data);
  1619. items[0].children.splice(ind, 1);
  1620. setData(items);
  1621. }
  1622. };
  1623. return (
  1624. <Tree
  1625. treeData={cloneDeep(data)}
  1626. renderLabel={(label, data) => (
  1627. <div>
  1628. {label}
  1629. <Button onClick={() => remove(data.key)}>remove</Button>
  1630. </div>
  1631. )}
  1632. />
  1633. );
  1634. };
  1635. export const DeleteOrAddChildNode = () => <ActionTree />;
  1636. DeleteOrAddChildNode.story = {
  1637. name: 'Delete or Add Child Node',
  1638. };
  1639. const MutipleHLTree = () => {
  1640. const [selected, setSelected] = useState(new Set());
  1641. const [selectedThroughParent, setSelectedThroughParent] = useState(new Set());
  1642. const findDescendantKeys = node => {
  1643. let res = [node.key];
  1644. const findChild = item => {
  1645. if (!item) return;
  1646. const { children } = item;
  1647. if (children && children.length) {
  1648. children.forEach(child => {
  1649. res.push(child.key);
  1650. findChild(child);
  1651. });
  1652. }
  1653. };
  1654. findChild(node);
  1655. return res;
  1656. };
  1657. const handleSelect = (key, bool, node) => {
  1658. setSelected(new Set([key]));
  1659. const descendantKeys = findDescendantKeys(node);
  1660. setSelectedThroughParent(new Set(descendantKeys));
  1661. };
  1662. const renderLabel = ({ className, data, onClick, expandIcon }) => {
  1663. const { label, icon, key } = data;
  1664. const isLeaf = !(data.children && data.children.length);
  1665. const style = {
  1666. backgroundColor: selected.has(key)
  1667. ? 'rgba(var(--semi-blue-0), 1)'
  1668. : selectedThroughParent.has(key)
  1669. ? 'rgba(var(--semi-blue-0), .5)'
  1670. : 'transparent',
  1671. };
  1672. return (
  1673. <li className={className} role="treeitem" onClick={onClick} style={style}>
  1674. {isLeaf ? null : expandIcon}
  1675. {icon ? icon : null}
  1676. <span>{label}</span>
  1677. </li>
  1678. );
  1679. };
  1680. const treeStyle = {
  1681. width: 260,
  1682. height: 420,
  1683. border: '1px solid var(--semi-color-border)',
  1684. };
  1685. return (
  1686. <Tree
  1687. treeData={treeData1}
  1688. renderFullLabel={renderLabel}
  1689. onSelect={handleSelect}
  1690. style={treeStyle}
  1691. />
  1692. );
  1693. };
  1694. export const RenderOuterLable = () => <MutipleHLTree />;
  1695. RenderOuterLable.story = {
  1696. name: 'renderOuterLable',
  1697. };
  1698. export const TreeWithoutValueProps = () => (
  1699. <Tree
  1700. treeData={treeDataWithoutValue}
  1701. value="meiguo"
  1702. defaultExpandAll
  1703. onChange={(...args) => console.log(args)}
  1704. />
  1705. );
  1706. TreeWithoutValueProps.story = {
  1707. name: 'tree without value props',
  1708. };
  1709. const DnDTree = () => {
  1710. const initialData = [
  1711. {
  1712. label: 'Asia',
  1713. value: 'Asia',
  1714. key: '0',
  1715. children: [
  1716. {
  1717. label: 'China',
  1718. value: 'China',
  1719. key: '0-0',
  1720. children: [
  1721. {
  1722. label: 'Beijing',
  1723. value: 'Beijing',
  1724. key: '0-0-0',
  1725. },
  1726. {
  1727. label: 'Shanghai',
  1728. value: 'Shanghai',
  1729. key: '0-0-1',
  1730. },
  1731. ],
  1732. },
  1733. {
  1734. label: 'Japan',
  1735. value: 'Japan',
  1736. key: '0-1',
  1737. children: [
  1738. {
  1739. label: 'Osaka',
  1740. value: 'Osaka',
  1741. key: '0-1-0',
  1742. },
  1743. ],
  1744. },
  1745. ],
  1746. },
  1747. {
  1748. label: 'North America',
  1749. value: 'North America',
  1750. key: '1',
  1751. children: [
  1752. {
  1753. label: 'United States',
  1754. value: 'United States',
  1755. key: '1-0',
  1756. },
  1757. {
  1758. label: 'Canada',
  1759. value: 'Canada',
  1760. key: '1-1',
  1761. },
  1762. ],
  1763. },
  1764. {
  1765. label: 'Europe',
  1766. value: 'Europe',
  1767. key: '2',
  1768. },
  1769. ];
  1770. const [treeData, setTreeData] = useState(initialData);
  1771. // const [expandedKeys, setExpandedKeys] = useState(['zhongguo']);
  1772. function onDragEnter(info) {
  1773. console.log(info);
  1774. // if in controlled expandedKeys mode
  1775. // setExpandedKeys(info.expandedKeys)
  1776. }
  1777. function onDrop(info) {
  1778. const { dropToGap, node, dragNode } = info;
  1779. const dropKey = node.key;
  1780. const dragKey = dragNode.key;
  1781. const dropPos = node.pos.split('-');
  1782. const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
  1783. const data = [...treeData];
  1784. const loop = (data, key, callback) => {
  1785. data.forEach((item, ind, arr) => {
  1786. if (item.key === key) return callback(item, ind, arr);
  1787. if (item.children) return loop(item.children, key, callback);
  1788. });
  1789. };
  1790. let dragObj;
  1791. loop(data, dragKey, (item, ind, arr) => {
  1792. arr.splice(ind, 1);
  1793. dragObj = item;
  1794. });
  1795. if (!dropToGap) {
  1796. // inset into the dropPosition
  1797. loop(data, dropKey, (item, ind, arr) => {
  1798. item.children = item.children || [];
  1799. item.children.push(dragObj);
  1800. });
  1801. } else if (dropPosition === 1 && node.children && node.expanded) {
  1802. // has children && expanded and drop into the node bottom gap
  1803. // insert to the top 这里我们添加在头部,可以是任意位置
  1804. loop(data, dropKey, item => {
  1805. item.children = item.children || [];
  1806. item.children.unshift(dragObj);
  1807. });
  1808. } else {
  1809. let dropNodeInd;
  1810. let dropNodePosArr;
  1811. loop(data, dropKey, (item, ind, arr) => {
  1812. dropNodePosArr = arr;
  1813. dropNodeInd = ind;
  1814. });
  1815. if (dropPosition === -1) {
  1816. // insert to top
  1817. dropNodePosArr.splice(dropNodeInd, 0, dragObj);
  1818. } else {
  1819. // insert to bottom
  1820. dropNodePosArr.splice(dropNodeInd + 1, 0, dragObj);
  1821. }
  1822. }
  1823. setTreeData(data);
  1824. }
  1825. return (
  1826. <Tree
  1827. treeData={treeData}
  1828. draggable
  1829. //expandedKeys={expandedKeys}
  1830. onDragEnter={onDragEnter}
  1831. onDrop={onDrop}
  1832. />
  1833. );
  1834. };
  1835. export const DraggableTree = () => <DnDTree />;
  1836. DraggableTree.story = {
  1837. name: 'draggable Tree',
  1838. };
  1839. const TestTree = () => {
  1840. return (
  1841. <Tree
  1842. treeData={testData}
  1843. // motion={false}
  1844. style={{ height: '100%' }}
  1845. filterTreeNode
  1846. expandAction="click"
  1847. showFilteredOnly
  1848. />
  1849. );
  1850. };
  1851. export const Draggable = () => <TestTree />;
  1852. Draggable.story = {
  1853. name: 'draggable',
  1854. };
  1855. export const RenderFullLabelWithDraggable = () => {
  1856. const [selected, setSelected] = useState(new Set());
  1857. const [selectedThroughParent, setSelectedThroughParent] = useState(new Set());
  1858. const defaultTreeData = [
  1859. {
  1860. label: '黑色固定按钮',
  1861. key: 'fix-btn-0',
  1862. },
  1863. {
  1864. label: '模块',
  1865. key: 'module-0',
  1866. children: [
  1867. {
  1868. label: '可自由摆放的组件',
  1869. key: 'free-compo-0',
  1870. },
  1871. {
  1872. label: '分栏容器',
  1873. key: 'split-col-0',
  1874. children: [
  1875. {
  1876. label: '按钮组件',
  1877. key: 'btn-0',
  1878. },
  1879. {
  1880. label: '按钮组件',
  1881. key: 'btn-1',
  1882. },
  1883. ],
  1884. },
  1885. ],
  1886. },
  1887. {
  1888. label: '模块',
  1889. key: 'module-1',
  1890. children: [
  1891. {
  1892. label: '自定义组件',
  1893. key: 'cus-0',
  1894. },
  1895. ],
  1896. },
  1897. ];
  1898. const [treeData, setTreeData] = useState(defaultTreeData);
  1899. const onDrop = info => {
  1900. const { dropToGap, node, dragNode } = info;
  1901. const dropKey = node.key;
  1902. const dragKey = dragNode.key;
  1903. const dropPos = node.pos.split('-');
  1904. const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
  1905. const data = [...treeData];
  1906. const loop = (data, key, callback) => {
  1907. data.forEach((item, ind, arr) => {
  1908. if (item.key === key) return callback(item, ind, arr);
  1909. if (item.children) return loop(item.children, key, callback);
  1910. });
  1911. };
  1912. let dragObj;
  1913. loop(data, dragKey, (item, ind, arr) => {
  1914. arr.splice(ind, 1);
  1915. dragObj = item;
  1916. });
  1917. if (!dropToGap) {
  1918. loop(data, dropKey, (item, ind, arr) => {
  1919. item.children = item.children || [];
  1920. item.children.push(dragObj);
  1921. });
  1922. } else if (dropPosition === 1 && node.children && node.expanded) {
  1923. loop(data, dropKey, item => {
  1924. item.children = item.children || [];
  1925. item.children.unshift(dragObj);
  1926. });
  1927. } else {
  1928. let dropNodeInd;
  1929. let dropNodePosArr;
  1930. loop(data, dropKey, (item, ind, arr) => {
  1931. dropNodePosArr = arr;
  1932. dropNodeInd = ind;
  1933. });
  1934. if (dropPosition === -1) {
  1935. dropNodePosArr.splice(dropNodeInd, 0, dragObj);
  1936. } else {
  1937. dropNodePosArr.splice(dropNodeInd + 1, 0, dragObj);
  1938. }
  1939. }
  1940. setTreeData(data);
  1941. };
  1942. const findDescendantKeys = node => {
  1943. let res = [node.key];
  1944. const findChild = item => {
  1945. if (!item) return;
  1946. const { children } = item;
  1947. if (children && children.length) {
  1948. children.forEach(child => {
  1949. res.push(child.key);
  1950. findChild(child);
  1951. });
  1952. }
  1953. };
  1954. findChild(node);
  1955. return res;
  1956. };
  1957. const handleSelect = (key, bool, node) => {
  1958. setSelected(new Set([key]));
  1959. const descendantKeys = findDescendantKeys(node);
  1960. setSelectedThroughParent(new Set(descendantKeys));
  1961. };
  1962. const renderLabel = ({ className, data, onClick, expandIcon }) => {
  1963. const { label, icon, key } = data;
  1964. const isLeaf = !(data.children && data.children.length);
  1965. const style = {
  1966. backgroundColor: selected.has(key)
  1967. ? 'rgba(var(--semi-blue-0), 1)'
  1968. : selectedThroughParent.has(key)
  1969. ? 'rgba(var(--semi-blue-0), .5)'
  1970. : 'transparent',
  1971. };
  1972. return (
  1973. <li className={className} role="treeitem" onClick={onClick} style={style}>
  1974. {isLeaf ? <span style={{ width: 24 }}></span> : expandIcon}
  1975. {icon ? icon : null}
  1976. <span>{label}</span>
  1977. </li>
  1978. );
  1979. };
  1980. const treeStyle = {
  1981. height: 420,
  1982. border: '1px solid var(--semi-color-border)',
  1983. };
  1984. return (
  1985. <Tree
  1986. treeData={treeData}
  1987. draggable
  1988. onDrop={onDrop}
  1989. renderFullLabel={renderLabel}
  1990. onSelect={handleSelect}
  1991. style={treeStyle}
  1992. defaultExpandAll
  1993. />
  1994. );
  1995. };
  1996. RenderFullLabelWithDraggable.story = {
  1997. name: 'renderFullLabel with draggable',
  1998. };