cascader.stories.js 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452
  1. import React, { useState } from 'react';
  2. import CustomTrigger from './CustomTrigger';
  3. import { Button, Typography, Toast, Cascader } from '../../index';
  4. const { Text } = Typography;
  5. export default {
  6. title: 'Cascader',
  7. parameters: {
  8. chromatic: { disableSnapshot: true },
  9. },
  10. }
  11. export {
  12. CustomTrigger
  13. };
  14. const treeData1 = [
  15. {
  16. label: 'Node1',
  17. value: '0-0',
  18. children: [
  19. {
  20. label: 'Child Node1',
  21. value: '0-0-1',
  22. disabled: true,
  23. },
  24. {
  25. label: 'Child Node2',
  26. value: '0-0-2',
  27. },
  28. ],
  29. },
  30. {
  31. label: 'Node2',
  32. value: '0-1',
  33. },
  34. ];
  35. const treeData2 = [
  36. {
  37. label: '亚洲',
  38. value: 'yazhou',
  39. children: [
  40. {
  41. label: '中国',
  42. value: 'zhongguo',
  43. children: [
  44. {
  45. label: '北京',
  46. value: 'beijing',
  47. },
  48. {
  49. label: '上海',
  50. value: 'shanghai',
  51. },
  52. ],
  53. },
  54. {
  55. label: '日本',
  56. value: 'riben',
  57. disabled: true,
  58. children: [
  59. {
  60. label: '大阪',
  61. value: 'daban',
  62. },
  63. ],
  64. },
  65. ],
  66. },
  67. {
  68. label: '北美洲',
  69. value: 'beimeizhou',
  70. children: [
  71. {
  72. label: '美国',
  73. value: 'meiguo',
  74. },
  75. {
  76. label: '加拿大',
  77. value: 'jianada',
  78. },
  79. ],
  80. },
  81. ];
  82. const treeData3 = [
  83. {
  84. label: '亚洲',
  85. value: 'yazhou',
  86. children: [
  87. {
  88. label: '中国',
  89. value: 'zhongguo',
  90. children: [
  91. {
  92. label: '北京',
  93. value: 'beijing',
  94. },
  95. {
  96. label: '上海',
  97. value: 'shanghai',
  98. },
  99. ],
  100. },
  101. {
  102. label: '日本',
  103. value: 'riben',
  104. children: [
  105. {
  106. label: '大阪',
  107. value: 'daban',
  108. },
  109. ],
  110. },
  111. ],
  112. },
  113. ];
  114. const treeData4 = [
  115. {
  116. label: '浙江省',
  117. value: 'zhejiang',
  118. children: [
  119. {
  120. label: '杭州市',
  121. value: 'hangzhou',
  122. children: [
  123. {
  124. label: '西湖区',
  125. value: 'xihu',
  126. },
  127. {
  128. label: '萧山区',
  129. value: 'xiaoshan',
  130. },
  131. {
  132. label: '临安区',
  133. value: 'linan',
  134. },
  135. ],
  136. },
  137. {
  138. label: '宁波市',
  139. value: 'ningbo',
  140. children: [
  141. {
  142. label: '海曙区',
  143. value: 'haishu',
  144. },
  145. {
  146. label: '江北区',
  147. value: 'jiangbei',
  148. },
  149. ],
  150. },
  151. ],
  152. },
  153. ];
  154. const treeOrder = [
  155. {
  156. label: '-1',
  157. value: '0-0',
  158. key: '-1',
  159. children: [
  160. {
  161. label: 'Child Node1',
  162. value: '0-0-1',
  163. key: '0-0-1',
  164. },
  165. {
  166. label: 'Child Node2',
  167. value: '0-0-2',
  168. key: '0-0-2',
  169. },
  170. ],
  171. },
  172. {
  173. label: '1',
  174. value: '0-1',
  175. key: '1',
  176. },
  177. ];
  178. const longTreeData = [
  179. {
  180. label: 'udghajsasndanm,',
  181. value: 'A',
  182. children: [
  183. {
  184. label: 'Bsasfads',
  185. value: 'B',
  186. children: [
  187. {
  188. label: 'C',
  189. value: 'C',
  190. children: [
  191. {
  192. label: 'D',
  193. value: 'D',
  194. children: [
  195. {
  196. label: 'E',
  197. value: 'E',
  198. children: [
  199. {
  200. label: 'F',
  201. value: 'F',
  202. }
  203. ]
  204. }
  205. ]
  206. }
  207. ]
  208. }
  209. ],
  210. }
  211. ]
  212. }
  213. ];
  214. const treedataWithNodeLabel = [
  215. {
  216. label: '浙江省',
  217. value: 'zhejiang',
  218. children: [
  219. {
  220. label: '杭州市',
  221. value: 'hangzhou',
  222. children: [
  223. {
  224. label: '西湖市区',
  225. value: 'xihu',
  226. },
  227. {
  228. label: '萧山区',
  229. value: 'xiaoshan',
  230. },
  231. {
  232. label: '临安区',
  233. value: 'linan',
  234. },
  235. ],
  236. },
  237. {
  238. label: <strong>宁波市</strong>,
  239. value: 'ningbo',
  240. children: [
  241. {
  242. label: '海曙区',
  243. value: 'haishu',
  244. },
  245. {
  246. label: '江北区',
  247. value: 'jiangbei',
  248. }
  249. ]
  250. },
  251. ],
  252. }
  253. ];
  254. export const _Cascader = () => {
  255. return (
  256. <div>
  257. <Cascader
  258. style={{ width: 300 }}
  259. treeData={treeData1}
  260. placeholder="Please select"
  261. motion={false}
  262. />
  263. <br />
  264. <br />
  265. <Cascader
  266. style={{ width: 300 }}
  267. treeData={treeData1}
  268. placeholder="Multiple select"
  269. multiple
  270. motion={false}
  271. />
  272. <br />
  273. <br />
  274. <Cascader
  275. style={{ width: 300 }}
  276. treeData={treeData1}
  277. placeholder="Multiple select enableLeafClick"
  278. multiple
  279. enableLeafClick
  280. motion={false}
  281. />
  282. <br />
  283. <br />
  284. <Cascader
  285. style={{ width: 300 }}
  286. treeData={[]}
  287. motion={false}
  288. placeholder="Please select"
  289. // defaultOpen={true}
  290. />
  291. </div>
  292. );
  293. };
  294. export const ChangeOnSelect = () => {
  295. return (
  296. <div>
  297. <Cascader
  298. style={{ width: 300 }}
  299. treeData={treeData2}
  300. placeholder="Please select"
  301. changeOnSelect={true}
  302. />
  303. </div>
  304. );
  305. };
  306. export const Searchable = () => {
  307. return (
  308. <div>
  309. <Cascader
  310. style={{ width: 300 }}
  311. treeData={treeData2}
  312. placeholder="Please select"
  313. filterTreeNode
  314. motion={false}
  315. />
  316. <br />
  317. <br />
  318. <Cascader
  319. style={{ width: 300 }}
  320. treeData={treeData2}
  321. placeholder="Please select"
  322. filterTreeNode
  323. changeOnSelect
  324. allowHalfPath
  325. />
  326. <br />
  327. <br />
  328. <Cascader
  329. style={{ width: 300 }}
  330. treeData={treeData2}
  331. placeholder="Please select"
  332. filterTreeNode
  333. filterLeafOnly={false}
  334. onChange={e => console.log(e)}
  335. />
  336. <br />
  337. <br />
  338. <div>fix-1449,当 label 为 ReactNode 时,搜索显示结果[object object]</div>
  339. <Cascader
  340. style={{ width: 300 }}
  341. treeData={treedataWithNodeLabel}
  342. placeholder="宁波为 ReactNode"
  343. filterTreeNode
  344. />
  345. <br />
  346. <br />
  347. <div>
  348. filterTreeNode=false,且 label 为 ReactNode
  349. 时,配合displayRender使用,使得回显到input的内容符合预期
  350. </div>
  351. <Cascader
  352. style={{ width: 300 }}
  353. treeData={treedataWithNodeLabel}
  354. placeholder="自定义回填时显示数据的格式"
  355. displayRender={list =>
  356. list.map((v, i) => {
  357. return list.length - 1 === i ? (
  358. <React.Fragment key={i}>{v}</React.Fragment>
  359. ) : (
  360. <React.Fragment key={i}>{v} / </React.Fragment>
  361. );
  362. })
  363. }
  364. defaultValue={['zhejiang', 'ningbo', 'jiangbei']}
  365. />
  366. <br />
  367. <br />
  368. <div>
  369. v2.5 起,filterTreeNode=false,且 label 为 ReactNode
  370. 时,无配合displayRender 使用,回显到input的内容也是符合预期
  371. </div>
  372. <Cascader
  373. style={{ width: 300 }}
  374. treeData={treedataWithNodeLabel}
  375. placeholder="宁波为 ReactNode"
  376. defaultValue={['zhejiang', 'ningbo', 'jiangbei']}
  377. />
  378. </div>
  379. );
  380. };
  381. Searchable.parameters = {
  382. chromatic: { disableSnapshot: false },
  383. }
  384. export const Disabled = () => {
  385. return (
  386. <div>
  387. <Cascader
  388. style={{ width: 300 }}
  389. treeData={treeData2}
  390. placeholder="Please select"
  391. filterTreeNode
  392. disabled
  393. />
  394. <br /><br />
  395. <Cascader
  396. defaultValue={['yazhou', 'zhongguo']}
  397. style={{ width: 300 }}
  398. treeData={treeData2}
  399. multiple
  400. filterTreeNode
  401. disabled
  402. />
  403. <br /><br />
  404. <Cascader
  405. defaultValue={['yazhou', 'zhongguo']}
  406. style={{ width: 300 }}
  407. treeData={treeData2}
  408. multiple
  409. disabled
  410. />
  411. </div>
  412. );
  413. };
  414. Disabled.parameters = {
  415. chromatic: { disableSnapshot: false },
  416. }
  417. export const DisabledOption = () => {
  418. return (
  419. <div>
  420. <div>common disabled option</div>
  421. <Cascader style={{ width: 300 }} treeData={treeData2} placeholder="Japan node is disabled" />
  422. <br />
  423. <br />
  424. <div>single selection + defaultValue is disabled option + changeOnSelect</div>
  425. <Cascader
  426. style={{ width: 300 }}
  427. treeData={treeData2}
  428. changeOnSelect
  429. defaultValue={['yazhou', 'riben']}
  430. placeholder="Japan node is disabled"
  431. />
  432. <br />
  433. <br />
  434. <div>
  435. single selection + defaultValue is disabled option + changeOnSelect + filterTreeNode
  436. </div>
  437. <Cascader
  438. style={{ width: 300 }}
  439. treeData={treeData2}
  440. changeOnSelect
  441. filterTreeNode
  442. defaultValue={['yazhou', 'riben']}
  443. placeholder="Japan node is disabled"
  444. />
  445. <br />
  446. <br />
  447. <div>multiple selection + defaultValue is disabled option</div>
  448. <Cascader
  449. multiple
  450. filterTreeNode
  451. style={{ width: 300 }}
  452. treeData={treeData2}
  453. defaultValue={['yazhou', 'riben']}
  454. placeholder="Japan node is disabled"
  455. />
  456. <br />
  457. <br />
  458. <div>multiple selection + filterTreeNode + defaultValue is disabled option</div>
  459. <Cascader
  460. filterTreeNode
  461. multiple
  462. style={{ width: 300 }}
  463. treeData={treeData2}
  464. defaultValue={[
  465. ['yazhou', 'riben'],
  466. ['beimeizhou', 'jianada']
  467. ]}
  468. placeholder="Japan node is disabled"
  469. />
  470. </div>
  471. );
  472. };
  473. export const CustomSearch = () => {
  474. return (
  475. <div>
  476. <Cascader
  477. style={{ width: 300 }}
  478. treeData={treeData2}
  479. placeholder="Please select"
  480. filterTreeNode
  481. treeNodeFilterProp="value"
  482. />
  483. </div>
  484. );
  485. };
  486. export const CustomDisplayProp = () => {
  487. return (
  488. <div>
  489. <Cascader
  490. style={{ width: 300 }}
  491. treeData={treeData2}
  492. placeholder="Please select"
  493. changeOnSelect={true}
  494. displayProp="value"
  495. filterTreeNode
  496. />
  497. </div>
  498. );
  499. };
  500. export const DefaultValue = () => {
  501. return (
  502. <div>
  503. <Cascader
  504. style={{ width: 300 }}
  505. treeData={treeData3}
  506. placeholder="Please select"
  507. defaultValue={['yazhou', 'zhongguo', 'shanghai']}
  508. />
  509. <br />
  510. <br />
  511. <Cascader
  512. style={{ width: 300 }}
  513. treeData={treeData3}
  514. placeholder="Please select"
  515. changeOnSelect
  516. defaultValue={['yazhou']}
  517. />
  518. <br />
  519. <br />
  520. <Cascader
  521. style={{ width: 300 }}
  522. treeData={treeData3}
  523. placeholder="Please select"
  524. changeOnSelect
  525. defaultValue={['yazhou', 'zhongguo']}
  526. filterTreeNode
  527. />
  528. <br />
  529. <br />
  530. <Cascader
  531. style={{ width: 300 }}
  532. treeData={treeData3}
  533. placeholder="Please select"
  534. changeOnSelect
  535. defaultValue={'yazhou'}
  536. filterTreeNode
  537. />
  538. <br />
  539. <br />
  540. <Cascader
  541. style={{ width: 300 }}
  542. treeData={treeData3}
  543. placeholder="Please select"
  544. defaultValue={['yazhou', 'zhongguo']}
  545. filterTreeNode
  546. />
  547. </div>
  548. );
  549. };
  550. export const DefaultValueNotExist = () => {
  551. return (
  552. <>
  553. <Cascader
  554. style={{ width: 300 }}
  555. treeData={treeData3}
  556. placeholder="Please select"
  557. changeOnSelect
  558. defaultValue={'yazhou not exist'}
  559. filterTreeNode
  560. />
  561. <br />
  562. <br />
  563. <Cascader
  564. style={{ width: 300 }}
  565. treeData={treeData3}
  566. placeholder="Please select"
  567. defaultValue={'tokyo not exist'}
  568. />
  569. </>
  570. );
  571. };
  572. class ControlledDemo extends React.Component {
  573. constructor() {
  574. super();
  575. this.state = {
  576. value: [],
  577. };
  578. }
  579. onChange(value) {
  580. this.setState({ value });
  581. }
  582. render() {
  583. const treeData = [
  584. {
  585. label: '浙江省',
  586. value: 'zhejiang',
  587. children: [
  588. {
  589. label: '杭州市',
  590. value: 'hangzhou',
  591. children: [
  592. {
  593. label: '西湖区',
  594. value: 'xihu',
  595. },
  596. {
  597. label: '萧山区',
  598. value: 'xiaoshan',
  599. },
  600. {
  601. label: '临安区',
  602. value: 'linan',
  603. },
  604. ],
  605. },
  606. {
  607. label: '宁波市',
  608. value: 'ningbo',
  609. children: [
  610. {
  611. label: '海曙区',
  612. value: 'haishu',
  613. },
  614. {
  615. label: '江北区',
  616. value: 'jiangbei',
  617. },
  618. ],
  619. },
  620. ],
  621. },
  622. ];
  623. return (
  624. <Cascader
  625. multiple
  626. style={{ width: 300 }}
  627. treeData={treeData}
  628. placeholder="请选择所在地区"
  629. value={this.state.value}
  630. changeOnSelect
  631. filterTreeNode
  632. onChangeWithObject
  633. onChange={e => this.onChange(e)}
  634. />
  635. );
  636. }
  637. }
  638. export const ControlledComponent = () => <ControlledDemo />;
  639. export const CascaderOrderTest = () => {
  640. return (
  641. <div>
  642. <Cascader style={{ width: 300 }} treeData={treeOrder} placeholder="Please select" />
  643. </div>
  644. );
  645. };
  646. export const OnFocusAndOnBlur = () => {
  647. return (
  648. <div>
  649. <Cascader
  650. style={{ width: 300 }}
  651. treeData={treeData1}
  652. placeholder="Please select"
  653. onFocus={(val, e) => console.log('focus', e, val)}
  654. onBlur={(val, e) => console.log('blur', e, val)}
  655. />
  656. </div>
  657. );
  658. };
  659. export const ShowClear = () => {
  660. return (
  661. <div>
  662. <Cascader
  663. style={{ marginLeft: 700, width: 300 }}
  664. treeData={treeData1}
  665. placeholder="Please select"
  666. showClear
  667. filterTreeNode
  668. />
  669. <br />
  670. <br />
  671. <Cascader
  672. style={{ marginLeft: 700, width: 300 }}
  673. treeData={treeData1}
  674. placeholder="Please select when multiple"
  675. multiple
  676. showClear
  677. />
  678. <br />
  679. <br />
  680. <div style={{ marginLeft: 700 }}>
  681. <p>有用户反馈,超长列表点击 showClear 后,dropdown错位。1.30.0-beta.1 fixed</p>
  682. <Cascader
  683. style={{ width: 300 }}
  684. treeData={longTreeData}
  685. placeholder="Please select"
  686. showClear
  687. />
  688. </div>
  689. </div>
  690. );
  691. };
  692. const LoadDataDemo = () => {
  693. const initialData = [
  694. {
  695. label: 'Node1',
  696. value: '0-0',
  697. },
  698. {
  699. label: 'Node2',
  700. value: '0-1',
  701. },
  702. {
  703. label: 'Node3',
  704. value: '0-2',
  705. isLeaf: true,
  706. },
  707. ];
  708. const [data, setData] = useState(initialData);
  709. const updateTreeData = (list, value, children) => {
  710. return list.map(node => {
  711. if (node.value === value) {
  712. return { ...node, children };
  713. }
  714. if (node.children) {
  715. return { ...node, children: updateTreeData(node.children, value, children) };
  716. }
  717. return node;
  718. });
  719. };
  720. const onLoadData = selectedOpt => {
  721. const targetOpt = selectedOpt[selectedOpt.length - 1];
  722. const { label, value } = targetOpt;
  723. return new Promise(resolve => {
  724. if (targetOpt.children) {
  725. resolve();
  726. return;
  727. }
  728. setTimeout(() => {
  729. setData(origin =>
  730. updateTreeData(origin, value, [
  731. {
  732. label: `${label} - 1`,
  733. value: `${label}-1`,
  734. isLeaf: selectedOpt.length > 1,
  735. },
  736. {
  737. label: `${label} - 2`,
  738. value: `${label}-2`,
  739. isLeaf: selectedOpt.length > 1,
  740. },
  741. ])
  742. );
  743. resolve();
  744. }, 1000);
  745. });
  746. };
  747. return (
  748. <Cascader
  749. style={{ width: 300 }}
  750. treeData={data}
  751. loadData={onLoadData}
  752. onChangeWithSelect
  753. placeholder="Please select"
  754. />
  755. );
  756. };
  757. const LoadDataWithReset = () => {
  758. const initialData = [
  759. {
  760. label: 'Node1',
  761. value: '0-0',
  762. },
  763. {
  764. label: 'Node2',
  765. value: '0-1',
  766. },
  767. {
  768. label: 'Node3',
  769. value: '0-2',
  770. isLeaf: true,
  771. },
  772. ];
  773. const [data, setData] = useState(initialData);
  774. const [value, setValue] = useState([]);
  775. const updateTreeData = (list, value, children) => {
  776. return list.map(node => {
  777. if (node.value === value) {
  778. return { ...node, children };
  779. }
  780. if (node.children) {
  781. return { ...node, children: updateTreeData(node.children, value, children) };
  782. }
  783. return node;
  784. });
  785. };
  786. const onLoadData = selectedOpt => {
  787. const targetOpt = selectedOpt[selectedOpt.length - 1];
  788. const { label, value } = targetOpt;
  789. return new Promise(resolve => {
  790. if (targetOpt.children) {
  791. resolve();
  792. return;
  793. }
  794. setTimeout(() => {
  795. setData(origin =>
  796. updateTreeData(origin, value, [
  797. {
  798. label: `${label} - 1`,
  799. value: `${label}-1`,
  800. isLeaf: selectedOpt.length > 1,
  801. },
  802. {
  803. label: `${label} - 2`,
  804. value: `${label}-2`,
  805. isLeaf: selectedOpt.length > 1,
  806. },
  807. ])
  808. );
  809. resolve();
  810. }, 1000);
  811. });
  812. };
  813. return (
  814. <>
  815. <Cascader
  816. style={{ width: 300 }}
  817. treeData={data}
  818. loadData={onLoadData}
  819. value={value}
  820. onChangeWithObject
  821. changeOnSelect
  822. onChange={setValue}
  823. placeholder="Please select"
  824. />
  825. <Button onClick={() => setValue([])}>重置</Button>
  826. </>
  827. );
  828. };
  829. export const LoadData = () => (
  830. <>
  831. <LoadDataDemo />
  832. <br />
  833. <br />
  834. <div>fix:1448,重置失效</div>
  835. <LoadDataWithReset />
  836. </>
  837. );
  838. export const DynamicPlaceholder = () => {
  839. const [isSelect, setSelect] = useState(false);
  840. return (
  841. <>
  842. <Button onClick={() => setSelect(!isSelect)}>Toggle</Button>
  843. <Cascader
  844. style={{ width: 300 }}
  845. treeData={treeData2}
  846. placeholder="Please select"
  847. searchPlaceholder="Search something"
  848. filterTreeNode={isSelect}
  849. showClear
  850. />
  851. </>
  852. );
  853. };
  854. export const FixDedupOnSelect = () => {
  855. return (
  856. <div>
  857. <Cascader
  858. style={{ width: 300 }}
  859. treeData={treeData2}
  860. placeholder="Please select"
  861. onSelect={v => console.log(v)}
  862. />
  863. <Cascader
  864. style={{ width: 300 }}
  865. treeData={treeData2}
  866. placeholder="Please select"
  867. onSelect={v => console.log(v)}
  868. dedupOnSelect={false}
  869. />
  870. </div>
  871. );
  872. };
  873. const slotStyle = {
  874. height: '36px',
  875. display: 'flex',
  876. padding: '0 32px',
  877. alignItems: 'center',
  878. cursor: 'pointer',
  879. borderRadius: '0 0 6px 6px',
  880. };
  881. export const CascaderWithSlot = () => {
  882. return (
  883. <div>
  884. <Cascader
  885. style={{ width: 300 }}
  886. treeData={treeData2}
  887. placeholder="请选择所在地区"
  888. topSlot={<Text style={slotStyle}>选择地区</Text>}
  889. bottomSlot={
  890. <div style={slotStyle}>
  891. <Text>找不大相关选项?</Text>
  892. <Text link>去新建</Text>
  893. </div>
  894. }
  895. />
  896. </div>
  897. );
  898. };
  899. export const CascaderWithMaxTagCountShowRestTagsPopoverRestTagsPopoverProps = () => {
  900. return (
  901. <div>
  902. <Cascader
  903. style={{ width: 300 }}
  904. treeData={treeData4}
  905. placeholder="请选择所在地区"
  906. multiple
  907. maxTagCount={1}
  908. showRestTagsPopover
  909. restTagsPopoverProps={{ position: 'bottom' }}
  910. defaultValue={[
  911. ['zhejiang', 'ningbo', 'haishu'],
  912. ['zhejiang', 'hangzhou', 'xihu'],
  913. ]}
  914. />
  915. </div>
  916. );
  917. };
  918. CascaderWithMaxTagCountShowRestTagsPopoverRestTagsPopoverProps.story = {
  919. name: 'Cascader with maxTagCount/showRestTagsPopover/restTagsPopoverProps',
  920. };
  921. CascaderWithMaxTagCountShowRestTagsPopoverRestTagsPopoverProps.parameters = {
  922. chromatic: { disableSnapshot: false },
  923. }
  924. export const CascaderWithShowNext = () => {
  925. return (
  926. <div>
  927. <Cascader
  928. style={{ width: 300 }}
  929. treeData={treeData4}
  930. placeholder="请选择所在地区"
  931. showNext="hover"
  932. />
  933. </div>
  934. );
  935. };
  936. export const CascaderWithMaxOnExceed = () => {
  937. return (
  938. <div>
  939. <div>普通情况</div>
  940. <Cascader
  941. style={{ width: 300 }}
  942. treeData={treeData4}
  943. placeholder="请选择所在地区"
  944. multiple
  945. max={1}
  946. onExceed={v => {
  947. Toast.warning('exceed max');
  948. console.log(v);
  949. }}
  950. defaultValue={['zhejiang', 'ningbo', 'haishu']}
  951. />
  952. <br />
  953. <br />
  954. <div>defaultValue的数量超过max,则只允许减少到合法,不允许再增加</div>
  955. <Cascader
  956. style={{ width: 300 }}
  957. treeData={treeData4}
  958. placeholder="请选择所在地区"
  959. multiple
  960. max={1}
  961. onExceed={v => {
  962. Toast.warning('exceed max');
  963. console.log(v);
  964. }}
  965. defaultValue={[
  966. ['zhejiang', 'ningbo', 'haishu'],
  967. ['zhejiang', 'hangzhou', 'xihu'],
  968. ]}
  969. />
  970. <br />
  971. <br />
  972. <div>autoMergeValue=false时的情况</div>
  973. <Cascader
  974. style={{ width: 300 }}
  975. treeData={treeData4}
  976. placeholder="请选择所在地区"
  977. multiple
  978. max={2}
  979. autoMergeValue={false}
  980. onExceed={v => {
  981. Toast.warning('exceed max');
  982. console.log(v);
  983. }}
  984. defaultValue={[
  985. ['zhejiang', 'ningbo', 'haishu'],
  986. ['zhejiang', 'hangzhou', 'xihu'],
  987. ]}
  988. />
  989. </div>
  990. );
  991. };
  992. CascaderWithMaxOnExceed.story = {
  993. name: 'Cascader with max/onExceed',
  994. };
  995. CascaderWithMaxOnExceed.parameters = {
  996. chromatic: { disableSnapshot: false },
  997. }
  998. const ControlledLoadDataWithDefaultValue = () => {
  999. const [v, setV] = useState('受控 Value');
  1000. const initialData = [
  1001. {
  1002. label: 'Node1',
  1003. value: '0-0',
  1004. },
  1005. {
  1006. label: 'Node2',
  1007. value: '0-1',
  1008. },
  1009. {
  1010. label: 'Node3',
  1011. value: '0-2',
  1012. isLeaf: true,
  1013. },
  1014. ];
  1015. const [data, setData] = useState(initialData);
  1016. const updateTreeData = (list, value, children) => {
  1017. return list.map(node => {
  1018. if (node.value === value) {
  1019. return { ...node, children };
  1020. }
  1021. if (node.children) {
  1022. return { ...node, children: updateTreeData(node.children, value, children) };
  1023. }
  1024. return node;
  1025. });
  1026. };
  1027. const onLoadData = selectedOpt => {
  1028. const targetOpt = selectedOpt[selectedOpt.length - 1];
  1029. const { label, value } = targetOpt;
  1030. return new Promise(resolve => {
  1031. if (targetOpt.children) {
  1032. resolve();
  1033. return;
  1034. }
  1035. setTimeout(() => {
  1036. setData(origin =>
  1037. updateTreeData(origin, value, [
  1038. {
  1039. label: `${label} - 1`,
  1040. value: `${label}-1`,
  1041. isLeaf: selectedOpt.length > 1,
  1042. },
  1043. {
  1044. label: `${label} - 2`,
  1045. value: `${label}-2`,
  1046. isLeaf: selectedOpt.length > 1,
  1047. },
  1048. ])
  1049. );
  1050. resolve();
  1051. }, 1000);
  1052. });
  1053. };
  1054. return (
  1055. <Cascader
  1056. defaultValue="123"
  1057. value={v}
  1058. onChange={v => setV(v)}
  1059. style={{ width: 300 }}
  1060. treeData={data}
  1061. loadData={onLoadData}
  1062. placeholder="Please select"
  1063. />
  1064. );
  1065. };
  1066. const LoadDataWithDefaultValue = () => {
  1067. const initialData = [
  1068. {
  1069. label: 'Node1',
  1070. value: '0-0',
  1071. },
  1072. {
  1073. label: 'Node2',
  1074. value: '0-1',
  1075. },
  1076. {
  1077. label: 'Node3',
  1078. value: '0-2',
  1079. isLeaf: true,
  1080. },
  1081. ];
  1082. const [data, setData] = useState(initialData);
  1083. const updateTreeData = (list, value, children) => {
  1084. return list.map(node => {
  1085. if (node.value === value) {
  1086. return { ...node, children };
  1087. }
  1088. if (node.children) {
  1089. return { ...node, children: updateTreeData(node.children, value, children) };
  1090. }
  1091. return node;
  1092. });
  1093. };
  1094. const onLoadData = selectedOpt => {
  1095. const targetOpt = selectedOpt[selectedOpt.length - 1];
  1096. const { label, value } = targetOpt;
  1097. return new Promise(resolve => {
  1098. if (targetOpt.children) {
  1099. resolve();
  1100. return;
  1101. }
  1102. setTimeout(() => {
  1103. setData(origin =>
  1104. updateTreeData(origin, value, [
  1105. {
  1106. label: `${label} - 1`,
  1107. value: `${label}-1`,
  1108. isLeaf: selectedOpt.length > 1,
  1109. },
  1110. {
  1111. label: `${label} - 2`,
  1112. value: `${label}-2`,
  1113. isLeaf: selectedOpt.length > 1,
  1114. },
  1115. ])
  1116. );
  1117. resolve();
  1118. }, 1000);
  1119. });
  1120. };
  1121. return (
  1122. <Cascader
  1123. defaultValue="defaultValue"
  1124. style={{ width: 300 }}
  1125. treeData={data}
  1126. loadData={onLoadData}
  1127. showClear
  1128. placeholder="Please select"
  1129. />
  1130. );
  1131. };
  1132. export const LoadDataWithDefaultValueDemo = () => {
  1133. return (
  1134. <div>
  1135. <div>fix-1429,检查defaultValue在异步时是否有异常</div>
  1136. <ControlledLoadDataWithDefaultValue />
  1137. <br />
  1138. <br />
  1139. <LoadDataWithDefaultValue />
  1140. </div>
  1141. );
  1142. };
  1143. LoadDataWithDefaultValueDemo.parameters = {
  1144. chromatic: { disableSnapshot: false },
  1145. }
  1146. export const OnChangeWithObject = () => (
  1147. <>
  1148. <div>单选 + onChangeWithObject + defaultValue 为 string []</div>
  1149. <Cascader
  1150. onChangeWithObject
  1151. style={{ width: 300 }}
  1152. treeData={treeData4}
  1153. placeholder="请选择所在地区"
  1154. defaultValue={['zhejiang', 'hangzhou', 'xihu']}
  1155. />
  1156. <br />
  1157. <br />
  1158. <div>多选 + onChangeWithObject + defaultValue 为 string []</div>
  1159. <Cascader
  1160. multiple
  1161. changeOnSelect
  1162. onChangeWithObject
  1163. style={{ width: 300 }}
  1164. treeData={treeData4}
  1165. placeholder="请选择所在地区"
  1166. defaultValue={'zhejiang'}
  1167. />
  1168. <br />
  1169. <br />
  1170. <div>单选 + onChangeWithObject + defaultValue 为 object []</div>
  1171. <Cascader
  1172. onChangeWithObject
  1173. changeOnSelect
  1174. style={{ width: 300 }}
  1175. treeData={treeData2}
  1176. placeholder="请选择所在地区"
  1177. defaultValue={{
  1178. label: '北美洲',
  1179. value: 'beimeizhou',
  1180. children: [
  1181. {
  1182. label: '美国',
  1183. value: 'meiguo',
  1184. },
  1185. {
  1186. label: '加拿大',
  1187. value: 'jianada',
  1188. },
  1189. ],
  1190. }}
  1191. />
  1192. <br />
  1193. <br />
  1194. <div>多选 + onChangeWithObject + defaultValue 为 object []</div>
  1195. <Cascader
  1196. multiple
  1197. onChangeWithObject
  1198. style={{ width: 300 }}
  1199. treeData={treeData2}
  1200. placeholder="请选择所在地区"
  1201. defaultValue={{
  1202. label: '北美洲',
  1203. value: 'beimeizhou',
  1204. children: [
  1205. {
  1206. label: '美国',
  1207. value: 'meiguo',
  1208. },
  1209. {
  1210. label: '加拿大',
  1211. value: 'jianada',
  1212. },
  1213. ],
  1214. }}
  1215. />
  1216. </>
  1217. );
  1218. export const LeafOnly = () => {
  1219. const [value, setValue] = useState([])
  1220. return (
  1221. <div>
  1222. <div>autoMergeValue=false,leafOnly=false</div>
  1223. <Cascader
  1224. style={{ width: 300 }}
  1225. treeData={treeData4}
  1226. placeholder="请选择所在地区"
  1227. multiple
  1228. autoMergeValue={false}
  1229. leafOnly={false}
  1230. defaultValue={['zhejiang']}
  1231. />
  1232. <br />
  1233. <br />
  1234. <div>autoMergeValue=false,leafOnly=true, leafOnly生效</div>
  1235. <Cascader
  1236. style={{ width: 300 }}
  1237. treeData={treeData4}
  1238. placeholder="请选择所在地区"
  1239. multiple
  1240. autoMergeValue={false}
  1241. leafOnly={true}
  1242. defaultValue={['zhejiang']}
  1243. />
  1244. <br />
  1245. <br />
  1246. <div>受控,autoMergeValue=false,leafOnly=true, leafOnly生效</div>
  1247. <Cascader
  1248. style={{ width: 300 }}
  1249. treeData={treeData4}
  1250. placeholder="请选择所在地区"
  1251. multiple
  1252. onChange={v=>{
  1253. console.log(v);
  1254. setValue(v)
  1255. }}
  1256. autoMergeValue={false}
  1257. leafOnly={true}
  1258. value={value}
  1259. />
  1260. <br />
  1261. <br />
  1262. <div>受控 onChangeWithObject, autoMergeValue=false,leafOnly=true, leafOnly生效</div>
  1263. <Cascader
  1264. style={{ width: 300 }}
  1265. treeData={treeData4}
  1266. placeholder="请选择所在地区"
  1267. multiple
  1268. onChange={v=>{
  1269. console.log(v);
  1270. setValue(v)
  1271. }}
  1272. onChangeWithObject
  1273. autoMergeValue={false}
  1274. leafOnly={true}
  1275. value={value}
  1276. />
  1277. <br />
  1278. <br />
  1279. <div>autoMergeValue=true,leafOnly=false</div>
  1280. <Cascader
  1281. style={{ width: 300 }}
  1282. treeData={treeData4}
  1283. placeholder="请选择所在地区"
  1284. multiple
  1285. autoMergeValue={true}
  1286. leafOnly={false}
  1287. defaultValue={['zhejiang']}
  1288. />
  1289. <br />
  1290. <br />
  1291. <br />
  1292. <div>autoMergeValue=true,leafOnly=true</div>
  1293. <Cascader
  1294. style={{ width: 300 }}
  1295. treeData={treeData4}
  1296. placeholder="请选择所在地区"
  1297. multiple
  1298. autoMergeValue={true}
  1299. leafOnly={true}
  1300. defaultValue={['zhejiang']}
  1301. />
  1302. </div>
  1303. );
  1304. }
  1305. export const DynamicTreeData = () => {
  1306. const [treeDataDemo1,setTreeData1]=useState(treeData2);
  1307. const [treeDataDemo2,setTreeData2]=useState(treeData2);
  1308. const [treeDataDemo3,setTreeData3]=useState(treeData2);
  1309. const [treeDataDemo4,setTreeData4]=useState(treeData2);
  1310. const [treeDataDemo5,setTreeData5]=useState(treeData2);
  1311. const [value3,setValue3]=useState();
  1312. const [value4,setValue4]=useState();
  1313. return (
  1314. <div>
  1315. <div>多选 + 动态更新 tree</div>
  1316. <Cascader
  1317. style={{ width: 300 }}
  1318. treeData={treeDataDemo1}
  1319. multiple
  1320. placeholder="请选择所在地区"
  1321. />
  1322. <Button onClick={()=>{setTreeData1(treeData3)}}>改变treeData</Button>
  1323. <br />
  1324. <br />
  1325. <div>单选 + 动态更新 tree</div>
  1326. <Cascader
  1327. style={{ width: 300 }}
  1328. treeData={treeDataDemo2}
  1329. placeholder="请选择所在地区"
  1330. />
  1331. <Button onClick={()=>{setTreeData2(treeData3)}}>改变treeData</Button>
  1332. <br />
  1333. <br />
  1334. <div>多选 + 动态更新 tree + 受控</div>
  1335. <Cascader
  1336. style={{ width: 300 }}
  1337. treeData={treeDataDemo3}
  1338. multiple
  1339. value={value3}
  1340. onChange={v=>{
  1341. console.log(v);
  1342. setValue3(v);
  1343. }}
  1344. placeholder="请选择所在地区"
  1345. />
  1346. <Button onClick={()=>{setTreeData3(treeData3)}}>改变treeData</Button>
  1347. <br />
  1348. <br />
  1349. <div>单选 + 动态更新 tree + 受控</div>
  1350. <Cascader
  1351. style={{ width: 300 }}
  1352. treeData={treeDataDemo4}
  1353. value={value4}
  1354. onChange={v=>{
  1355. console.log(v);
  1356. setValue4(v);
  1357. }}
  1358. placeholder="请选择所在地区"
  1359. />
  1360. <Button onClick={()=>{setTreeData4(treeData3)}}>改变treeData</Button>
  1361. <br />
  1362. <br />
  1363. <div>多选 + 动态更新 tree + defaultValue 为亚洲</div>
  1364. <Cascader
  1365. style={{ width: 300 }}
  1366. treeData={treeDataDemo5}
  1367. multiple
  1368. defaultValue='yazhou'
  1369. placeholder="请选择所在地区"
  1370. />
  1371. <Button onClick={()=>{setTreeData5(treeData3)}}>改变treeData</Button>
  1372. <br />
  1373. <br />
  1374. </div>
  1375. );
  1376. }
  1377. export const SuperLongList = () => {
  1378. let treeData = new Array(100).fill().map(() => ({ label: '浙江省', value: 'zhejiang' }));
  1379. treeData.push({ label: '到底啦', value: 'bottom' })
  1380. return (
  1381. <Cascader
  1382. style={{ width: 300 }}
  1383. treeData={treeData}
  1384. placeholder="请选择所在地区"
  1385. onListScroll={()=>{console.log(123)}}
  1386. />
  1387. );
  1388. };