select.stories.jsx 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015
  1. import React, { useState, useRef, useEffect } from 'react';
  2. import './select.scss';
  3. import { Input, Select, Button, Icon, Avatar, Checkbox, Form, withField, Space, Tag } from '../../index';
  4. import CustomTrigger from './CustomTrigger';
  5. import classNames from 'classnames';
  6. import { getHighLightTextHTML } from '../../_utils/index';
  7. const Option = Select.Option;
  8. import { IconSearch, IconGift } from '@douyinfe/semi-icons';
  9. export default {
  10. title: 'Select',
  11. parameters: {
  12. chromatic: { disableSnapshot: true },
  13. },
  14. }
  15. let Test = () => {
  16. let [options, setOptions] = useState([1, 2, 3, 4]);
  17. function add() {
  18. let newOptions = Array.from(
  19. {
  20. length: Math.floor(Math.random() * 10),
  21. },
  22. (v, i) => i + 1
  23. );
  24. setOptions(newOptions);
  25. }
  26. let style = {
  27. width: 150,
  28. margin: 20,
  29. };
  30. let slotStyle = {
  31. backgroundColor: 'whitesmoke',
  32. height: '40px',
  33. display: 'flex',
  34. justifyContent: 'center',
  35. alignItems: 'center',
  36. borderRadius: '0 0 6px 6px',
  37. };
  38. let outSlotStyle = {
  39. backgroundColor: 'whitesmoke',
  40. height: '29px',
  41. display: 'flex',
  42. justifyContent: 'center',
  43. alignItems: 'center',
  44. cursor: 'pointer',
  45. };
  46. const click = e => {};
  47. let outSlotNode = (
  48. <div onClick={e => click(e)}>
  49. <Checkbox>sendLarkNotification</Checkbox>
  50. <div>
  51. <Button theme="solid">confirm</Button>
  52. </div>
  53. </div>
  54. );
  55. return (
  56. <>
  57. <Select
  58. style={style}
  59. dropdownClassName="test-dropdown"
  60. dropdownStyle={{
  61. width: 150,
  62. }}
  63. filter
  64. placeholder="fefe"
  65. position="rightTop"
  66. innerBottomSlot={
  67. <div style={slotStyle}>
  68. <Button
  69. size="small"
  70. style={{
  71. margin: 0,
  72. }}
  73. >
  74. 申请其他地区权限
  75. </Button>
  76. </div>
  77. }
  78. >
  79. {options.map(option => (
  80. <Option value={option} key={option} className="fefe">
  81. {option}
  82. </Option>
  83. ))}
  84. </Select>
  85. <Select
  86. style={{
  87. marginTop: 20,
  88. width: 200,
  89. }}
  90. dropdownClassName="test-dropdown"
  91. dropdownStyle={{
  92. width: 150,
  93. }}
  94. filter
  95. placeholder="fefe"
  96. position="rightTop"
  97. outerBottomSlot={outSlotNode}
  98. >
  99. {options.map(option => (
  100. <Option value={option} key={option} className="fefe">
  101. {option}
  102. </Option>
  103. ))}
  104. </Select>
  105. </>
  106. );
  107. };
  108. const AutoFocusDemo = () => {
  109. return (
  110. <>
  111. <Select
  112. autoFocus
  113. style={{
  114. width: 200,
  115. }}
  116. onFocus={() => console.log('onFocus')}
  117. onBlur={() => console.log('onBlur')}
  118. >
  119. <Option value="abc">抖音</Option>
  120. <Option value="hotsoon">火山</Option>
  121. <Option value="pipixia">皮皮虾</Option>
  122. <Option value="duoshan">多闪</Option>
  123. <Option value="xigua">西瓜视频</Option>
  124. </Select>
  125. <div className="test-div">test-div</div>
  126. </>
  127. );
  128. };
  129. export const AutoFocus = () => <AutoFocusDemo />;
  130. AutoFocus.story = {
  131. name: 'autoFocus',
  132. };
  133. export const InnerBottomSlotOuterBottomSlot = () => <Test />;
  134. InnerBottomSlotOuterBottomSlot.story = {
  135. name: 'innerBottomSlot / outerBottomSlot',
  136. };
  137. export const InnerTopSlotOuterTopSlot = () => {
  138. const slot = <div>未找到应用?</div>;
  139. return (
  140. <div>
  141. innerTopSlot
  142. <div>
  143. <Select
  144. innerTopSlot={slot}
  145. style={{
  146. width: 250,
  147. }}
  148. maxHeight={150}
  149. >
  150. <Option value="abc">抖音</Option>
  151. <Option value="hotsoon">火山</Option>
  152. <Option value="pipixia">皮皮虾</Option>
  153. <Option value="duoshan">多闪</Option>
  154. <Option value="xigua">西瓜视频</Option>
  155. </Select>
  156. </div>
  157. outerTopSlot
  158. <div>
  159. <Select
  160. outerTopSlot={slot}
  161. style={{
  162. width: 250,
  163. }}
  164. maxHeight={150}
  165. >
  166. <Option value="abc">抖音</Option>
  167. <Option value="hotsoon">火山</Option>
  168. <Option value="pipixia">皮皮虾</Option>
  169. <Option value="duoshan">多闪</Option>
  170. <Option value="xigua">西瓜视频</Option>
  171. </Select>
  172. </div>
  173. </div>
  174. );
  175. };
  176. InnerTopSlotOuterTopSlot.story = {
  177. name: 'innerTopSlot / outerTopSlot',
  178. };
  179. export const OneOptionJsxWithOtherOptionArray = () => (
  180. <Select
  181. defaultValue={'all'}
  182. style={{
  183. width: 250,
  184. }}
  185. >
  186. <Option value="all" key="all">
  187. all
  188. </Option>
  189. {[1, 2, 3].map(item => (
  190. <Option value={`type${item}`} key={item}>{`type${item}`}</Option>
  191. ))}
  192. </Select>
  193. );
  194. OneOptionJsxWithOtherOptionArray.story = {
  195. name: 'one option jsx with other option array',
  196. };
  197. let options = [
  198. {
  199. value: 'all',
  200. label: '全部',
  201. otherKey: 'all semi',
  202. },
  203. {
  204. value: 'abc',
  205. label: '抖音',
  206. otherKey: 'abc semi',
  207. },
  208. {
  209. value: 'hotsoon',
  210. label: '火山小视频',
  211. otherKey: 'hostsoom semi',
  212. },
  213. {
  214. value: 'pipixia',
  215. label: '皮皮虾',
  216. otherKey: 'pif',
  217. },
  218. {
  219. value: 'toutiao',
  220. label: '今日头条',
  221. otherKey: 'toutiao semi',
  222. },
  223. {
  224. value: 'rd',
  225. label: 'rd',
  226. otherKey: 'semi rd',
  227. },
  228. {
  229. value: 'ued',
  230. label: 'ued',
  231. otherKey: 'semi ued',
  232. },
  233. {
  234. value: 'ued',
  235. label: 'japan',
  236. otherKey: 'semi ued',
  237. },
  238. {
  239. value: '+86',
  240. label: '+86',
  241. otherKey: 'semi',
  242. },
  243. ];
  244. let longOptions = options.concat({
  245. value: 'long',
  246. label: 'Semi Design 是一个设计系统,它定义了一套中后台设计与前端基础组',
  247. });
  248. export const SelectSize = () => (
  249. <div
  250. style={{
  251. margin: 20,
  252. }}
  253. >
  254. <h4>
  255. 使用方不设width时,下拉菜单根据内容自动适配宽度(不推荐这样使用,select的宽度会动态变化)
  256. </h4>
  257. <Select
  258. defaultValue={'all'}
  259. optionList={options}
  260. style={{
  261. margin: 10,
  262. }}
  263. ></Select>
  264. <Select
  265. defaultValue={'long'}
  266. optionList={longOptions}
  267. style={{
  268. margin: 10,
  269. }}
  270. ></Select>
  271. <Select
  272. defaultValue={'abc'}
  273. size="large"
  274. optionList={options}
  275. style={{
  276. margin: 10,
  277. }}
  278. ></Select>
  279. {/* <Select defaultValue={'+86'} size="large" optionList={options} style={{margin: 10}}>
  280. </Select> */}
  281. <h4>通过style设width的</h4>
  282. 90px:{' '}
  283. <Select
  284. defaultValue={'all'}
  285. style={{
  286. width: 90,
  287. marign: 10,
  288. }}
  289. optionList={options}
  290. ></Select>
  291. 120px:{' '}
  292. <Select
  293. defaultValue={'all'}
  294. style={{
  295. width: 120,
  296. margin: 10,
  297. }}
  298. optionList={options}
  299. ></Select>
  300. 400px:{' '}
  301. <Select
  302. defaultValue={'all'}
  303. style={{
  304. width: 400,
  305. margin: 10,
  306. }}
  307. optionList={options}
  308. ></Select>
  309. <br />
  310. 100%:{' '}
  311. <Select
  312. defaultValue={'all'}
  313. style={{
  314. width: '100%',
  315. margin: 10,
  316. }}
  317. optionList={options}
  318. ></Select>
  319. <br />
  320. <h4>通过css设width的</h4>
  321. <Select defaultValue={'all'} className="test-width" optionList={options}></Select>
  322. <br />
  323. <h4>dropdownMatchSelectWidth</h4>
  324. <p>当该项设为true时,下拉菜单最小宽度会等于Select宽度(默认为true)</p>
  325. <div
  326. style={{
  327. margin: 10,
  328. }}
  329. >
  330. style方式指定90px:
  331. <Select
  332. defaultValue={'all'}
  333. optionList={options}
  334. dropdownMatchSelectWidth={true}
  335. style={{
  336. width: 90,
  337. }}
  338. />
  339. </div>
  340. <div
  341. style={{
  342. margin: 10,
  343. }}
  344. >
  345. css方式声明130px:
  346. <Select
  347. defaultValue={'all'}
  348. className="test-width"
  349. optionList={options}
  350. dropdownMatchSelectWidth={true}
  351. ></Select>
  352. </div>
  353. <div>
  354. <h4>需要强制下拉菜单与select同宽的时候</h4>
  355. <p>通过dropdownStyle覆盖min-width,将其设成与select的width同样的值</p>
  356. <Select
  357. defaultValue={'all'}
  358. style={{
  359. width: 300,
  360. margin: 10,
  361. }}
  362. dropdownStyle={{
  363. width: 300,
  364. }}
  365. optionList={options}
  366. />
  367. </div>
  368. </div>
  369. );
  370. SelectSize.story = {
  371. name: 'select size',
  372. };
  373. export const WithPrefixSuffixInsetLabelShowClearShowArrow = () => (
  374. <>
  375. <h4>prefix & suffix</h4>
  376. <Select
  377. style={{
  378. width: '250px',
  379. }}
  380. optionList={options}
  381. prefix={<IconSearch />}
  382. suffix={<IconGift></IconGift>}
  383. ></Select>
  384. <h4>insetLabel</h4>
  385. <Select
  386. style={{
  387. width: '250px',
  388. }}
  389. optionList={options}
  390. insetLabel={'业务线'}
  391. ></Select>
  392. <h4>showClear</h4>
  393. <Select
  394. style={{
  395. width: '250px',
  396. }}
  397. optionList={options}
  398. showClear
  399. ></Select>
  400. <h4>showArrow = false</h4>
  401. <Select
  402. style={{
  403. width: '250px',
  404. }}
  405. optionList={options}
  406. showArrow={false}
  407. ></Select>
  408. <h4>defaultValue是不存在的值</h4>
  409. <Select
  410. style={{
  411. width: '250px',
  412. }}
  413. optionList={options}
  414. defaultValue="+85"
  415. ></Select>
  416. </>
  417. );
  418. WithPrefixSuffixInsetLabelShowClearShowArrow.story = {
  419. name: 'with prefix / suffix / insetLabel, showClear, showArrow',
  420. };
  421. WithPrefixSuffixInsetLabelShowClearShowArrow.parameters = {
  422. chromatic: { disableSnapshot: false },
  423. };
  424. export const WithDefaultSelected = () => (
  425. <Select
  426. style={{
  427. width: '250px',
  428. }}
  429. defaultValue={1}
  430. >
  431. <Option value={1}>opt1</Option>
  432. <Option value={2}>opt2</Option>
  433. <Option value={3}>opt3</Option>
  434. <Option value="4">opt4</Option>
  435. </Select>
  436. );
  437. WithDefaultSelected.story = {
  438. name: 'with default selected',
  439. };
  440. export const WithScrollbar = () => (
  441. <Select
  442. style={{
  443. width: '250px',
  444. }}
  445. defaultValue={1}
  446. >
  447. <Option value={1}>opt1</Option>
  448. <Option value={2}>opt2</Option>
  449. <Option value={3}>opt3</Option>
  450. <Option value="4">opt4</Option>
  451. <Option value={5}>opt5</Option>
  452. <Option value={6}>opt6</Option>
  453. <Option value={7}>opt7</Option>
  454. <Option value="8">opt8</Option>
  455. <Option value={9}>opt9</Option>
  456. <Option value={10}>opt10dfsdfsdfdsfdsfsdf</Option>
  457. <Option value={11}>opt11</Option>
  458. <Option value="12">opt12jfldsjflsdjlfldjslfjhifsdfdsfdsffdsodsjlfhjl</Option>
  459. </Select>
  460. );
  461. WithScrollbar.story = {
  462. name: 'with scrollbar',
  463. };
  464. class Link extends React.Component {
  465. get provinces() {
  466. return ['Sichuan', 'Guangdong'];
  467. }
  468. get maps() {
  469. return {
  470. Sichuan: ['Chengdu', 'Dujiangyan'],
  471. Guangdong: ['Guangzhou', 'Shenzhen', 'Dongguan'],
  472. };
  473. }
  474. constructor() {
  475. super();
  476. this.state = {
  477. provinces: this.provinces,
  478. maps: this.maps,
  479. citys: this.maps[this.provinces[0]],
  480. city: this.maps[this.provinces[0]][0],
  481. };
  482. this.provinceChange = this.provinceChange.bind(this);
  483. this.cityChange = this.cityChange.bind(this);
  484. }
  485. provinceChange(newProvince) {
  486. const { maps } = this.state;
  487. this.setState({
  488. citys: maps[newProvince],
  489. city: maps[newProvince][0],
  490. });
  491. }
  492. cityChange(city) {
  493. this.setState({
  494. city,
  495. });
  496. }
  497. render() {
  498. const { provinces, citys, city } = this.state;
  499. return (
  500. <React.Fragment>
  501. <Select
  502. style={{
  503. width: '150px',
  504. margin: '10px',
  505. }}
  506. onChange={this.provinceChange}
  507. defaultValue={provinces[0]}
  508. >
  509. {provinces.map(pro => (
  510. <Option value={pro} key={pro}>
  511. {pro}
  512. </Option>
  513. ))}
  514. </Select>
  515. <Select
  516. style={{
  517. width: '150px',
  518. margin: '10px',
  519. }}
  520. value={city}
  521. onChange={this.cityChange}
  522. >
  523. {citys.map(c => (
  524. <Option value={c} key={c}>
  525. {c}
  526. </Option>
  527. ))}
  528. </Select>
  529. </React.Fragment>
  530. );
  531. }
  532. }
  533. export const TwoSelectChangeAtTheSameTime = () => <Link />;
  534. TwoSelectChangeAtTheSameTime.story = {
  535. name: 'two select change at the same time',
  536. };
  537. export const SelectMultiple = () => (
  538. <>
  539. <Select
  540. multiple={true}
  541. max={10}
  542. style={{
  543. width: '180px',
  544. }}
  545. placeholder="fefe"
  546. >
  547. <Option value={1}>opt1</Option>
  548. <Option value={2}>opt2</Option>
  549. <Option value={3}>opt3</Option>
  550. <Option value="4">opt4</Option>
  551. <Option value={5}>opt5</Option>
  552. <Option value={6}>opt6</Option>
  553. <Option value={7}>opt7</Option>
  554. <Option value={8}>opt8</Option>
  555. </Select>
  556. <br />
  557. <br />
  558. <Select
  559. multiple={true}
  560. style={{
  561. width: '300px',
  562. }}
  563. defaultValue={[1, 2, 3]}
  564. placeholder="fefe"
  565. >
  566. <Option value={1}>opt1</Option>
  567. <Option value={2}>opt2</Option>
  568. <Option value={3}>opt3</Option>
  569. <Option value="4">opt4</Option>
  570. <Option value={5}>opt5</Option>
  571. <Option value={6}>opt6</Option>
  572. <Option value={7}>opt7</Option>
  573. <Option value={8}>opt8</Option>
  574. </Select>
  575. <br />
  576. <br />
  577. <Select
  578. multiple={true}
  579. style={{
  580. width: '300px',
  581. }}
  582. defaultValue={[1, 2, 3]}
  583. placeholder="fefe"
  584. disabled
  585. onSelect={(...res) => console.log(res)}
  586. onDeselect={(...res) => console.log(res)}
  587. >
  588. <Option value={1}>opt1</Option>
  589. <Option value={2}>opt2</Option>
  590. <Option value={3}>opt3</Option>
  591. <Option value="4">opt4</Option>
  592. <Option value={5}>opt5</Option>
  593. <Option value={6}>opt6</Option>
  594. <Option value={7}>opt7</Option>
  595. <Option value={8}>opt8</Option>
  596. </Select>
  597. <br />
  598. <br />
  599. maxTagCount = 3
  600. <br />
  601. <Select
  602. multiple={true}
  603. maxTagCount={3}
  604. style={{
  605. width: '350px',
  606. }}
  607. defaultValue={[1, 2, 3]}
  608. placeholder="fefe"
  609. insetLabel="标签"
  610. onSelect={(...res) => console.log(res)}
  611. onDeselect={(...res) => console.log(res)}
  612. >
  613. <Option value={1}>opt1</Option>
  614. <Option value={2}>opt2</Option>
  615. <Option value={3}>opt3</Option>
  616. <Option value="4">opt4</Option>
  617. <Option value={5}>opt5</Option>
  618. <Option value={6}>opt6</Option>
  619. <Option value={7}>opt7</Option>
  620. <Option value={8}>opt8</Option>
  621. </Select>
  622. <br />
  623. <br />
  624. maxTagCount = 3, showRestTagsPopover
  625. <br />
  626. <Select
  627. multiple={true}
  628. maxTagCount={3}
  629. style={{
  630. width: '350px',
  631. }}
  632. defaultValue={[1, 2, 3]}
  633. placeholder="fefe"
  634. insetLabel="标签"
  635. onSelect={(...res) => console.log(res)}
  636. onDeselect={(...res) => console.log(res)}
  637. showRestTagsPopover={true}
  638. >
  639. <Option value={1}>opt1</Option>
  640. <Option value={2}>opt2</Option>
  641. <Option value={3}>opt3</Option>
  642. <Option value="4">opt4</Option>
  643. <Option value={5}>opt5</Option>
  644. <Option value={6}>opt6</Option>
  645. <Option value={7}>opt7</Option>
  646. <Option value={8}>opt8</Option>
  647. </Select>
  648. <br />
  649. <br />
  650. maxTagCount = 3, max=5
  651. <br />
  652. <Select
  653. multiple={true}
  654. maxTagCount={3}
  655. max={5}
  656. style={{
  657. width: '350px',
  658. }}
  659. defaultValue={[1, 2, 3]}
  660. placeholder="fefe"
  661. insetLabel="标签"
  662. onSelect={(...res) => console.log(res)}
  663. onDeselect={(...res) => console.log(res)}
  664. >
  665. <Option value={1}>opt1</Option>
  666. <Option value={2}>opt2</Option>
  667. <Option value={3}>opt3</Option>
  668. <Option value="4">opt4</Option>
  669. <Option value={5}>opt5</Option>
  670. <Option value={6}>opt6</Option>
  671. <Option value={7}>opt7</Option>
  672. <Option value={8}>opt8</Option>
  673. </Select>
  674. </>
  675. );
  676. SelectMultiple.story = {
  677. name: 'select multiple',
  678. };
  679. SelectMultiple.parameters = {
  680. chromatic: { disableSnapshot: false },
  681. };
  682. export const SelectDisabled = () => (
  683. <Select
  684. disabled
  685. multiple={true}
  686. max={10}
  687. style={{
  688. width: '250px',
  689. }}
  690. >
  691. <Option value={1}>opt1</Option>
  692. <Option value={2} disabled>
  693. opt2
  694. </Option>
  695. <Option value={3}>opt3</Option>
  696. <Option value="4">opt4</Option>
  697. </Select>
  698. );
  699. SelectDisabled.story = {
  700. name: 'select disabled',
  701. };
  702. function filter(input, option) {
  703. console.log(option);
  704. return option.label.includes(input);
  705. }
  706. const spanStyle = {
  707. display: 'inline-block',
  708. marginRight: '8px',
  709. width: '16px',
  710. height: '16px',
  711. borderRadius: '50%',
  712. border: '1px solid var(--semi-color-bg-1)',
  713. };
  714. const colorOptions = [
  715. {
  716. value: 'grey-1',
  717. spanStyle: { ...spanStyle, backgroundColor: 'rgb(107, 116, 117)' },
  718. },
  719. {
  720. value: 'purple-5',
  721. spanStyle: { ...spanStyle, backgroundColor: 'rgb(158, 40, 179)' },
  722. },
  723. {
  724. value: 'pink-2',
  725. spanStyle: { ...spanStyle, backgroundColor: 'rgb(233, 30, 99)' },
  726. },
  727. {
  728. value: 'blue-3',
  729. spanStyle: { ...spanStyle, backgroundColor: 'rgb(0, 119, 250)' },
  730. },
  731. ];
  732. const alignStyle = {
  733. display: 'flex',
  734. alignItems: 'center',
  735. };
  736. const customFilter = (input, option) => {
  737. return option.value.includes(input);
  738. };
  739. export const SelectFilterSingle = () => (
  740. <div>
  741. <h5>默认筛选</h5>
  742. <Select
  743. filter
  744. style={{
  745. width: '250px',
  746. margin: 10,
  747. }}
  748. showClear
  749. autoFocus
  750. onSearch={(val) => console.log(`onSearch:${val}`)}
  751. onFocus={() => console.log('onFocus')}
  752. onBlur={() => console.log('onBlur')}
  753. >
  754. <Option value={1}>opt1</Option>
  755. <Option value={2} disabled>
  756. disabled
  757. </Option>
  758. <Option value={3}>Lucy</Option>
  759. <Option value="4">bay</Option>
  760. <Option value="5">sert</Option>
  761. <Option value="6">wym</Option>
  762. <Option value="7" disabled>
  763. meno
  764. </Option>
  765. <Option value="8">opts</Option>
  766. </Select>
  767. <h5>自定义筛选函数</h5>
  768. <Select
  769. style={{
  770. width: '250px',
  771. margin: 10,
  772. }}
  773. filter={filter}
  774. showClear
  775. onBlur={() => console.log('onBlur')}
  776. onSearch={val => console.log(val)}
  777. onFocus={() => console.log('onFocus')}
  778. >
  779. <Option value={1}>opt1(value:1)</Option>
  780. <Option value={2}>mike(value:2)</Option>
  781. <Option value={3}>Lucy(value:3)</Option>
  782. <Option value={4}>bay(value:4)</Option>
  783. </Select>
  784. <h5>filter为true,但option label为node时</h5>
  785. <Select
  786. style={{
  787. width: '250px',
  788. margin: 10,
  789. }}
  790. showClear
  791. filter={customFilter}
  792. onChange={v => console.log(v)}
  793. insetLabel="insetLabel"
  794. onFocus={() => console.log('onFocus')}
  795. onBlur={() => console.log('onBlur')}
  796. onSearch={(val) => console.log(val)}
  797. >
  798. {colorOptions.map(option => (
  799. <Option value={option.value} key={option.value}>
  800. <div style={alignStyle}>
  801. <span style={option.spanStyle}></span>
  802. {option.value}
  803. </div>
  804. </Option>
  805. ))}
  806. </Select>
  807. </div>
  808. );
  809. SelectFilterSingle.story = {
  810. name: 'select filter single',
  811. };
  812. export const SelectFilterMultiple = () => (
  813. <>
  814. <Select
  815. filter
  816. multiple={true}
  817. style={{
  818. width: '250px',
  819. }}
  820. placeholder="fefe"
  821. >
  822. <Option value={1}>opt1</Option>
  823. <Option value={2}>opt2</Option>
  824. <Option value={3}>opt22</Option>
  825. <Option value={3}>opt3</Option>
  826. <Option value={4}>opt4</Option>
  827. <Option value={5}>opt5</Option>
  828. <Option value={6}>opt6</Option>
  829. <Option value={7}>opt7</Option>
  830. <Option value={8}>opt8</Option>
  831. </Select>
  832. <Select
  833. filter
  834. multiple={true}
  835. maxTagCount={3}
  836. style={{
  837. width: '270px',
  838. }}
  839. placeholder="fefe"
  840. >
  841. <Option value={1}>opt1</Option>
  842. <Option value={2}>opt2</Option>
  843. <Option value={3}>opt22</Option>
  844. <Option value={3}>opt3</Option>
  845. <Option value={4}>opt4</Option>
  846. <Option value={5}>opt5</Option>
  847. <Option value={6}>opt6</Option>
  848. <Option value={7}>opt7</Option>
  849. <Option value={8}>opt8</Option>
  850. </Select>
  851. </>
  852. );
  853. SelectFilterMultiple.story = {
  854. name: 'select filter multiple',
  855. };
  856. const OptionLabelProp = () => {
  857. const [value, setValue] = useState(1);
  858. return (
  859. <>
  860. 设置optionLabelProp属性(默认为'children')为'value'时,回填到选择框中的文本会是Option.value
  861. <br></br>
  862. <Select
  863. style={{
  864. width: '250px',
  865. }}
  866. defaultValue={1}
  867. optionLabelProp="value"
  868. >
  869. <Option value={1}>opt1</Option>
  870. <Option value={2}>opt2</Option>
  871. <Option value={3}>
  872. <span
  873. style={{
  874. color: 'pink',
  875. }}
  876. >
  877. opt3 Node
  878. </span>
  879. </Option>
  880. <Option value="4">
  881. <span
  882. style={{
  883. color: 'red',
  884. }}
  885. >
  886. testNode
  887. </span>
  888. </Option>
  889. </Select>
  890. <br />
  891. <br />
  892. <Select
  893. style={{
  894. width: '250px',
  895. }}
  896. value={value}
  897. optionLabelProp="value"
  898. onChange={setValue}
  899. >
  900. <Option value={1}>opt1</Option>
  901. <Option value={2}>opt2</Option>
  902. <Option value={3}>
  903. <span
  904. style={{
  905. color: 'pink',
  906. }}
  907. >
  908. opt3 Node
  909. </span>
  910. </Option>
  911. <Option value="4">
  912. <span
  913. style={{
  914. color: 'red',
  915. }}
  916. >
  917. testNode
  918. </span>
  919. </Option>
  920. </Select>
  921. <br />
  922. <br />
  923. <Select
  924. style={{
  925. width: '250px',
  926. }}
  927. defaultValue={1}
  928. >
  929. <Option value={1}>children Label Text 1</Option>
  930. <Option value={2}>opt2</Option>
  931. <Option value={3}>opt3</Option>
  932. <Option value="4">
  933. <span
  934. style={{
  935. color: 'red',
  936. }}
  937. >
  938. testNode
  939. </span>
  940. </Option>
  941. </Select>
  942. <Select
  943. style={{
  944. width: '250px',
  945. }}
  946. defaultValue={1}
  947. filter
  948. optionLabelProp="value"
  949. >
  950. <Option value={1}>children Label Text 1</Option>
  951. <Option value={2}>opt2</Option>
  952. <Option value={3}>opt3</Option>
  953. <Option value="4">
  954. <span
  955. style={{
  956. color: 'red',
  957. }}
  958. >
  959. testNode
  960. </span>
  961. </Option>
  962. </Select>
  963. <br />
  964. <br />
  965. 多选
  966. <Select
  967. style={{
  968. width: '250px',
  969. }}
  970. multiple
  971. filter
  972. optionLabelProp="value"
  973. >
  974. <Option value={1}>children Label Text 1</Option>
  975. <Option value={2}>opt2</Option>
  976. <Option value={3}>opt3</Option>
  977. <Option value="4">
  978. <span
  979. style={{
  980. color: 'red',
  981. }}
  982. >
  983. testNode
  984. </span>
  985. </Option>
  986. </Select>
  987. </>
  988. );
  989. };
  990. class CustomRender extends React.Component {
  991. constructor() {
  992. super();
  993. this.state = {
  994. list: [
  995. {
  996. name: '夏可漫',
  997. email: '[email protected]',
  998. abbr: 'XK',
  999. color: 'amber',
  1000. },
  1001. {
  1002. name: '申悦',
  1003. email: '[email protected]',
  1004. abbr: 'SY',
  1005. color: 'indigo',
  1006. },
  1007. {
  1008. name: '曲晨一',
  1009. email: '[email protected]',
  1010. abbr: 'CY',
  1011. color: 'blue',
  1012. },
  1013. {
  1014. name: '文嘉茂',
  1015. email: '[email protected]',
  1016. abbr: 'JM',
  1017. color: 'cyan',
  1018. },
  1019. ],
  1020. };
  1021. }
  1022. renderCustomOption(item, index) {
  1023. const optionStyle = {
  1024. display: 'flex',
  1025. };
  1026. return (
  1027. <Option key={index} value={item.name} style={optionStyle} showTick={false} {...item}>
  1028. <Avatar color={item.color} size="small">
  1029. {item.abbr}
  1030. </Avatar>
  1031. <div
  1032. style={{
  1033. marginLeft: 4,
  1034. }}
  1035. >
  1036. <p
  1037. style={{
  1038. fontSize: 14,
  1039. margin: 4,
  1040. }}
  1041. >
  1042. {item.name}
  1043. </p>
  1044. <p
  1045. style={{
  1046. margin: 4,
  1047. }}
  1048. >
  1049. {item.email}
  1050. </p>
  1051. </div>
  1052. </Option>
  1053. );
  1054. }
  1055. renderSelectedItem(optionNode) {
  1056. return (
  1057. <div>
  1058. <Avatar color={optionNode.color} size="small">
  1059. {optionNode.abbr}
  1060. </Avatar>
  1061. <span
  1062. style={{
  1063. margin: 8,
  1064. }}
  1065. >
  1066. {optionNode.email}
  1067. </span>
  1068. </div>
  1069. );
  1070. }
  1071. renderMultipleSelectedItem(optionNode) {
  1072. let content = (
  1073. <div>
  1074. <Avatar color={optionNode.color} size="small">
  1075. {optionNode.abbr}
  1076. </Avatar>
  1077. </div>
  1078. );
  1079. return {
  1080. isRenderInTag: true,
  1081. content,
  1082. };
  1083. }
  1084. renderMultipleWithoutTag(optionNode) {
  1085. let content = (
  1086. <div>
  1087. <Avatar color={optionNode.color} size="small">
  1088. {optionNode.abbr}
  1089. </Avatar>
  1090. </div>
  1091. );
  1092. return {
  1093. isRenderInTag: false,
  1094. content,
  1095. };
  1096. }
  1097. render() {
  1098. const { list } = this.state;
  1099. return (
  1100. <React.Fragment>
  1101. <Select
  1102. style={{
  1103. width: 300,
  1104. height: 40,
  1105. }}
  1106. onChange={this.provinceChange}
  1107. defaultValue={'夏可漫'}
  1108. renderSelectedItem={this.renderSelectedItem}
  1109. >
  1110. {list.map((item, index) => this.renderCustomOption(item, index))}
  1111. </Select>
  1112. <Select
  1113. style={{
  1114. width: 360,
  1115. height: 60,
  1116. marginTop: 20,
  1117. }}
  1118. onChange={this.provinceChange}
  1119. defaultValue={['夏可漫', '申悦']}
  1120. multiple
  1121. renderSelectedItem={this.renderMultipleSelectedItem}
  1122. >
  1123. {list.map((item, index) => this.renderCustomOption(item, index))}
  1124. </Select>
  1125. <Select
  1126. style={{
  1127. width: 360,
  1128. height: 60,
  1129. marginTop: 20,
  1130. }}
  1131. onChange={this.provinceChange}
  1132. defaultValue={['夏可漫', '申悦']}
  1133. multiple
  1134. renderSelectedItem={this.renderMultipleWithoutTag}
  1135. >
  1136. {list.map((item, index) => this.renderCustomOption(item, index))}
  1137. </Select>
  1138. </React.Fragment>
  1139. );
  1140. }
  1141. }
  1142. export const RenderSelectedItem = () => (
  1143. <>
  1144. renderSelectedItem
  1145. <CustomRender />
  1146. <br />
  1147. <br />
  1148. OptionLabelProp
  1149. <OptionLabelProp />
  1150. </>
  1151. );
  1152. RenderSelectedItem.story = {
  1153. name: 'renderSelectedItem',
  1154. };
  1155. RenderSelectedItem.parameters = {
  1156. chromatic: { disableSnapshot: false },
  1157. };
  1158. const ControlledSelect = () => {
  1159. const [value, setValue] = useState('nick');
  1160. const [value2, setValue2] = useState('jerry');
  1161. const [value3, setValue3] = useState();
  1162. const [value4, setValue4] = useState(['nick']);
  1163. const [value5, setValue5] = useState();
  1164. return (
  1165. <>
  1166. <span>value + onChange</span>
  1167. <Select
  1168. value={value}
  1169. onChange={setValue}
  1170. style={{
  1171. width: 200,
  1172. }}
  1173. >
  1174. <Option value="nick">nick</Option>
  1175. <Option value="jerry">jerry</Option>
  1176. <Option value="mark">mark</Option>
  1177. </Select>
  1178. <br />
  1179. <br />
  1180. <span>只传value,不传onChange</span>
  1181. <Select
  1182. value={value2}
  1183. style={{
  1184. width: 200,
  1185. }}
  1186. >
  1187. <Option value="nick">nick</Option>
  1188. <Option value="jerry">jerry</Option>
  1189. <Option value="mark">mark</Option>
  1190. </Select>
  1191. <br />
  1192. <br />
  1193. <span>value + onChange , 多选</span>
  1194. <Select
  1195. value={value3}
  1196. onChange={setValue3}
  1197. multiple
  1198. style={{
  1199. width: 200,
  1200. }}
  1201. >
  1202. <Option value="nick">nick</Option>
  1203. <Option value="jerry">jerry</Option>
  1204. <Option value="mark">mark</Option>
  1205. <Option value="nick2">nick2</Option>
  1206. <Option value="jerry2">jerry2</Option>
  1207. <Option value="mark2">mark2</Option>
  1208. </Select>
  1209. <br />
  1210. <br />
  1211. <span>value, 多选</span>
  1212. <Select
  1213. value={value4}
  1214. multiple
  1215. style={{
  1216. width: 200,
  1217. }}
  1218. >
  1219. <Option value="nick">nick</Option>
  1220. <Option value="jerry">jerry</Option>
  1221. <Option value="mark">mark</Option>
  1222. </Select>
  1223. <br />
  1224. <h5>filter为true,但option label为node时</h5>
  1225. <Select
  1226. style={{
  1227. width: '250px',
  1228. }}
  1229. filter={customFilter}
  1230. insetLabel="insetLabel"
  1231. value={value5}
  1232. onChange={setValue5}
  1233. >
  1234. {colorOptions.map(option => (
  1235. <Option value={option.value} key={option.value}>
  1236. <div style={alignStyle}>
  1237. <span style={option.spanStyle}></span>
  1238. {option.value}
  1239. </div>
  1240. </Option>
  1241. ))}
  1242. </Select>
  1243. </>
  1244. );
  1245. };
  1246. export const Controlled = () => <ControlledSelect></ControlledSelect>;
  1247. Controlled.story = {
  1248. name: 'controlled',
  1249. };
  1250. const UnControlledSelect = () => {
  1251. const onChange = value => {
  1252. console.log(value);
  1253. };
  1254. return (
  1255. <>
  1256. <h5>defaultValue在list中不存在</h5>
  1257. <Select
  1258. defaultValue={90}
  1259. onChange={onChange}
  1260. style={{
  1261. width: 200,
  1262. }}
  1263. >
  1264. <Option value={20}>nick</Option>
  1265. <Option value={10}>jerry</Option>
  1266. <Option value={5}>mark</Option>
  1267. </Select>
  1268. <h5>defaultValue在list中存在</h5>
  1269. <Select
  1270. defaultValue={10}
  1271. onChange={onChange}
  1272. style={{
  1273. width: 200,
  1274. }}
  1275. >
  1276. <Option value={20}>nick</Option>
  1277. <Option value={10}>jerry</Option>
  1278. <Option value={5}>mark</Option>
  1279. </Select>
  1280. </>
  1281. );
  1282. };
  1283. export { UnControlledSelect };
  1284. UnControlledSelect.story = {
  1285. name: '非受控组件'
  1286. };
  1287. export const TestScroll = () => (
  1288. <div
  1289. style={{
  1290. marginTop: '600px',
  1291. marginBottom: '50px',
  1292. }}
  1293. >
  1294. <Select
  1295. style={{
  1296. width: '150px',
  1297. }}
  1298. >
  1299. <Option value="tony">IronMan</Option>
  1300. <Option value="Thor" disabled>
  1301. Thor
  1302. </Option>
  1303. <Option value="steve">Caption</Option>
  1304. <Option value="peter">SpiderBoy</Option>
  1305. </Select>
  1306. </div>
  1307. );
  1308. TestScroll.story = {
  1309. name: 'test scroll',
  1310. };
  1311. let optionList = [
  1312. {
  1313. value: 'tony',
  1314. label: 'Ironman',
  1315. },
  1316. {
  1317. value: 'Thor',
  1318. label: 'Thor',
  1319. },
  1320. {
  1321. value: 'steve',
  1322. label: 'Caption',
  1323. },
  1324. {
  1325. value: 'peter',
  1326. label: 'SpiderBoy',
  1327. },
  1328. ];
  1329. export const OptionList = () => (
  1330. <Select
  1331. style={{
  1332. width: '100px',
  1333. }}
  1334. optionList={optionList}
  1335. ></Select>
  1336. );
  1337. OptionList.story = {
  1338. name: 'optionList',
  1339. };
  1340. export const InsetLabel = () => (
  1341. <>
  1342. <Select
  1343. style={{
  1344. width: 300,
  1345. }}
  1346. insetLabel="主播类型"
  1347. placeholder="请选择"
  1348. optionList={optionList}
  1349. ></Select>
  1350. <Select
  1351. style={{
  1352. width: 300,
  1353. }}
  1354. multiple
  1355. insetLabel="主播类型"
  1356. optionList={optionList}
  1357. ></Select>
  1358. <Select
  1359. style={{
  1360. width: 300,
  1361. }}
  1362. filter
  1363. insetLabel="主播类型"
  1364. optionList={optionList}
  1365. ></Select>
  1366. <Select
  1367. style={{
  1368. width: 300,
  1369. }}
  1370. filter
  1371. multiple
  1372. insetLabel="主播类型"
  1373. optionList={optionList}
  1374. ></Select>
  1375. </>
  1376. );
  1377. InsetLabel.story = {
  1378. name: 'insetLabel',
  1379. };
  1380. export const ChangeOptionDynamic = () => {
  1381. function App() {
  1382. let [options, setOptions] = useState([]);
  1383. let [index, setIndex] = useState(0);
  1384. const addOption = () => {
  1385. const randomItem = optionList[index];
  1386. index = index + 1;
  1387. setIndex(index);
  1388. options = [...options, { ...randomItem }];
  1389. setOptions(options);
  1390. };
  1391. const reset = () => {
  1392. setOptions([]);
  1393. setIndex(0);
  1394. };
  1395. return (
  1396. <div>
  1397. <Select
  1398. style={{
  1399. width: '150px',
  1400. }}
  1401. defaultValue="tony"
  1402. >
  1403. {options.map((option, idx) => (
  1404. <Select.Option key={option.key || idx} value={option.value}>
  1405. {option.label}
  1406. </Select.Option>
  1407. ))}
  1408. </Select>
  1409. <h4>多选</h4>
  1410. <Select
  1411. style={{
  1412. width: '150px',
  1413. }}
  1414. multiple
  1415. defaultValue={['tony']}
  1416. >
  1417. {options.map((option, idx) => (
  1418. <Select.Option key={option.key || idx} value={option.value}>
  1419. {option.label}
  1420. </Select.Option>
  1421. ))}
  1422. </Select>
  1423. <button onClick={addOption}>add option</button>
  1424. <button onClick={reset}>reset</button>
  1425. </div>
  1426. );
  1427. }
  1428. return <App />;
  1429. };
  1430. ChangeOptionDynamic.story = {
  1431. name: 'change option dynamic',
  1432. };
  1433. let list = [
  1434. {
  1435. value: 'tony',
  1436. label: 'Ironman',
  1437. otherKey: {
  1438. role: 1,
  1439. },
  1440. },
  1441. {
  1442. value: 'Thor',
  1443. label: 'Thor',
  1444. otherKey: {
  1445. role: 2,
  1446. },
  1447. },
  1448. {
  1449. value: 'steve',
  1450. label: 'Caption',
  1451. otherKey: {
  1452. role: 3,
  1453. },
  1454. },
  1455. {
  1456. value: 'peter',
  1457. label: 'SpiderBoy',
  1458. otherKey: {
  1459. role: 4,
  1460. },
  1461. },
  1462. ];
  1463. const SearchDemo1 = () => {
  1464. const [optionList, setOptionList] = useState(list);
  1465. const [loading, setLoading] = useState(false);
  1466. const handleSearch = value => {
  1467. setLoading(true);
  1468. let length = Math.ceil(Math.random() * 10);
  1469. let result = Array.from(
  1470. {
  1471. length,
  1472. },
  1473. (v, i) => {
  1474. return {
  1475. value: value + i,
  1476. label: value + i,
  1477. otherKey: {
  1478. role: i,
  1479. },
  1480. };
  1481. }
  1482. );
  1483. setTimeout(() => {
  1484. setOptionList(result);
  1485. setLoading(false);
  1486. }, 1000);
  1487. };
  1488. const [value, setValue] = useState(optionList[0].value);
  1489. const onChange = value => {
  1490. console.log(value);
  1491. setValue(value);
  1492. };
  1493. return (
  1494. <div>
  1495. 受控:
  1496. <Select
  1497. filter
  1498. style={{
  1499. width: '150px',
  1500. }}
  1501. onSearch={v => handleSearch(v)}
  1502. optionList={optionList}
  1503. value={value}
  1504. loading={loading}
  1505. showClear
  1506. onChange={onChange}
  1507. ></Select>
  1508. 非受控:
  1509. <Select
  1510. style={{
  1511. width: '150px',
  1512. }}
  1513. filter
  1514. showClear
  1515. onSearch={v => handleSearch(v)}
  1516. optionList={optionList}
  1517. loading={loading}
  1518. onChange={onChange}
  1519. ></Select>
  1520. 多选非受控
  1521. <Select
  1522. style={{
  1523. width: '150px',
  1524. }}
  1525. showClear
  1526. filter
  1527. multiple
  1528. onSearch={v => handleSearch(v)}
  1529. optionList={optionList}
  1530. loading={loading}
  1531. onChange={onChange}
  1532. ></Select>
  1533. </div>
  1534. );
  1535. };
  1536. import debounce from 'lodash/debounce';
  1537. class SearchDemo2 extends React.Component {
  1538. constructor() {
  1539. super();
  1540. this.state = {
  1541. loading: false,
  1542. optionList: [
  1543. {
  1544. value: 'abc',
  1545. label: '抖音',
  1546. type: 1,
  1547. },
  1548. {
  1549. value: 'hotsoon',
  1550. label: '火山小视频',
  1551. type: 2,
  1552. },
  1553. {
  1554. value: 'pipixia',
  1555. label: '皮皮虾',
  1556. type: 3,
  1557. },
  1558. {
  1559. value: 'toutiao',
  1560. label: '今日头条',
  1561. type: 4,
  1562. },
  1563. ],
  1564. value: [],
  1565. };
  1566. this.handleSearch = debounce(this.handleSearch, 800).bind(this);
  1567. this.onChange = this.onChange.bind(this);
  1568. this.customRender = this.customRender.bind(this);
  1569. }
  1570. handleSearch(inputValue) {
  1571. this.setState({
  1572. loading: true,
  1573. });
  1574. let length = Math.ceil(Math.random() * 100);
  1575. let result = Array.from(
  1576. {
  1577. length,
  1578. },
  1579. (v, i) => {
  1580. return {
  1581. value: inputValue + i,
  1582. label: 'label' + i,
  1583. type: i + 1,
  1584. };
  1585. }
  1586. );
  1587. setTimeout(() => {
  1588. this.setState({
  1589. optionList: result,
  1590. loading: false,
  1591. });
  1592. }, 2000);
  1593. }
  1594. onChange(value) {
  1595. this.setState({
  1596. value,
  1597. });
  1598. console.log(value);
  1599. }
  1600. customRender(optionNode) {
  1601. return optionNode.value + optionNode.label;
  1602. }
  1603. render() {
  1604. const { loading, optionList, value } = this.state;
  1605. return (
  1606. <div>
  1607. <Select
  1608. style={{
  1609. width: 150,
  1610. }}
  1611. showClear
  1612. filter
  1613. labelInValue
  1614. onSearch={this.handleSearch}
  1615. optionList={optionList}
  1616. loading={loading}
  1617. onChange={this.onChange}
  1618. placeholder="请选择"
  1619. ></Select>
  1620. <br />
  1621. <br />
  1622. <Select
  1623. style={{
  1624. width: 180,
  1625. }}
  1626. filter // labelInValue
  1627. showClear
  1628. multiple
  1629. value={value}
  1630. renderSelectedItem={this.customRender}
  1631. onSearch={this.handleSearch}
  1632. optionList={optionList}
  1633. loading={loading}
  1634. onChange={this.onChange}
  1635. placeholder="请选择"
  1636. ></Select>
  1637. </div>
  1638. );
  1639. }
  1640. }
  1641. export const Search = () => (
  1642. <>
  1643. <SearchDemo1 />
  1644. <SearchDemo2 />
  1645. </>
  1646. );
  1647. Search.story = {
  1648. name: 'search',
  1649. };
  1650. export const IncomeDetail = ({ config = {}, params = {} }) => {
  1651. const [detailList, setDetailList] = useState([]);
  1652. const [hasMore, setHasMore] = useState(true);
  1653. const [loading, setLoading] = useState();
  1654. let lock;
  1655. const fetchData = (outParams = {}) => {
  1656. if (lock) {
  1657. return;
  1658. }
  1659. setLoading(true); // 参数
  1660. // 请求
  1661. fetch({
  1662. url: URL.user_profit,
  1663. method: 'get',
  1664. baseURL: config.webcast_host,
  1665. params,
  1666. })
  1667. .then(res => {
  1668. lock = false;
  1669. setLoading(false);
  1670. console.log('++++', data);
  1671. })
  1672. .catch(() => {
  1673. setLoading(false);
  1674. Toast.show('网络异常,请稍后重试');
  1675. });
  1676. };
  1677. useEffect(fetchData, []); // 监听滚动设置吸顶 以及加载更多
  1678. useEffect(() => {
  1679. window.addEventListener('scroll', function() {
  1680. // 加载更多
  1681. const scrollY = window.scrollY;
  1682. const scrollHeight = document.documentElement.scrollHeight;
  1683. const screenHeight = screen.height;
  1684. if (!loading && hasMore && scrollY + screenHeight + 300 > scrollHeight) {
  1685. fetchData();
  1686. }
  1687. });
  1688. }, [detailList.length]);
  1689. return (
  1690. <div>
  1691. <Select></Select>
  1692. </div>
  1693. );
  1694. };
  1695. export const AllowCreate = () => (
  1696. <Select
  1697. style={{
  1698. width: 500,
  1699. }}
  1700. optionList={optionList}
  1701. allowCreate={true}
  1702. multiple={true}
  1703. filter={true}
  1704. onChange={v => console.log(v)}
  1705. ></Select>
  1706. );
  1707. AllowCreate.story = {
  1708. name: 'allowCreate',
  1709. };
  1710. export const AllowCreateCustomRender = () => (
  1711. <Select
  1712. style={{
  1713. width: 500,
  1714. }}
  1715. optionList={optionList}
  1716. allowCreate={true}
  1717. multiple={true}
  1718. filter={true}
  1719. onChange={v => console.log(v)}
  1720. renderCreateItem={v => `semi: ${v}`}
  1721. ></Select>
  1722. );
  1723. AllowCreateCustomRender.story = {
  1724. name: 'allowCreate custom render',
  1725. };
  1726. let AllowCreateControlledDemo = () => {
  1727. let [value, setValue] = useState();
  1728. const optionList = [
  1729. {
  1730. value: 'abc',
  1731. label: '抖音',
  1732. },
  1733. {
  1734. value: 'hotsoon',
  1735. label: '火山小视频',
  1736. },
  1737. {
  1738. value: 'pipixia',
  1739. label: '皮皮虾',
  1740. },
  1741. {
  1742. value: 'toutiao',
  1743. label: '今日头条',
  1744. },
  1745. ];
  1746. const [list, setList] = useState(optionList);
  1747. const handleSelect = v => {
  1748. var lastOne = v[v.length - 1];
  1749. if (lastOne && list.findIndex(item => item.value === lastOne) == -1) {
  1750. list.push({
  1751. value: lastOne,
  1752. label: lastOne,
  1753. });
  1754. }
  1755. setList(list);
  1756. setValue(v);
  1757. };
  1758. return (
  1759. <Select
  1760. style={{
  1761. width: 400,
  1762. }}
  1763. optionList={list}
  1764. allowCreate={true}
  1765. multiple={true}
  1766. filter={true}
  1767. value={value}
  1768. onChange={handleSelect}
  1769. ></Select>
  1770. );
  1771. };
  1772. const AllowCreateDemo = () => {
  1773. let [value, setValue] = useState();
  1774. const optionList = [
  1775. {
  1776. value: 'abc',
  1777. label: '抖音',
  1778. },
  1779. {
  1780. value: 'hotsoon',
  1781. label: '火山小视频',
  1782. },
  1783. {
  1784. value: 'pipixia',
  1785. label: '皮皮虾',
  1786. },
  1787. {
  1788. value: 'toutiao',
  1789. label: '今日头条',
  1790. },
  1791. ];
  1792. const [list, setList] = useState(optionList);
  1793. const handleSelect = v => {
  1794. var lastOne = v[v.length - 1];
  1795. if (lastOne && list.findIndex(item => item.value === lastOne) == -1) {
  1796. list.push({
  1797. value: lastOne,
  1798. label: lastOne,
  1799. });
  1800. }
  1801. setList(list); // setValue(v)
  1802. };
  1803. return (
  1804. <Select
  1805. style={{
  1806. width: 400,
  1807. }}
  1808. optionList={list}
  1809. defaultValue={['abc', 'hotsoon']}
  1810. allowCreate={true}
  1811. multiple={true}
  1812. filter={true}
  1813. onChange={handleSelect}
  1814. ></Select>
  1815. );
  1816. };
  1817. export const AllowCreateWithDefaultValue = () => <AllowCreateDemo />;
  1818. AllowCreateWithDefaultValue.story = {
  1819. name: 'allowCreate with defaultValue',
  1820. };
  1821. class HideDemo extends React.Component {
  1822. constructor(props) {
  1823. super(props);
  1824. this.state = {
  1825. optionList: [
  1826. {
  1827. value: 'abc',
  1828. label: '抖音',
  1829. },
  1830. {
  1831. value: 'hotsoon',
  1832. label: '火山小视频',
  1833. },
  1834. {
  1835. value: 'pipixia',
  1836. label: '皮皮虾',
  1837. },
  1838. {
  1839. value: 'toutiao',
  1840. label: '今日头条',
  1841. },
  1842. ],
  1843. selectedItems: [],
  1844. };
  1845. this.onChange = this.onChange.bind(this);
  1846. }
  1847. onChange(selectedItems) {
  1848. this.setState({
  1849. selectedItems,
  1850. });
  1851. }
  1852. render() {
  1853. let { optionList, selectedItems } = this.state;
  1854. let filterOptions = optionList.filter(option => !selectedItems.includes(option.value));
  1855. return (
  1856. <Select
  1857. value={selectedItems}
  1858. multiple
  1859. style={{
  1860. width: 300,
  1861. }}
  1862. onChange={this.onChange}
  1863. optionList={filterOptions}
  1864. ></Select>
  1865. );
  1866. }
  1867. }
  1868. export const AutoHiddenSelectedItem = () => <HideDemo></HideDemo>;
  1869. AutoHiddenSelectedItem.story = {
  1870. name: 'auto hidden selected item',
  1871. };
  1872. class CustomCreate extends React.Component {
  1873. constructor(props) {
  1874. super(props);
  1875. this.state = {
  1876. optionList: [
  1877. {
  1878. value: 'abc',
  1879. label: '抖音',
  1880. },
  1881. {
  1882. value: 'hotsoon',
  1883. label: '火山小视频',
  1884. },
  1885. {
  1886. value: 'pipixia',
  1887. label: '皮皮虾',
  1888. },
  1889. {
  1890. value: 'toutiao',
  1891. label: '今日头条',
  1892. },
  1893. {
  1894. value: 0,
  1895. label: 0,
  1896. },
  1897. ],
  1898. selectedItems: ['fefe'],
  1899. };
  1900. this.onChange = this.onChange.bind(this);
  1901. this.customRender = this.customRender.bind(this);
  1902. this.search = this.search.bind(this);
  1903. }
  1904. onChange(selectedItems) {
  1905. console.log(selectedItems); // this.setState({ selectedItems, optionList: [] });
  1906. this.setState({
  1907. selectedItems,
  1908. }); // this.setState({ optionList: [] });
  1909. }
  1910. customRender(v) {
  1911. return (
  1912. <>
  1913. <span>label:{v.label}</span>
  1914. <span>value:{v.value}</span>
  1915. </>
  1916. );
  1917. }
  1918. customCreate(inputValue, isFocus) {
  1919. let style = {
  1920. padding: 12,
  1921. cursor: 'pointer',
  1922. backgroundColor: isFocus ? 'var(--semi-color-fill-0)' : '#FFF',
  1923. };
  1924. return <div style={style}>{'create' + inputValue}</div>;
  1925. }
  1926. search(inputValue) {
  1927. let length = Math.ceil(Math.random() * 10);
  1928. let result = Array.from(
  1929. {
  1930. length,
  1931. },
  1932. (v, i) => {
  1933. return {
  1934. value: inputValue + i,
  1935. label: inputValue + i,
  1936. type: i + 1,
  1937. };
  1938. }
  1939. );
  1940. console.log(result); // result = result.concat(selectedOption);
  1941. this.setState({
  1942. optionList: result,
  1943. });
  1944. }
  1945. render() {
  1946. let { optionList, selectedItems } = this.state;
  1947. return (
  1948. <>
  1949. <Select
  1950. defaultValue={['abc']}
  1951. filter
  1952. style={{
  1953. width: 300,
  1954. }}
  1955. multiple
  1956. optionList={optionList}
  1957. onSearch={this.search}
  1958. onChange={this.onChange}
  1959. emptyContent={null} // onChangeWithObject
  1960. ></Select>
  1961. </>
  1962. );
  1963. }
  1964. }
  1965. export const _CustomCreate = () => <CustomCreate></CustomCreate>;
  1966. _CustomCreate.story = {
  1967. name: 'CustomCreate',
  1968. };
  1969. class OptionGroupDemo extends React.Component {
  1970. constructor(props) {
  1971. super(props);
  1972. this.handleSearch = this.handleSearch.bind(this);
  1973. this.state = {
  1974. groups: [
  1975. {
  1976. label: 'Asia',
  1977. children: [
  1978. {
  1979. label: 'China',
  1980. value: 'zhongguo',
  1981. },
  1982. {
  1983. label: 'Koera',
  1984. value: 'hanguo',
  1985. },
  1986. ],
  1987. },
  1988. {
  1989. label: 'Europe',
  1990. children: [
  1991. {
  1992. label: 'Germany',
  1993. value: 'deguo',
  1994. },
  1995. {
  1996. label: 'France',
  1997. value: 'faguo',
  1998. },
  1999. ],
  2000. },
  2001. {
  2002. label: 'Other',
  2003. children: [
  2004. {
  2005. label: 'vf',
  2006. value: 'Sourth',
  2007. },
  2008. ],
  2009. },
  2010. ],
  2011. };
  2012. }
  2013. handleSearch(input) {
  2014. let groups = [1, 2, 3].map(i => {
  2015. return {
  2016. label: i,
  2017. // label: Math.random(),
  2018. children: [10, 20].map(j => {
  2019. return {
  2020. label: Math.random(),
  2021. value: Math.random(),
  2022. };
  2023. }),
  2024. };
  2025. });
  2026. this.setState({
  2027. groups,
  2028. });
  2029. }
  2030. renderGroup(group, index) {
  2031. const options = group.children.map(option => (
  2032. <Select.Option value={option.value} label={option.label} key={option.label} />
  2033. ));
  2034. return <Select.OptGroup key={`${index}-${group.label}`} label={group.label}>{options}</Select.OptGroup>;
  2035. }
  2036. render() {
  2037. const { groups } = this.state;
  2038. return (
  2039. <>
  2040. <Select
  2041. placeholder=""
  2042. style={{
  2043. width: 180,
  2044. }}
  2045. filter
  2046. onSearch={this.handleSearch}
  2047. remote
  2048. >
  2049. {groups.map((group, index) => this.renderGroup(group, index))}
  2050. </Select>
  2051. </>
  2052. );
  2053. }
  2054. }
  2055. export const SelectOptionGroup = () => <OptionGroupDemo />;
  2056. SelectOptionGroup.story = {
  2057. name: 'Select OptionGroup',
  2058. };
  2059. const BlurDemo = () => {
  2060. const onBlur = (value, e) => {
  2061. console.log(value);
  2062. console.log(e);
  2063. };
  2064. const onFocus = (value, e) => {
  2065. console.log(value);
  2066. console.log(e);
  2067. };
  2068. return (
  2069. <>
  2070. <Select
  2071. filter
  2072. placeholder=""
  2073. style={{
  2074. width: 180,
  2075. }}
  2076. onBlur={onBlur}
  2077. onFocus={onFocus}
  2078. >
  2079. <Select.Option value="zhongguo">China</Select.Option>
  2080. <Select.Option value="hanguo">Koera</Select.Option>
  2081. <Select.Option value="deguo">Germany</Select.Option>
  2082. <Select.Option value="faguo">France</Select.Option>
  2083. </Select>
  2084. </>
  2085. );
  2086. };
  2087. export const SelectOnBlurOnFocus = () => <BlurDemo></BlurDemo>;
  2088. SelectOnBlurOnFocus.story = {
  2089. name: 'Select onBlur/onFocus',
  2090. };
  2091. const AutoAdjustOverflowDemo = () => {
  2092. const [list, setList] = useState([
  2093. {
  2094. value: 'abc',
  2095. label: '1111',
  2096. },
  2097. {
  2098. value: 'hotsoon',
  2099. label: '1112',
  2100. },
  2101. {
  2102. value: 'pipixia',
  2103. label: '1113',
  2104. },
  2105. {
  2106. value: 'toutiao',
  2107. label: '1114',
  2108. },
  2109. ]);
  2110. const onSearch = () => {
  2111. let newList = Array.from(
  2112. {
  2113. length: Math.floor(Math.random() * 10),
  2114. },
  2115. (v, i) => {
  2116. return {
  2117. value: i,
  2118. label: i,
  2119. };
  2120. }
  2121. );
  2122. setList(newList);
  2123. console.log(newList);
  2124. };
  2125. return (
  2126. <div
  2127. style={{
  2128. height: 180,
  2129. margin: 250,
  2130. border: '1px solid pink',
  2131. }}
  2132. >
  2133. <Select
  2134. optionList={list}
  2135. filter={true}
  2136. remote={true}
  2137. onSearch={onSearch}
  2138. style={{
  2139. width: 200,
  2140. }}
  2141. multiple
  2142. />
  2143. </div>
  2144. );
  2145. };
  2146. export const AutoAdjustOverflow = () => <AutoAdjustOverflowDemo></AutoAdjustOverflowDemo>;
  2147. AutoAdjustOverflow.story = {
  2148. name: 'autoAdjustOverflow',
  2149. };
  2150. const AllowCreateWithFilter = () => {
  2151. const [list, setList] = useState([
  2152. {
  2153. value: 'abc',
  2154. label: 'abc',
  2155. otherKey: 'abc',
  2156. },
  2157. {
  2158. value: 'hotsoon',
  2159. label: 'hotsoon',
  2160. otherKey: 'efg',
  2161. },
  2162. {
  2163. value: 'pipixia',
  2164. label: 'pipixia',
  2165. otherKey: 'hij',
  2166. },
  2167. {
  2168. value: 'toutiao',
  2169. label: 'toutiao',
  2170. otherKey: 'klm',
  2171. },
  2172. ]);
  2173. const filter = (sugInput, option) => {
  2174. let compareKey = option.otherKey ? option.otherKey.toUpperCase() : '';
  2175. let sug = sugInput.toUpperCase();
  2176. return compareKey.includes(sug);
  2177. };
  2178. return (
  2179. <div
  2180. style={{
  2181. height: 180,
  2182. margin: 250,
  2183. }}
  2184. >
  2185. <Select
  2186. optionList={list}
  2187. multiple
  2188. filter={filter}
  2189. style={{
  2190. width: 200,
  2191. }}
  2192. allowCreate
  2193. />
  2194. </div>
  2195. );
  2196. };
  2197. export const FilterAllowCreate = () => <AllowCreateWithFilter></AllowCreateWithFilter>;
  2198. FilterAllowCreate.story = {
  2199. name: 'Filter + allowCreate',
  2200. };
  2201. const SelectRefDemo = () => {
  2202. const ref = useRef();
  2203. const secondRef = useRef();
  2204. const [open, setOpen] = useState(false);
  2205. const list = [
  2206. {
  2207. value: 'abc',
  2208. label: 'Abc',
  2209. },
  2210. {
  2211. value: 'hotsoon',
  2212. label: 'Hotsoon',
  2213. },
  2214. {
  2215. value: 'pipixia',
  2216. label: 'Pipixia',
  2217. },
  2218. {
  2219. value: 'toutiao',
  2220. label: 'TooBuzz',
  2221. },
  2222. ];
  2223. const change = () => {
  2224. if (!open) {
  2225. ref.current.open();
  2226. setOpen(true);
  2227. } else {
  2228. ref.current.close();
  2229. setOpen(false);
  2230. }
  2231. };
  2232. const focus = () => {
  2233. ref.current.focus();
  2234. };
  2235. const clearInput = () => {
  2236. ref.current.clearInput();
  2237. };
  2238. const deselectAll = () => {
  2239. ref.current.deselectAll();
  2240. };
  2241. const selectAll = () => {
  2242. ref.current.selectAll();
  2243. };
  2244. return (
  2245. <>
  2246. <h4>onChangeWithObject = false</h4>
  2247. <Select
  2248. innerBottomSlot={
  2249. <div>
  2250. <Space>
  2251. <Button onClick={change}>close</Button>
  2252. <Button onClick={clearInput}>clearInput</Button>
  2253. <Button onClick={deselectAll}>deselectAll</Button>
  2254. <Button onClick={selectAll}>selectAll</Button>
  2255. </Space>
  2256. </div>
  2257. }
  2258. ref={ref}
  2259. onChange={e => console.log(e)}
  2260. placeholder="Business line"
  2261. style={{
  2262. width: 180,
  2263. }}
  2264. optionList={list}
  2265. filter
  2266. multiple
  2267. ></Select>
  2268. <Space>
  2269. <Button onClick={change}>open</Button>
  2270. <Button onClick={focus}>focus</Button>
  2271. <Button onClick={clearInput}>clearInput</Button>
  2272. <Button onClick={deselectAll}>deselectAll</Button>
  2273. <Button onClick={selectAll}>selectAll</Button>
  2274. </Space>
  2275. <h4
  2276. style={{
  2277. marginTop: 20,
  2278. }}
  2279. >
  2280. onChangeWithObject = true
  2281. </h4>
  2282. <Select
  2283. innerBottomSlot={
  2284. <div>
  2285. <Space></Space>
  2286. </div>
  2287. }
  2288. onChange={e => console.log(e)}
  2289. onChangeWithObject
  2290. ref={secondRef}
  2291. placeholder="Business line"
  2292. style={{
  2293. width: 180,
  2294. }}
  2295. optionList={list}
  2296. filter
  2297. multiple
  2298. ></Select>
  2299. <Space>
  2300. <Button onClick={() => secondRef.current.deselectAll()}>deselectAll</Button>
  2301. <Button onClick={() => secondRef.current.selectAll()}>selectAll</Button>
  2302. </Space>
  2303. </>
  2304. );
  2305. };
  2306. export const Ref = () => <SelectRefDemo />;
  2307. Ref.story = {
  2308. name: 'ref',
  2309. };
  2310. export const CustomTriggerDemo = () => <CustomTrigger />;
  2311. CustomTriggerDemo.story = {
  2312. name: 'custom trigger'
  2313. }
  2314. class VirtualizeClassDemo extends React.Component {
  2315. constructor(props) {
  2316. super(props);
  2317. // this.handleSearch = this.handleSearch.bind(this);
  2318. let newOptions = Array.from({ length: 1000 }, (v, i) => ({ label: `o-${i}`, value: `v-${v}-${i}` }));
  2319. this.state = {
  2320. optionList: newOptions,
  2321. };
  2322. }
  2323. render() {
  2324. let { groups, optionList } = this.state;
  2325. let virtualize = {
  2326. height: 300,
  2327. widht: '100%',
  2328. itemSize: 36,
  2329. };
  2330. return (
  2331. <>
  2332. <Select
  2333. placeholder=""
  2334. style={{ width: 180 }}
  2335. filter
  2336. onSearch={this.handleSearch}
  2337. virtualize={virtualize}
  2338. optionList={optionList}
  2339. ></Select>
  2340. </>
  2341. );
  2342. }
  2343. }
  2344. export const VirtualizeDemo = () => <VirtualizeClassDemo />;
  2345. VirtualizeDemo.story = {
  2346. name: 'virtualize select'
  2347. }
  2348. const SelectPosition = () => {
  2349. return (
  2350. <div
  2351. style={{
  2352. height: 500,
  2353. border: '1px solid red',
  2354. overflow: 'auto',
  2355. }}
  2356. >
  2357. <p>p</p>
  2358. <p>p</p>
  2359. <p>p</p>
  2360. <p>p</p>
  2361. <p>p</p>
  2362. <p>p</p>
  2363. <p>p</p>
  2364. <p>p</p>
  2365. <p>p</p>
  2366. <p>p</p>
  2367. <p>p</p>
  2368. <p>p</p>
  2369. <p>p</p>
  2370. <p>p</p>
  2371. <p>p</p>
  2372. <p>p</p>
  2373. <p>p</p>
  2374. <p>p</p>
  2375. <p>p</p>
  2376. <p>p</p>
  2377. <p>p</p>
  2378. <p>p</p>
  2379. <p>p</p>
  2380. <Select
  2381. defaultValue="abc"
  2382. style={{
  2383. width: 120,
  2384. }}
  2385. >
  2386. <Option value="abc">抖音</Option>
  2387. <Option value="hotsoon">火山</Option>
  2388. <Option value="pipixia" disabled>
  2389. 皮皮虾
  2390. </Option>
  2391. <Option value="xigua">西瓜视频</Option>
  2392. </Select>
  2393. <p>p</p>
  2394. <p>p</p>
  2395. <p>p</p>
  2396. <p>p</p>
  2397. <p>p</p>
  2398. <p>p</p>
  2399. <p>p</p>
  2400. <p>p</p>
  2401. <p>p</p>
  2402. <p>p</p>
  2403. <p>p</p>
  2404. <p>p</p>
  2405. <p>p</p>
  2406. <p>p</p>
  2407. <p>p</p>
  2408. <p>p</p>
  2409. <p>p</p>
  2410. <p>p</p>
  2411. <p>p</p>
  2412. <p>p</p>
  2413. <p>p</p>
  2414. <p>p</p>
  2415. <p>p</p>
  2416. <p>p</p>
  2417. <p>p</p>
  2418. <p>p</p>
  2419. <p>p</p>
  2420. <p>p</p>
  2421. <p>p</p>
  2422. <p>p</p>
  2423. <p>p</p>
  2424. <p>p</p>
  2425. <p>p</p>
  2426. <p>p</p>
  2427. <p>p</p>
  2428. <p>p</p>
  2429. <p>p</p>
  2430. <p>p</p>
  2431. <p>p</p>
  2432. <p>p</p>
  2433. <p>p</p>
  2434. <p>p</p>
  2435. </div>
  2436. );
  2437. };
  2438. export { SelectPosition };
  2439. SelectPosition.story = {
  2440. name: 'Select position problem'
  2441. }
  2442. const RenderOptionDemo = () => {
  2443. const renderOptionItem = renderProps => {
  2444. const {
  2445. disabled,
  2446. selected,
  2447. label,
  2448. value,
  2449. focused,
  2450. className,
  2451. style,
  2452. onMouseEnter,
  2453. onClick,
  2454. empty,
  2455. emptyContent,
  2456. ...rest
  2457. } = renderProps;
  2458. const optionCls = classNames({
  2459. ['custom-option-render']: true,
  2460. ['custom-option-render-focused']: focused,
  2461. ['custom-option-render-disabled']: disabled,
  2462. ['custom-option-render-selected']: selected,
  2463. }); // Notice:
  2464. // 1.props传入的style需在wrapper dom上进行消费,否则在虚拟化场景下会无法正常使用
  2465. // 2.选中(selected)、聚焦(focused)、禁用(disabled)等状态的样式需自行加上,你可以从props中获取到相对的boolean值
  2466. // 3.onMouseEnter需在wrapper dom上绑定,否则上下键盘操作时显示会有问题
  2467. return (
  2468. <div
  2469. style={style}
  2470. className={optionCls}
  2471. onClick={() => onClick()}
  2472. onMouseEnter={e => onMouseEnter()}
  2473. >
  2474. <Checkbox checked={selected} />
  2475. <div className="option-right">{label}</div>
  2476. </div>
  2477. );
  2478. };
  2479. return (
  2480. <>
  2481. <Select
  2482. filter
  2483. dropdownClassName="components-select-demo-renderOptionItem"
  2484. optionList={optionList}
  2485. style={{
  2486. width: 300,
  2487. }}
  2488. renderOptionItem={renderOptionItem}
  2489. />
  2490. <br />
  2491. <br />
  2492. <Select
  2493. filter
  2494. multiple
  2495. dropdownClassName="components-select-demo-renderOptionItem"
  2496. optionList={optionList}
  2497. style={{
  2498. width: 450,
  2499. }}
  2500. renderOptionItem={renderOptionItem}
  2501. />
  2502. </>
  2503. );
  2504. };
  2505. export const RenderOptionItem = () => <RenderOptionDemo />;
  2506. RenderOptionItem.story = {
  2507. name: 'renderOptionItem',
  2508. };
  2509. const FilterDefaultOpen = () => {
  2510. const [value1, setValue1] = useState('a-1');
  2511. return (
  2512. <>
  2513. <Select
  2514. placeholder=""
  2515. style={{
  2516. width: 180,
  2517. }}
  2518. filter
  2519. defaultOpen
  2520. >
  2521. <Select.OptGroup label="Asia">
  2522. <Select.Option value="a-1">China</Select.Option>
  2523. <Select.Option value="a-2">Koera</Select.Option>
  2524. </Select.OptGroup>
  2525. <Select.OptGroup label="Europe">
  2526. <Select.Option value="b-1">Germany</Select.Option>
  2527. <Select.Option value="b-2">France</Select.Option>
  2528. </Select.OptGroup>
  2529. <Select.OptGroup label="South America">
  2530. <Select.Option value="c-1">Peru</Select.Option>
  2531. </Select.OptGroup>
  2532. </Select>
  2533. <Select
  2534. placeholder=""
  2535. style={{
  2536. width: 180,
  2537. marginLeft: 20,
  2538. }}
  2539. filter
  2540. defaultOpen
  2541. defaultValue="a-2"
  2542. >
  2543. <Select.OptGroup label="Asia">
  2544. <Select.Option value="a-1">China</Select.Option>
  2545. <Select.Option value="a-2">Koera</Select.Option>
  2546. </Select.OptGroup>
  2547. <Select.OptGroup label="Europe">
  2548. <Select.Option value="b-1">Germany</Select.Option>
  2549. <Select.Option value="b-2">France</Select.Option>
  2550. </Select.OptGroup>
  2551. <Select.OptGroup label="South America">
  2552. <Select.Option value="c-1">Peru</Select.Option>
  2553. </Select.OptGroup>
  2554. </Select>
  2555. <Select
  2556. placeholder=""
  2557. style={{
  2558. width: 180,
  2559. marginLeft: 20,
  2560. }}
  2561. filter
  2562. defaultOpen
  2563. value={value1}
  2564. onChange={val => setValue1(val)}
  2565. >
  2566. <Select.Option value="a-1">China</Select.Option>
  2567. <Select.Option value="a-2">Koera</Select.Option>
  2568. <Select.Option value="b-1">Germany</Select.Option>
  2569. <Select.Option value="b-2">France</Select.Option>
  2570. <Select.Option value="c-1">Peru</Select.Option>
  2571. </Select>
  2572. </>
  2573. );
  2574. };
  2575. export { FilterDefaultOpen };
  2576. FilterDefaultOpen.story = {
  2577. name: 'Filter + defaultOpen'
  2578. };
  2579. const CustomSelect = props => {
  2580. const { fieldRef, ...rest } = props;
  2581. return <Select {...rest} ref={fieldRef} />;
  2582. };
  2583. const CustomFieldSelect = withField(CustomSelect);
  2584. const RefDemo = () => {
  2585. const fieldRef = useRef(null);
  2586. const onChange = () => {
  2587. console.log(fieldRef);
  2588. fieldRef.current.open();
  2589. debugger;
  2590. };
  2591. return (
  2592. <Form>
  2593. <CustomFieldSelect field="test" initValue="se" fieldRef={fieldRef}></CustomFieldSelect>
  2594. <Button onClick={onChange}>change</Button>
  2595. </Form>
  2596. );
  2597. };
  2598. export const RefFieldDemo = () => <RefDemo />;
  2599. RefFieldDemo.story = {
  2600. name: 'Ref field demo',
  2601. };
  2602. const ValueZeroDemo = () => {
  2603. const list = [
  2604. {
  2605. value: 6,
  2606. label: '抖音小视频',
  2607. otherKey: 0,
  2608. },
  2609. {
  2610. value: 1,
  2611. label: '火山小视频',
  2612. disabled: true,
  2613. otherKey: 1,
  2614. },
  2615. {
  2616. value: 'pipixia',
  2617. label: '皮皮虾',
  2618. otherKey: 2,
  2619. },
  2620. {
  2621. value: 'toutiao',
  2622. label: '今日头条',
  2623. otherKey: 3,
  2624. },
  2625. ];
  2626. return (
  2627. <Select
  2628. placeholder="请选择业务线"
  2629. style={{
  2630. width: 180,
  2631. }}
  2632. optionList={list}
  2633. value={0}
  2634. renderSelectedItem={option => option.label + 1}
  2635. ></Select>
  2636. );
  2637. };
  2638. export const Value0 = () => <ValueZeroDemo />;
  2639. Value0.story = {
  2640. name: 'value=0',
  2641. };
  2642. const Highlight = () => {
  2643. const searchWords = ['do', 'dollar'];
  2644. const sourceString = 'aaa do dollar aaa';
  2645. const result = getHighLightTextHTML({
  2646. searchWords,
  2647. sourceString,
  2648. });
  2649. const result2 = getHighLightTextHTML({
  2650. searchWords: ['z'],
  2651. sourceString: 'aaazaaazaaa',
  2652. });
  2653. return result2;
  2654. };
  2655. export const _Highlight = () => <Highlight />;
  2656. _Highlight.story = {
  2657. name: 'highlight',
  2658. };
  2659. export const ScrollIntoView = () => (
  2660. <div>
  2661. <p>single selection</p>
  2662. <Select defaultValue='v-11' defaultOpen style={{ width: 120, marginBottom: 300 }}>
  2663. {new Array(50).fill(null).map((item, idx) => (
  2664. <Option value={`v-${idx}`} key={idx}>{`option-${idx}`}</Option>
  2665. ))}
  2666. </Select>
  2667. <p>single selection with no selected item</p>
  2668. <Select style={{ marginBottom: 300, width: 120 }}>
  2669. {new Array(50).fill(null).map((item, idx) => (
  2670. <Option value={`v-${idx}`} key={idx}>{`option-${idx}`}</Option>
  2671. ))}
  2672. </Select>
  2673. <p>The selected node is the last</p>
  2674. <Select defaultValue='v-49' defaultOpen style={{ marginBottom: 300, width: 120 }}>
  2675. {new Array(50).fill(null).map((item, idx) => (
  2676. <Option value={`v-${idx}`} key={idx}>{`option-${idx}`}</Option>
  2677. ))}
  2678. </Select>
  2679. <p>The selected node is the first</p>
  2680. <Select defaultValue='v-0' style={{ marginBottom: 300, width: 120 }}>
  2681. {new Array(50).fill(null).map((item, idx) => (
  2682. <Option value={`v-${idx}`} key={idx}>{`option-${idx}`}</Option>
  2683. ))}
  2684. </Select>
  2685. <p>multiple selection</p>
  2686. <Select defaultValue={['v-25', 'v-9']} multiple style={{ marginBottom: 300, width: 220 }}>
  2687. {new Array(30).fill(null).map((item, idx) => (
  2688. <Option value={`v-${idx}`} key={idx}>{`option-${idx}`}</Option>
  2689. ))}
  2690. </Select>
  2691. <p>multiple selection with no selected item</p>
  2692. <Select multiple style={{ marginBottom: 300, width: 220 }}>
  2693. {new Array(30).fill(null).map((item, idx) => (
  2694. <Option value={`v-${idx}`} key={idx}>{`option-${idx}`}</Option>
  2695. ))}
  2696. </Select>
  2697. </div>
  2698. );
  2699. ScrollIntoView.story = {
  2700. name: 'scroll into view',
  2701. };
  2702. export const SelectInputPropsDemo = () => {
  2703. const inputProps = {
  2704. className: 'ttt',
  2705. onCompositionEnd: (v) => console.log(v.target.value)
  2706. };
  2707. return (
  2708. <Select
  2709. // onSearch={(v) => console.log(v)}
  2710. optionList={list}
  2711. inputProps={inputProps}
  2712. multiple
  2713. filter
  2714. style={{ width: 200 }}
  2715. >
  2716. </Select>
  2717. )
  2718. };
  2719. SelectInputPropsDemo.story = {
  2720. name: 'inputProps',
  2721. };
  2722. export const AutoClearSearchValue = () => {
  2723. const [val, setVal] = useState(['semi1']);
  2724. const optionList = [
  2725. { label: 'semi1', value: 'semi1' },
  2726. { label: 'semi2', value: 'semi2' },
  2727. { label: 'semi3', value: 'semi3' },
  2728. { label: 'semi4', value: 'semi4' },
  2729. { label: 'semi5', value: 'semi5' },
  2730. { label: 'semi6', value: 'semi6' },
  2731. ];
  2732. return (
  2733. <>
  2734. <h4>Controlled mode + multiple</h4>
  2735. <Select style={{ width: 400 }} multiple optionList={optionList} filter value={val} onChange={value => setVal(value)} autoClearSearchValue={false}></Select>
  2736. <br />
  2737. <br />
  2738. <h4>Uncontrolled mode + multiple</h4>
  2739. <Select style={{ width: 400 }} multiple optionList={optionList} filter autoClearSearchValue={false}></Select>
  2740. <h4>Uncontrolled mode + multiple + defaultValue</h4>
  2741. <Select style={{ width: 400 }} multiple optionList={optionList} filter defaultValue={['semi2']} autoClearSearchValue={false}></Select>
  2742. </>
  2743. )
  2744. }
  2745. SelectInputPropsDemo.story = {
  2746. name: 'AutoClearSearchValue',
  2747. };
  2748. export const RenderSelectedItemCallCount = () => {
  2749. const list = [
  2750. { "name": "夏可漫", "email": "[email protected]", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/avatarDemo.jpeg" },
  2751. { "name": "申悦", "email": "[email protected]", "avatar": "https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bag.jpeg" },
  2752. { "name": "曲晨一", "email": "[email protected]", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/8bd8224511db085ed74fea37205aede5.jpg" },
  2753. { "name": "文嘉茂", "email": "[email protected]", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/6fbafc2d-e3e6-4cff-a1e2-17709c680624.png" },
  2754. { "name": "文嘉茂2", "email": "[email protected]", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/6fbafc2d-e3e6-4cff-a1e2-17709c680624.png" },
  2755. { "name": "文嘉茂3", "email": "[email protected]", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/6fbafc2d-e3e6-4cff-a1e2-17709c680624.png" },
  2756. ]
  2757. const renderMultipleWithCustomTag = (optionNode, { onClose }) => {
  2758. console.count('rerender')
  2759. const content = (
  2760. <Tag
  2761. avatarSrc={optionNode.avatar}
  2762. avatarShape='circle'
  2763. closable={true}
  2764. onClose={onClose}
  2765. size='large'
  2766. >
  2767. {optionNode.name}
  2768. </Tag>
  2769. );
  2770. return {
  2771. isRenderInTag: false,
  2772. content
  2773. };
  2774. }
  2775. const renderCustomOption = (item, index) => {
  2776. const optionStyle = {
  2777. display: 'flex',
  2778. paddingLeft: 24,
  2779. paddingTop: 10,
  2780. paddingBottom: 10
  2781. }
  2782. return (
  2783. <Select.Option value={item.name} style={optionStyle} showTick={true} {...item} key={item.email}>
  2784. <Avatar size="small" src={item.avatar} />
  2785. <div style={{ marginLeft: 8 }}>
  2786. <div style={{ fontSize: 14 }}>{item.name}</div>
  2787. <div style={{ color: 'var(--color-text-2)', fontSize: 12, lineHeight: '16px', fontWeight: 'normal' }}>{item.email}</div>
  2788. </div>
  2789. </Select.Option>
  2790. )
  2791. }
  2792. return (
  2793. <>
  2794. <Select
  2795. placeholder='请选择'
  2796. showClear
  2797. multiple
  2798. maxTagCount={2}
  2799. style={{ width: 280, height: 40 }}
  2800. onChange={v => console.log(v)}
  2801. defaultValue={'夏可漫'}
  2802. renderSelectedItem={renderMultipleWithCustomTag}
  2803. >
  2804. {list.map((item, index) => renderCustomOption(item, index))}
  2805. </Select>
  2806. </>
  2807. );
  2808. }
  2809. RenderSelectedItemCallCount.story = {
  2810. name: 'RenderSelectedItemCallCount',
  2811. };