cascader.stories.js 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424
  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. }
  1292. export const DynamicTreeData = () => {
  1293. const [treeDataDemo1,setTreeData1]=useState(treeData2);
  1294. const [treeDataDemo2,setTreeData2]=useState(treeData2);
  1295. const [treeDataDemo3,setTreeData3]=useState(treeData2);
  1296. const [treeDataDemo4,setTreeData4]=useState(treeData2);
  1297. const [treeDataDemo5,setTreeData5]=useState(treeData2);
  1298. const [value3,setValue3]=useState();
  1299. const [value4,setValue4]=useState();
  1300. return (
  1301. <div>
  1302. <div>多选 + 动态更新 tree</div>
  1303. <Cascader
  1304. style={{ width: 300 }}
  1305. treeData={treeDataDemo1}
  1306. multiple
  1307. placeholder="请选择所在地区"
  1308. />
  1309. <Button onClick={()=>{setTreeData1(treeData3)}}>改变treeData</Button>
  1310. <br />
  1311. <br />
  1312. <div>单选 + 动态更新 tree</div>
  1313. <Cascader
  1314. style={{ width: 300 }}
  1315. treeData={treeDataDemo2}
  1316. placeholder="请选择所在地区"
  1317. />
  1318. <Button onClick={()=>{setTreeData2(treeData3)}}>改变treeData</Button>
  1319. <br />
  1320. <br />
  1321. <div>多选 + 动态更新 tree + 受控</div>
  1322. <Cascader
  1323. style={{ width: 300 }}
  1324. treeData={treeDataDemo3}
  1325. multiple
  1326. value={value3}
  1327. onChange={v=>{
  1328. console.log(v);
  1329. setValue3(v);
  1330. }}
  1331. placeholder="请选择所在地区"
  1332. />
  1333. <Button onClick={()=>{setTreeData3(treeData3)}}>改变treeData</Button>
  1334. <br />
  1335. <br />
  1336. <div>单选 + 动态更新 tree + 受控</div>
  1337. <Cascader
  1338. style={{ width: 300 }}
  1339. treeData={treeDataDemo4}
  1340. value={value4}
  1341. onChange={v=>{
  1342. console.log(v);
  1343. setValue4(v);
  1344. }}
  1345. placeholder="请选择所在地区"
  1346. />
  1347. <Button onClick={()=>{setTreeData4(treeData3)}}>改变treeData</Button>
  1348. <br />
  1349. <br />
  1350. <div>多选 + 动态更新 tree + defaultValue 为亚洲</div>
  1351. <Cascader
  1352. style={{ width: 300 }}
  1353. treeData={treeDataDemo5}
  1354. multiple
  1355. defaultValue='yazhou'
  1356. placeholder="请选择所在地区"
  1357. />
  1358. <Button onClick={()=>{setTreeData5(treeData3)}}>改变treeData</Button>
  1359. <br />
  1360. <br />
  1361. </div>
  1362. );
  1363. }