cascader.stories.js 31 KB

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