cascader.stories.js 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495
  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 filterTreeNodeAndDisplayRender = () => {
  385. return (
  386. <>
  387. <div>
  388. filterTreeNode=true,配合displayRender 使用,回显到input的内容也是符合预期
  389. </div>
  390. <Cascader
  391. filterTreeNode
  392. style={{ width: 300 }}
  393. treeData={treeData4}
  394. placeholder="自定义回填时显示数据的格式"
  395. defaultValue={['zhejiang', 'ningbo', 'jiangbei']}
  396. displayRender={(item) => {
  397. console.log('item', item);
  398. return <div>
  399. {'已选择:' + item.join(' -> ')}
  400. </div>;}}
  401. />
  402. </>
  403. );
  404. };
  405. export const Disabled = () => {
  406. return (
  407. <div>
  408. <Cascader
  409. style={{ width: 300 }}
  410. treeData={treeData2}
  411. placeholder="Please select"
  412. filterTreeNode
  413. disabled
  414. />
  415. <br /><br />
  416. <Cascader
  417. defaultValue={['yazhou', 'zhongguo']}
  418. style={{ width: 300 }}
  419. treeData={treeData2}
  420. multiple
  421. filterTreeNode
  422. disabled
  423. />
  424. <br /><br />
  425. <Cascader
  426. defaultValue={['yazhou', 'zhongguo']}
  427. style={{ width: 300 }}
  428. treeData={treeData2}
  429. multiple
  430. disabled
  431. />
  432. </div>
  433. );
  434. };
  435. Disabled.parameters = {
  436. chromatic: { disableSnapshot: false },
  437. }
  438. export const DisabledOption = () => {
  439. return (
  440. <div>
  441. <div>common disabled option</div>
  442. <Cascader style={{ width: 300 }} treeData={treeData2} placeholder="Japan node is disabled" />
  443. <br />
  444. <br />
  445. <div>single selection + defaultValue is disabled option + changeOnSelect</div>
  446. <Cascader
  447. style={{ width: 300 }}
  448. treeData={treeData2}
  449. changeOnSelect
  450. defaultValue={['yazhou', 'riben']}
  451. placeholder="Japan node is disabled"
  452. />
  453. <br />
  454. <br />
  455. <div>
  456. single selection + defaultValue is disabled option + changeOnSelect + filterTreeNode
  457. </div>
  458. <Cascader
  459. style={{ width: 300 }}
  460. treeData={treeData2}
  461. changeOnSelect
  462. filterTreeNode
  463. defaultValue={['yazhou', 'riben']}
  464. placeholder="Japan node is disabled"
  465. />
  466. <br />
  467. <br />
  468. <div>multiple selection + defaultValue is disabled option</div>
  469. <Cascader
  470. multiple
  471. filterTreeNode
  472. style={{ width: 300 }}
  473. treeData={treeData2}
  474. defaultValue={['yazhou', 'riben']}
  475. placeholder="Japan node is disabled"
  476. />
  477. <br />
  478. <br />
  479. <div>multiple selection + filterTreeNode + defaultValue is disabled option</div>
  480. <Cascader
  481. filterTreeNode
  482. multiple
  483. style={{ width: 300 }}
  484. treeData={treeData2}
  485. defaultValue={[
  486. ['yazhou', 'riben'],
  487. ['beimeizhou', 'jianada']
  488. ]}
  489. placeholder="Japan node is disabled"
  490. />
  491. </div>
  492. );
  493. };
  494. export const CustomSearch = () => {
  495. return (
  496. <div>
  497. <Cascader
  498. style={{ width: 300 }}
  499. treeData={treeData2}
  500. placeholder="Please select"
  501. filterTreeNode
  502. treeNodeFilterProp="value"
  503. />
  504. </div>
  505. );
  506. };
  507. export const CustomDisplayProp = () => {
  508. return (
  509. <div>
  510. <Cascader
  511. style={{ width: 300 }}
  512. treeData={treeData2}
  513. placeholder="Please select"
  514. changeOnSelect={true}
  515. displayProp="value"
  516. filterTreeNode
  517. />
  518. </div>
  519. );
  520. };
  521. export const DefaultValue = () => {
  522. return (
  523. <div>
  524. <Cascader
  525. style={{ width: 300 }}
  526. treeData={treeData3}
  527. placeholder="Please select"
  528. defaultValue={['yazhou', 'zhongguo', 'shanghai']}
  529. />
  530. <br />
  531. <br />
  532. <Cascader
  533. style={{ width: 300 }}
  534. treeData={treeData3}
  535. placeholder="Please select"
  536. changeOnSelect
  537. defaultValue={['yazhou']}
  538. />
  539. <br />
  540. <br />
  541. <Cascader
  542. style={{ width: 300 }}
  543. treeData={treeData3}
  544. placeholder="Please select"
  545. changeOnSelect
  546. defaultValue={['yazhou', 'zhongguo']}
  547. filterTreeNode
  548. />
  549. <br />
  550. <br />
  551. <Cascader
  552. style={{ width: 300 }}
  553. treeData={treeData3}
  554. placeholder="Please select"
  555. changeOnSelect
  556. defaultValue={'yazhou'}
  557. filterTreeNode
  558. />
  559. <br />
  560. <br />
  561. <Cascader
  562. style={{ width: 300 }}
  563. treeData={treeData3}
  564. placeholder="Please select"
  565. defaultValue={['yazhou', 'zhongguo']}
  566. filterTreeNode
  567. />
  568. </div>
  569. );
  570. };
  571. export const DefaultValueNotExist = () => {
  572. return (
  573. <>
  574. <Cascader
  575. style={{ width: 300 }}
  576. treeData={treeData3}
  577. placeholder="Please select"
  578. changeOnSelect
  579. defaultValue={'yazhou not exist'}
  580. filterTreeNode
  581. />
  582. <br />
  583. <br />
  584. <Cascader
  585. style={{ width: 300 }}
  586. treeData={treeData3}
  587. placeholder="Please select"
  588. defaultValue={'tokyo not exist'}
  589. />
  590. </>
  591. );
  592. };
  593. class ControlledDemo extends React.Component {
  594. constructor() {
  595. super();
  596. this.state = {
  597. value: [],
  598. };
  599. }
  600. onChange(value) {
  601. this.setState({ value });
  602. }
  603. render() {
  604. const treeData = [
  605. {
  606. label: '浙江省',
  607. value: 'zhejiang',
  608. children: [
  609. {
  610. label: '杭州市',
  611. value: 'hangzhou',
  612. children: [
  613. {
  614. label: '西湖区',
  615. value: 'xihu',
  616. },
  617. {
  618. label: '萧山区',
  619. value: 'xiaoshan',
  620. },
  621. {
  622. label: '临安区',
  623. value: 'linan',
  624. },
  625. ],
  626. },
  627. {
  628. label: '宁波市',
  629. value: 'ningbo',
  630. children: [
  631. {
  632. label: '海曙区',
  633. value: 'haishu',
  634. },
  635. {
  636. label: '江北区',
  637. value: 'jiangbei',
  638. },
  639. ],
  640. },
  641. ],
  642. },
  643. ];
  644. return (
  645. <Cascader
  646. multiple
  647. style={{ width: 300 }}
  648. treeData={treeData}
  649. placeholder="请选择所在地区"
  650. value={this.state.value}
  651. changeOnSelect
  652. filterTreeNode
  653. onChangeWithObject
  654. onChange={e => this.onChange(e)}
  655. />
  656. );
  657. }
  658. }
  659. export const ControlledComponent = () => <ControlledDemo />;
  660. export const CascaderOrderTest = () => {
  661. return (
  662. <div>
  663. <Cascader style={{ width: 300 }} treeData={treeOrder} placeholder="Please select" />
  664. </div>
  665. );
  666. };
  667. export const OnFocusAndOnBlur = () => {
  668. return (
  669. <div>
  670. <Cascader
  671. style={{ width: 300 }}
  672. treeData={treeData1}
  673. placeholder="Please select"
  674. onFocus={(val, e) => console.log('focus', e, val)}
  675. onBlur={(val, e) => console.log('blur', e, val)}
  676. />
  677. </div>
  678. );
  679. };
  680. export const ShowClear = () => {
  681. return (
  682. <div>
  683. <Cascader
  684. style={{ marginLeft: 700, width: 300 }}
  685. treeData={treeData1}
  686. placeholder="Please select"
  687. showClear
  688. filterTreeNode
  689. />
  690. <br />
  691. <br />
  692. <Cascader
  693. style={{ marginLeft: 700, width: 300 }}
  694. treeData={treeData1}
  695. placeholder="Please select when multiple"
  696. multiple
  697. showClear
  698. />
  699. <br />
  700. <br />
  701. <div style={{ marginLeft: 700 }}>
  702. <p>有用户反馈,超长列表点击 showClear 后,dropdown错位。1.30.0-beta.1 fixed</p>
  703. <Cascader
  704. style={{ width: 300 }}
  705. treeData={longTreeData}
  706. placeholder="Please select"
  707. showClear
  708. />
  709. </div>
  710. </div>
  711. );
  712. };
  713. const LoadDataDemo = () => {
  714. const initialData = [
  715. {
  716. label: 'Node1',
  717. value: '0-0',
  718. },
  719. {
  720. label: 'Node2',
  721. value: '0-1',
  722. },
  723. {
  724. label: 'Node3',
  725. value: '0-2',
  726. isLeaf: true,
  727. },
  728. ];
  729. const [data, setData] = useState(initialData);
  730. const updateTreeData = (list, value, children) => {
  731. return list.map(node => {
  732. if (node.value === value) {
  733. return { ...node, children };
  734. }
  735. if (node.children) {
  736. return { ...node, children: updateTreeData(node.children, value, children) };
  737. }
  738. return node;
  739. });
  740. };
  741. const onLoadData = selectedOpt => {
  742. const targetOpt = selectedOpt[selectedOpt.length - 1];
  743. const { label, value } = targetOpt;
  744. return new Promise(resolve => {
  745. if (targetOpt.children) {
  746. resolve();
  747. return;
  748. }
  749. setTimeout(() => {
  750. setData(origin =>
  751. updateTreeData(origin, value, [
  752. {
  753. label: `${label} - 1`,
  754. value: `${label}-1`,
  755. isLeaf: selectedOpt.length > 1,
  756. },
  757. {
  758. label: `${label} - 2`,
  759. value: `${label}-2`,
  760. isLeaf: selectedOpt.length > 1,
  761. },
  762. ])
  763. );
  764. resolve();
  765. }, 1000);
  766. });
  767. };
  768. return (
  769. <Cascader
  770. style={{ width: 300 }}
  771. treeData={data}
  772. loadData={onLoadData}
  773. onChangeWithSelect
  774. placeholder="Please select"
  775. />
  776. );
  777. };
  778. const LoadDataWithReset = () => {
  779. const initialData = [
  780. {
  781. label: 'Node1',
  782. value: '0-0',
  783. },
  784. {
  785. label: 'Node2',
  786. value: '0-1',
  787. },
  788. {
  789. label: 'Node3',
  790. value: '0-2',
  791. isLeaf: true,
  792. },
  793. ];
  794. const [data, setData] = useState(initialData);
  795. const [value, setValue] = useState([]);
  796. const updateTreeData = (list, value, children) => {
  797. return list.map(node => {
  798. if (node.value === value) {
  799. return { ...node, children };
  800. }
  801. if (node.children) {
  802. return { ...node, children: updateTreeData(node.children, value, children) };
  803. }
  804. return node;
  805. });
  806. };
  807. const onLoadData = selectedOpt => {
  808. const targetOpt = selectedOpt[selectedOpt.length - 1];
  809. const { label, value } = targetOpt;
  810. return new Promise(resolve => {
  811. if (targetOpt.children) {
  812. resolve();
  813. return;
  814. }
  815. setTimeout(() => {
  816. setData(origin =>
  817. updateTreeData(origin, value, [
  818. {
  819. label: `${label} - 1`,
  820. value: `${label}-1`,
  821. isLeaf: selectedOpt.length > 1,
  822. },
  823. {
  824. label: `${label} - 2`,
  825. value: `${label}-2`,
  826. isLeaf: selectedOpt.length > 1,
  827. },
  828. ])
  829. );
  830. resolve();
  831. }, 1000);
  832. });
  833. };
  834. return (
  835. <>
  836. <Cascader
  837. style={{ width: 300 }}
  838. treeData={data}
  839. loadData={onLoadData}
  840. value={value}
  841. onChangeWithObject
  842. changeOnSelect
  843. onChange={setValue}
  844. placeholder="Please select"
  845. />
  846. <Button onClick={() => setValue([])}>重置</Button>
  847. </>
  848. );
  849. };
  850. export const LoadData = () => (
  851. <>
  852. <LoadDataDemo />
  853. <br />
  854. <br />
  855. <div>fix:1448,重置失效</div>
  856. <LoadDataWithReset />
  857. </>
  858. );
  859. export const DynamicPlaceholder = () => {
  860. const [isSelect, setSelect] = useState(false);
  861. return (
  862. <>
  863. <Button onClick={() => setSelect(!isSelect)}>Toggle</Button>
  864. <Cascader
  865. style={{ width: 300 }}
  866. treeData={treeData2}
  867. placeholder="Please select"
  868. searchPlaceholder="Search something"
  869. filterTreeNode={isSelect}
  870. showClear
  871. />
  872. </>
  873. );
  874. };
  875. export const FixDedupOnSelect = () => {
  876. return (
  877. <div>
  878. <Cascader
  879. style={{ width: 300 }}
  880. treeData={treeData2}
  881. placeholder="Please select"
  882. onSelect={v => console.log(v)}
  883. />
  884. <Cascader
  885. style={{ width: 300 }}
  886. treeData={treeData2}
  887. placeholder="Please select"
  888. onSelect={v => console.log(v)}
  889. dedupOnSelect={false}
  890. />
  891. </div>
  892. );
  893. };
  894. const slotStyle = {
  895. height: '36px',
  896. display: 'flex',
  897. padding: '0 32px',
  898. alignItems: 'center',
  899. cursor: 'pointer',
  900. borderRadius: '0 0 6px 6px',
  901. };
  902. export const CascaderWithSlot = () => {
  903. return (
  904. <div>
  905. <Cascader
  906. style={{ width: 300 }}
  907. treeData={treeData2}
  908. placeholder="请选择所在地区"
  909. topSlot={<Text style={slotStyle}>选择地区</Text>}
  910. bottomSlot={
  911. <div style={slotStyle}>
  912. <Text>找不大相关选项?</Text>
  913. <Text link>去新建</Text>
  914. </div>
  915. }
  916. />
  917. </div>
  918. );
  919. };
  920. export const CascaderWithMaxTagCountShowRestTagsPopoverRestTagsPopoverProps = () => {
  921. return (
  922. <div>
  923. <Cascader
  924. style={{ width: 300 }}
  925. treeData={treeData4}
  926. placeholder="请选择所在地区"
  927. multiple
  928. maxTagCount={1}
  929. showRestTagsPopover
  930. restTagsPopoverProps={{ position: 'bottom' }}
  931. defaultValue={[
  932. ['zhejiang', 'ningbo', 'haishu'],
  933. ['zhejiang', 'hangzhou', 'xihu'],
  934. ]}
  935. />
  936. </div>
  937. );
  938. };
  939. CascaderWithMaxTagCountShowRestTagsPopoverRestTagsPopoverProps.story = {
  940. name: 'Cascader with maxTagCount/showRestTagsPopover/restTagsPopoverProps',
  941. };
  942. CascaderWithMaxTagCountShowRestTagsPopoverRestTagsPopoverProps.parameters = {
  943. chromatic: { disableSnapshot: false },
  944. }
  945. export const CascaderWithShowNext = () => {
  946. return (
  947. <div>
  948. <Cascader
  949. style={{ width: 300 }}
  950. treeData={treeData4}
  951. placeholder="请选择所在地区"
  952. showNext="hover"
  953. />
  954. </div>
  955. );
  956. };
  957. export const CascaderWithMaxOnExceed = () => {
  958. return (
  959. <div>
  960. <div>普通情况</div>
  961. <Cascader
  962. style={{ width: 300 }}
  963. treeData={treeData4}
  964. placeholder="请选择所在地区"
  965. multiple
  966. max={1}
  967. onExceed={v => {
  968. Toast.warning('exceed max');
  969. console.log(v);
  970. }}
  971. defaultValue={['zhejiang', 'ningbo', 'haishu']}
  972. />
  973. <br />
  974. <br />
  975. <div>defaultValue的数量超过max,则只允许减少到合法,不允许再增加</div>
  976. <Cascader
  977. style={{ width: 300 }}
  978. treeData={treeData4}
  979. placeholder="请选择所在地区"
  980. multiple
  981. max={1}
  982. onExceed={v => {
  983. Toast.warning('exceed max');
  984. console.log(v);
  985. }}
  986. defaultValue={[
  987. ['zhejiang', 'ningbo', 'haishu'],
  988. ['zhejiang', 'hangzhou', 'xihu'],
  989. ]}
  990. />
  991. <br />
  992. <br />
  993. <div>autoMergeValue=false时的情况</div>
  994. <Cascader
  995. style={{ width: 300 }}
  996. treeData={treeData4}
  997. placeholder="请选择所在地区"
  998. multiple
  999. max={2}
  1000. autoMergeValue={false}
  1001. onExceed={v => {
  1002. Toast.warning('exceed max');
  1003. console.log(v);
  1004. }}
  1005. defaultValue={[
  1006. ['zhejiang', 'ningbo', 'haishu'],
  1007. ['zhejiang', 'hangzhou', 'xihu'],
  1008. ]}
  1009. />
  1010. </div>
  1011. );
  1012. };
  1013. CascaderWithMaxOnExceed.story = {
  1014. name: 'Cascader with max/onExceed',
  1015. };
  1016. CascaderWithMaxOnExceed.parameters = {
  1017. chromatic: { disableSnapshot: false },
  1018. }
  1019. const ControlledLoadDataWithDefaultValue = () => {
  1020. const [v, setV] = useState('受控 Value');
  1021. const initialData = [
  1022. {
  1023. label: 'Node1',
  1024. value: '0-0',
  1025. },
  1026. {
  1027. label: 'Node2',
  1028. value: '0-1',
  1029. },
  1030. {
  1031. label: 'Node3',
  1032. value: '0-2',
  1033. isLeaf: true,
  1034. },
  1035. ];
  1036. const [data, setData] = useState(initialData);
  1037. const updateTreeData = (list, value, children) => {
  1038. return list.map(node => {
  1039. if (node.value === value) {
  1040. return { ...node, children };
  1041. }
  1042. if (node.children) {
  1043. return { ...node, children: updateTreeData(node.children, value, children) };
  1044. }
  1045. return node;
  1046. });
  1047. };
  1048. const onLoadData = selectedOpt => {
  1049. const targetOpt = selectedOpt[selectedOpt.length - 1];
  1050. const { label, value } = targetOpt;
  1051. return new Promise(resolve => {
  1052. if (targetOpt.children) {
  1053. resolve();
  1054. return;
  1055. }
  1056. setTimeout(() => {
  1057. setData(origin =>
  1058. updateTreeData(origin, value, [
  1059. {
  1060. label: `${label} - 1`,
  1061. value: `${label}-1`,
  1062. isLeaf: selectedOpt.length > 1,
  1063. },
  1064. {
  1065. label: `${label} - 2`,
  1066. value: `${label}-2`,
  1067. isLeaf: selectedOpt.length > 1,
  1068. },
  1069. ])
  1070. );
  1071. resolve();
  1072. }, 1000);
  1073. });
  1074. };
  1075. return (
  1076. <Cascader
  1077. defaultValue="123"
  1078. value={v}
  1079. onChange={v => setV(v)}
  1080. style={{ width: 300 }}
  1081. treeData={data}
  1082. loadData={onLoadData}
  1083. placeholder="Please select"
  1084. />
  1085. );
  1086. };
  1087. const LoadDataWithDefaultValue = () => {
  1088. const initialData = [
  1089. {
  1090. label: 'Node1',
  1091. value: '0-0',
  1092. },
  1093. {
  1094. label: 'Node2',
  1095. value: '0-1',
  1096. },
  1097. {
  1098. label: 'Node3',
  1099. value: '0-2',
  1100. isLeaf: true,
  1101. },
  1102. ];
  1103. const [data, setData] = useState(initialData);
  1104. const updateTreeData = (list, value, children) => {
  1105. return list.map(node => {
  1106. if (node.value === value) {
  1107. return { ...node, children };
  1108. }
  1109. if (node.children) {
  1110. return { ...node, children: updateTreeData(node.children, value, children) };
  1111. }
  1112. return node;
  1113. });
  1114. };
  1115. const onLoadData = selectedOpt => {
  1116. const targetOpt = selectedOpt[selectedOpt.length - 1];
  1117. const { label, value } = targetOpt;
  1118. return new Promise(resolve => {
  1119. if (targetOpt.children) {
  1120. resolve();
  1121. return;
  1122. }
  1123. setTimeout(() => {
  1124. setData(origin =>
  1125. updateTreeData(origin, value, [
  1126. {
  1127. label: `${label} - 1`,
  1128. value: `${label}-1`,
  1129. isLeaf: selectedOpt.length > 1,
  1130. },
  1131. {
  1132. label: `${label} - 2`,
  1133. value: `${label}-2`,
  1134. isLeaf: selectedOpt.length > 1,
  1135. },
  1136. ])
  1137. );
  1138. resolve();
  1139. }, 1000);
  1140. });
  1141. };
  1142. return (
  1143. <Cascader
  1144. defaultValue="defaultValue"
  1145. style={{ width: 300 }}
  1146. treeData={data}
  1147. loadData={onLoadData}
  1148. showClear
  1149. placeholder="Please select"
  1150. />
  1151. );
  1152. };
  1153. export const LoadDataWithDefaultValueDemo = () => {
  1154. return (
  1155. <div>
  1156. <div>fix-1429,检查defaultValue在异步时是否有异常</div>
  1157. <ControlledLoadDataWithDefaultValue />
  1158. <br />
  1159. <br />
  1160. <LoadDataWithDefaultValue />
  1161. </div>
  1162. );
  1163. };
  1164. LoadDataWithDefaultValueDemo.parameters = {
  1165. chromatic: { disableSnapshot: false },
  1166. }
  1167. export const OnChangeWithObject = () => (
  1168. <>
  1169. <div>单选 + onChangeWithObject + defaultValue 为 string []</div>
  1170. <Cascader
  1171. onChangeWithObject
  1172. style={{ width: 300 }}
  1173. treeData={treeData4}
  1174. placeholder="请选择所在地区"
  1175. defaultValue={['zhejiang', 'hangzhou', 'xihu']}
  1176. />
  1177. <br />
  1178. <br />
  1179. <div>多选 + onChangeWithObject + defaultValue 为 string []</div>
  1180. <Cascader
  1181. multiple
  1182. changeOnSelect
  1183. onChangeWithObject
  1184. style={{ width: 300 }}
  1185. treeData={treeData4}
  1186. placeholder="请选择所在地区"
  1187. defaultValue={'zhejiang'}
  1188. />
  1189. <br />
  1190. <br />
  1191. <div>单选 + onChangeWithObject + defaultValue 为 object []</div>
  1192. <Cascader
  1193. onChangeWithObject
  1194. changeOnSelect
  1195. style={{ width: 300 }}
  1196. treeData={treeData2}
  1197. placeholder="请选择所在地区"
  1198. defaultValue={{
  1199. label: '北美洲',
  1200. value: 'beimeizhou',
  1201. children: [
  1202. {
  1203. label: '美国',
  1204. value: 'meiguo',
  1205. },
  1206. {
  1207. label: '加拿大',
  1208. value: 'jianada',
  1209. },
  1210. ],
  1211. }}
  1212. />
  1213. <br />
  1214. <br />
  1215. <div>多选 + onChangeWithObject + defaultValue 为 object []</div>
  1216. <Cascader
  1217. multiple
  1218. onChangeWithObject
  1219. style={{ width: 300 }}
  1220. treeData={treeData2}
  1221. placeholder="请选择所在地区"
  1222. defaultValue={{
  1223. label: '北美洲',
  1224. value: 'beimeizhou',
  1225. children: [
  1226. {
  1227. label: '美国',
  1228. value: 'meiguo',
  1229. },
  1230. {
  1231. label: '加拿大',
  1232. value: 'jianada',
  1233. },
  1234. ],
  1235. }}
  1236. />
  1237. </>
  1238. );
  1239. export const undefinedValueWhileMutipleAndOnChangeWithObject = () => {
  1240. const [value, setValue] = useState(undefined);
  1241. return (
  1242. <>
  1243. <div>多选 + onChangeWithObject + value 为 undefined</div>
  1244. <Cascader
  1245. multiple
  1246. onChangeWithObject
  1247. style={{ width: 300 }}
  1248. treeData={treeData2}
  1249. placeholder="请选择所在地区"
  1250. value={value}
  1251. onChange={(v)=>{
  1252. setValue(v);
  1253. }}
  1254. />
  1255. </>
  1256. )
  1257. }
  1258. export const LeafOnly = () => {
  1259. const [value, setValue] = useState([])
  1260. return (
  1261. <div>
  1262. <div>autoMergeValue=false,leafOnly=false</div>
  1263. <Cascader
  1264. style={{ width: 300 }}
  1265. treeData={treeData4}
  1266. placeholder="请选择所在地区"
  1267. multiple
  1268. autoMergeValue={false}
  1269. leafOnly={false}
  1270. defaultValue={['zhejiang']}
  1271. />
  1272. <br />
  1273. <br />
  1274. <div>autoMergeValue=false,leafOnly=true, leafOnly生效</div>
  1275. <Cascader
  1276. style={{ width: 300 }}
  1277. treeData={treeData4}
  1278. placeholder="请选择所在地区"
  1279. multiple
  1280. autoMergeValue={false}
  1281. leafOnly={true}
  1282. defaultValue={['zhejiang']}
  1283. />
  1284. <br />
  1285. <br />
  1286. <div>受控,autoMergeValue=false,leafOnly=true, leafOnly生效</div>
  1287. <Cascader
  1288. style={{ width: 300 }}
  1289. treeData={treeData4}
  1290. placeholder="请选择所在地区"
  1291. multiple
  1292. onChange={v=>{
  1293. console.log(v);
  1294. setValue(v)
  1295. }}
  1296. autoMergeValue={false}
  1297. leafOnly={true}
  1298. value={value}
  1299. />
  1300. <br />
  1301. <br />
  1302. <div>受控 onChangeWithObject, autoMergeValue=false,leafOnly=true, leafOnly生效</div>
  1303. <Cascader
  1304. style={{ width: 300 }}
  1305. treeData={treeData4}
  1306. placeholder="请选择所在地区"
  1307. multiple
  1308. onChange={v=>{
  1309. console.log(v);
  1310. setValue(v)
  1311. }}
  1312. onChangeWithObject
  1313. autoMergeValue={false}
  1314. leafOnly={true}
  1315. value={value}
  1316. />
  1317. <br />
  1318. <br />
  1319. <div>autoMergeValue=true,leafOnly=false</div>
  1320. <Cascader
  1321. style={{ width: 300 }}
  1322. treeData={treeData4}
  1323. placeholder="请选择所在地区"
  1324. multiple
  1325. autoMergeValue={true}
  1326. leafOnly={false}
  1327. defaultValue={['zhejiang']}
  1328. />
  1329. <br />
  1330. <br />
  1331. <br />
  1332. <div>autoMergeValue=true,leafOnly=true</div>
  1333. <Cascader
  1334. style={{ width: 300 }}
  1335. treeData={treeData4}
  1336. placeholder="请选择所在地区"
  1337. multiple
  1338. autoMergeValue={true}
  1339. leafOnly={true}
  1340. defaultValue={['zhejiang']}
  1341. />
  1342. </div>
  1343. );
  1344. }
  1345. export const DynamicTreeData = () => {
  1346. const [treeDataDemo1,setTreeData1]=useState(treeData2);
  1347. const [treeDataDemo2,setTreeData2]=useState(treeData2);
  1348. const [treeDataDemo3,setTreeData3]=useState(treeData2);
  1349. const [treeDataDemo4,setTreeData4]=useState(treeData2);
  1350. const [treeDataDemo5,setTreeData5]=useState(treeData2);
  1351. const [value3,setValue3]=useState();
  1352. const [value4,setValue4]=useState();
  1353. return (
  1354. <div>
  1355. <div>多选 + 动态更新 tree</div>
  1356. <Cascader
  1357. style={{ width: 300 }}
  1358. treeData={treeDataDemo1}
  1359. multiple
  1360. placeholder="请选择所在地区"
  1361. />
  1362. <Button onClick={()=>{setTreeData1(treeData3)}}>改变treeData</Button>
  1363. <br />
  1364. <br />
  1365. <div>单选 + 动态更新 tree</div>
  1366. <Cascader
  1367. style={{ width: 300 }}
  1368. treeData={treeDataDemo2}
  1369. placeholder="请选择所在地区"
  1370. />
  1371. <Button onClick={()=>{setTreeData2(treeData3)}}>改变treeData</Button>
  1372. <br />
  1373. <br />
  1374. <div>多选 + 动态更新 tree + 受控</div>
  1375. <Cascader
  1376. style={{ width: 300 }}
  1377. treeData={treeDataDemo3}
  1378. multiple
  1379. value={value3}
  1380. onChange={v=>{
  1381. console.log(v);
  1382. setValue3(v);
  1383. }}
  1384. placeholder="请选择所在地区"
  1385. />
  1386. <Button onClick={()=>{setTreeData3(treeData3)}}>改变treeData</Button>
  1387. <br />
  1388. <br />
  1389. <div>单选 + 动态更新 tree + 受控</div>
  1390. <Cascader
  1391. style={{ width: 300 }}
  1392. treeData={treeDataDemo4}
  1393. value={value4}
  1394. onChange={v=>{
  1395. console.log(v);
  1396. setValue4(v);
  1397. }}
  1398. placeholder="请选择所在地区"
  1399. />
  1400. <Button onClick={()=>{setTreeData4(treeData3)}}>改变treeData</Button>
  1401. <br />
  1402. <br />
  1403. <div>多选 + 动态更新 tree + defaultValue 为亚洲</div>
  1404. <Cascader
  1405. style={{ width: 300 }}
  1406. treeData={treeDataDemo5}
  1407. multiple
  1408. defaultValue='yazhou'
  1409. placeholder="请选择所在地区"
  1410. />
  1411. <Button onClick={()=>{setTreeData5(treeData3)}}>改变treeData</Button>
  1412. <br />
  1413. <br />
  1414. </div>
  1415. );
  1416. }
  1417. export const SuperLongList = () => {
  1418. let treeData = new Array(100).fill().map(() => ({ label: '浙江省', value: 'zhejiang' }));
  1419. treeData.push({ label: '到底啦', value: 'bottom' })
  1420. return (
  1421. <Cascader
  1422. style={{ width: 300 }}
  1423. treeData={treeData}
  1424. placeholder="请选择所在地区"
  1425. onListScroll={()=>{console.log(123)}}
  1426. />
  1427. );
  1428. };