select.stories.js 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988
  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. <Select
  601. multiple={true}
  602. maxTagCount={3}
  603. style={{
  604. width: '350px',
  605. }}
  606. defaultValue={[1, 2, 3]}
  607. placeholder="fefe"
  608. insetLabel="标签"
  609. onSelect={(...res) => console.log(res)}
  610. onDeselect={(...res) => console.log(res)}
  611. >
  612. <Option value={1}>opt1</Option>
  613. <Option value={2}>opt2</Option>
  614. <Option value={3}>opt3</Option>
  615. <Option value="4">opt4</Option>
  616. <Option value={5}>opt5</Option>
  617. <Option value={6}>opt6</Option>
  618. <Option value={7}>opt7</Option>
  619. <Option value={8}>opt8</Option>
  620. </Select>
  621. <br />
  622. <br />
  623. maxTagCount = 3, max=5
  624. <Select
  625. multiple={true}
  626. maxTagCount={3}
  627. max={5}
  628. style={{
  629. width: '350px',
  630. }}
  631. defaultValue={[1, 2, 3]}
  632. placeholder="fefe"
  633. insetLabel="标签"
  634. onSelect={(...res) => console.log(res)}
  635. onDeselect={(...res) => console.log(res)}
  636. >
  637. <Option value={1}>opt1</Option>
  638. <Option value={2}>opt2</Option>
  639. <Option value={3}>opt3</Option>
  640. <Option value="4">opt4</Option>
  641. <Option value={5}>opt5</Option>
  642. <Option value={6}>opt6</Option>
  643. <Option value={7}>opt7</Option>
  644. <Option value={8}>opt8</Option>
  645. </Select>
  646. </>
  647. );
  648. SelectMultiple.story = {
  649. name: 'select multiple',
  650. };
  651. SelectMultiple.parameters = {
  652. chromatic: { disableSnapshot: false },
  653. };
  654. export const SelectDisabled = () => (
  655. <Select
  656. disabled
  657. multiple={true}
  658. max={10}
  659. style={{
  660. width: '250px',
  661. }}
  662. >
  663. <Option value={1}>opt1</Option>
  664. <Option value={2} disabled>
  665. opt2
  666. </Option>
  667. <Option value={3}>opt3</Option>
  668. <Option value="4">opt4</Option>
  669. </Select>
  670. );
  671. SelectDisabled.story = {
  672. name: 'select disabled',
  673. };
  674. function filter(input, option) {
  675. console.log(option);
  676. return option.label.includes(input);
  677. }
  678. const spanStyle = {
  679. display: 'inline-block',
  680. marginRight: '8px',
  681. width: '16px',
  682. height: '16px',
  683. borderRadius: '50%',
  684. border: '1px solid var(--semi-color-bg-1)',
  685. };
  686. const colorOptions = [
  687. {
  688. value: 'grey-1',
  689. spanStyle: { ...spanStyle, backgroundColor: 'rgb(107, 116, 117)' },
  690. },
  691. {
  692. value: 'purple-5',
  693. spanStyle: { ...spanStyle, backgroundColor: 'rgb(158, 40, 179)' },
  694. },
  695. {
  696. value: 'pink-2',
  697. spanStyle: { ...spanStyle, backgroundColor: 'rgb(233, 30, 99)' },
  698. },
  699. {
  700. value: 'blue-3',
  701. spanStyle: { ...spanStyle, backgroundColor: 'rgb(0, 119, 250)' },
  702. },
  703. ];
  704. const alignStyle = {
  705. display: 'flex',
  706. alignItems: 'center',
  707. };
  708. const customFilter = (input, option) => {
  709. return option.value.includes(input);
  710. };
  711. export const SelectFilterSingle = () => (
  712. <div>
  713. <h5>默认筛选</h5>
  714. <Select
  715. filter
  716. style={{
  717. width: '250px',
  718. margin: 10,
  719. }}
  720. showClear
  721. autoFocus
  722. onSearch={(val) => console.log(`onSearch:${val}`)}
  723. onFocus={() => console.log('onFocus')}
  724. onBlur={() => console.log('onBlur')}
  725. >
  726. <Option value={1}>opt1</Option>
  727. <Option value={2} disabled>
  728. disabled
  729. </Option>
  730. <Option value={3}>Lucy</Option>
  731. <Option value="4">bay</Option>
  732. <Option value="5">sert</Option>
  733. <Option value="6">wym</Option>
  734. <Option value="7" disabled>
  735. meno
  736. </Option>
  737. <Option value="8">opts</Option>
  738. </Select>
  739. <h5>自定义筛选函数</h5>
  740. <Select
  741. style={{
  742. width: '250px',
  743. margin: 10,
  744. }}
  745. filter={filter}
  746. showClear
  747. onBlur={() => console.log('onBlur')}
  748. onSearch={val => console.log(val)}
  749. onFocus={() => console.log('onFocus')}
  750. >
  751. <Option value={1}>opt1(value:1)</Option>
  752. <Option value={2}>mike(value:2)</Option>
  753. <Option value={3}>Lucy(value:3)</Option>
  754. <Option value={4}>bay(value:4)</Option>
  755. </Select>
  756. <h5>filter为true,但option label为node时</h5>
  757. <Select
  758. style={{
  759. width: '250px',
  760. margin: 10,
  761. }}
  762. showClear
  763. filter={customFilter}
  764. onChange={v => console.log(v)}
  765. insetLabel="insetLabel"
  766. onFocus={() => console.log('onFocus')}
  767. onBlur={() => console.log('onBlur')}
  768. onSearch={(val) => console.log(val)}
  769. >
  770. {colorOptions.map(option => (
  771. <Option value={option.value} key={option.value}>
  772. <div style={alignStyle}>
  773. <span style={option.spanStyle}></span>
  774. {option.value}
  775. </div>
  776. </Option>
  777. ))}
  778. </Select>
  779. </div>
  780. );
  781. SelectFilterSingle.story = {
  782. name: 'select filter single',
  783. };
  784. export const SelectFilterMultiple = () => (
  785. <>
  786. <Select
  787. filter
  788. multiple={true}
  789. style={{
  790. width: '250px',
  791. }}
  792. placeholder="fefe"
  793. >
  794. <Option value={1}>opt1</Option>
  795. <Option value={2}>opt2</Option>
  796. <Option value={3}>opt22</Option>
  797. <Option value={3}>opt3</Option>
  798. <Option value={4}>opt4</Option>
  799. <Option value={5}>opt5</Option>
  800. <Option value={6}>opt6</Option>
  801. <Option value={7}>opt7</Option>
  802. <Option value={8}>opt8</Option>
  803. </Select>
  804. <Select
  805. filter
  806. multiple={true}
  807. maxTagCount={3}
  808. style={{
  809. width: '270px',
  810. }}
  811. placeholder="fefe"
  812. >
  813. <Option value={1}>opt1</Option>
  814. <Option value={2}>opt2</Option>
  815. <Option value={3}>opt22</Option>
  816. <Option value={3}>opt3</Option>
  817. <Option value={4}>opt4</Option>
  818. <Option value={5}>opt5</Option>
  819. <Option value={6}>opt6</Option>
  820. <Option value={7}>opt7</Option>
  821. <Option value={8}>opt8</Option>
  822. </Select>
  823. </>
  824. );
  825. SelectFilterMultiple.story = {
  826. name: 'select filter multiple',
  827. };
  828. const OptionLabelProp = () => {
  829. const [value, setValue] = useState(1);
  830. return (
  831. <>
  832. 设置optionLabelProp属性(默认为'children')为'value'时,回填到选择框中的文本会是Option.value
  833. <br></br>
  834. <Select
  835. style={{
  836. width: '250px',
  837. }}
  838. defaultValue={1}
  839. optionLabelProp="value"
  840. >
  841. <Option value={1}>opt1</Option>
  842. <Option value={2}>opt2</Option>
  843. <Option value={3}>
  844. <span
  845. style={{
  846. color: 'pink',
  847. }}
  848. >
  849. opt3 Node
  850. </span>
  851. </Option>
  852. <Option value="4">
  853. <span
  854. style={{
  855. color: 'red',
  856. }}
  857. >
  858. testNode
  859. </span>
  860. </Option>
  861. </Select>
  862. <br />
  863. <br />
  864. <Select
  865. style={{
  866. width: '250px',
  867. }}
  868. value={value}
  869. optionLabelProp="value"
  870. onChange={setValue}
  871. >
  872. <Option value={1}>opt1</Option>
  873. <Option value={2}>opt2</Option>
  874. <Option value={3}>
  875. <span
  876. style={{
  877. color: 'pink',
  878. }}
  879. >
  880. opt3 Node
  881. </span>
  882. </Option>
  883. <Option value="4">
  884. <span
  885. style={{
  886. color: 'red',
  887. }}
  888. >
  889. testNode
  890. </span>
  891. </Option>
  892. </Select>
  893. <br />
  894. <br />
  895. <Select
  896. style={{
  897. width: '250px',
  898. }}
  899. defaultValue={1}
  900. >
  901. <Option value={1}>children Label Text 1</Option>
  902. <Option value={2}>opt2</Option>
  903. <Option value={3}>opt3</Option>
  904. <Option value="4">
  905. <span
  906. style={{
  907. color: 'red',
  908. }}
  909. >
  910. testNode
  911. </span>
  912. </Option>
  913. </Select>
  914. <Select
  915. style={{
  916. width: '250px',
  917. }}
  918. defaultValue={1}
  919. filter
  920. optionLabelProp="value"
  921. >
  922. <Option value={1}>children Label Text 1</Option>
  923. <Option value={2}>opt2</Option>
  924. <Option value={3}>opt3</Option>
  925. <Option value="4">
  926. <span
  927. style={{
  928. color: 'red',
  929. }}
  930. >
  931. testNode
  932. </span>
  933. </Option>
  934. </Select>
  935. <br />
  936. <br />
  937. 多选
  938. <Select
  939. style={{
  940. width: '250px',
  941. }}
  942. multiple
  943. filter
  944. optionLabelProp="value"
  945. >
  946. <Option value={1}>children Label Text 1</Option>
  947. <Option value={2}>opt2</Option>
  948. <Option value={3}>opt3</Option>
  949. <Option value="4">
  950. <span
  951. style={{
  952. color: 'red',
  953. }}
  954. >
  955. testNode
  956. </span>
  957. </Option>
  958. </Select>
  959. </>
  960. );
  961. };
  962. class CustomRender extends React.Component {
  963. constructor() {
  964. super();
  965. this.state = {
  966. list: [
  967. {
  968. name: '夏可漫',
  969. email: '[email protected]',
  970. abbr: 'XK',
  971. color: 'amber',
  972. },
  973. {
  974. name: '申悦',
  975. email: '[email protected]',
  976. abbr: 'SY',
  977. color: 'indigo',
  978. },
  979. {
  980. name: '曲晨一',
  981. email: '[email protected]',
  982. abbr: 'CY',
  983. color: 'blue',
  984. },
  985. {
  986. name: '文嘉茂',
  987. email: '[email protected]',
  988. abbr: 'JM',
  989. color: 'cyan',
  990. },
  991. ],
  992. };
  993. }
  994. renderCustomOption(item, index) {
  995. const optionStyle = {
  996. display: 'flex',
  997. };
  998. return (
  999. <Option key={index} value={item.name} style={optionStyle} showTick={false} {...item}>
  1000. <Avatar color={item.color} size="small">
  1001. {item.abbr}
  1002. </Avatar>
  1003. <div
  1004. style={{
  1005. marginLeft: 4,
  1006. }}
  1007. >
  1008. <p
  1009. style={{
  1010. fontSize: 14,
  1011. margin: 4,
  1012. }}
  1013. >
  1014. {item.name}
  1015. </p>
  1016. <p
  1017. style={{
  1018. margin: 4,
  1019. }}
  1020. >
  1021. {item.email}
  1022. </p>
  1023. </div>
  1024. </Option>
  1025. );
  1026. }
  1027. renderSelectedItem(optionNode) {
  1028. return (
  1029. <div>
  1030. <Avatar color={optionNode.color} size="small">
  1031. {optionNode.abbr}
  1032. </Avatar>
  1033. <span
  1034. style={{
  1035. margin: 8,
  1036. }}
  1037. >
  1038. {optionNode.email}
  1039. </span>
  1040. </div>
  1041. );
  1042. }
  1043. renderMultipleSelectedItem(optionNode) {
  1044. let content = (
  1045. <div>
  1046. <Avatar color={optionNode.color} size="small">
  1047. {optionNode.abbr}
  1048. </Avatar>
  1049. </div>
  1050. );
  1051. return {
  1052. isRenderInTag: true,
  1053. content,
  1054. };
  1055. }
  1056. renderMultipleWithoutTag(optionNode) {
  1057. let content = (
  1058. <div>
  1059. <Avatar color={optionNode.color} size="small">
  1060. {optionNode.abbr}
  1061. </Avatar>
  1062. </div>
  1063. );
  1064. return {
  1065. isRenderInTag: false,
  1066. content,
  1067. };
  1068. }
  1069. render() {
  1070. const { list } = this.state;
  1071. return (
  1072. <React.Fragment>
  1073. <Select
  1074. style={{
  1075. width: 300,
  1076. height: 40,
  1077. }}
  1078. onChange={this.provinceChange}
  1079. defaultValue={'夏可漫'}
  1080. renderSelectedItem={this.renderSelectedItem}
  1081. >
  1082. {list.map((item, index) => this.renderCustomOption(item, index))}
  1083. </Select>
  1084. <Select
  1085. style={{
  1086. width: 360,
  1087. height: 60,
  1088. marginTop: 20,
  1089. }}
  1090. onChange={this.provinceChange}
  1091. defaultValue={['夏可漫', '申悦']}
  1092. multiple
  1093. renderSelectedItem={this.renderMultipleSelectedItem}
  1094. >
  1095. {list.map((item, index) => this.renderCustomOption(item, index))}
  1096. </Select>
  1097. <Select
  1098. style={{
  1099. width: 360,
  1100. height: 60,
  1101. marginTop: 20,
  1102. }}
  1103. onChange={this.provinceChange}
  1104. defaultValue={['夏可漫', '申悦']}
  1105. multiple
  1106. renderSelectedItem={this.renderMultipleWithoutTag}
  1107. >
  1108. {list.map((item, index) => this.renderCustomOption(item, index))}
  1109. </Select>
  1110. </React.Fragment>
  1111. );
  1112. }
  1113. }
  1114. export const RenderSelectedItem = () => (
  1115. <>
  1116. renderSelectedItem
  1117. <CustomRender />
  1118. <br />
  1119. <br />
  1120. OptionLabelProp
  1121. <OptionLabelProp />
  1122. </>
  1123. );
  1124. RenderSelectedItem.story = {
  1125. name: 'renderSelectedItem',
  1126. };
  1127. RenderSelectedItem.parameters = {
  1128. chromatic: { disableSnapshot: false },
  1129. };
  1130. const ControlledSelect = () => {
  1131. const [value, setValue] = useState('nick');
  1132. const [value2, setValue2] = useState('jerry');
  1133. const [value3, setValue3] = useState();
  1134. const [value4, setValue4] = useState(['nick']);
  1135. const [value5, setValue5] = useState();
  1136. return (
  1137. <>
  1138. <span>value + onChange</span>
  1139. <Select
  1140. value={value}
  1141. onChange={setValue}
  1142. style={{
  1143. width: 200,
  1144. }}
  1145. >
  1146. <Option value="nick">nick</Option>
  1147. <Option value="jerry">jerry</Option>
  1148. <Option value="mark">mark</Option>
  1149. </Select>
  1150. <br />
  1151. <br />
  1152. <span>只传value,不传onChange</span>
  1153. <Select
  1154. value={value2}
  1155. style={{
  1156. width: 200,
  1157. }}
  1158. >
  1159. <Option value="nick">nick</Option>
  1160. <Option value="jerry">jerry</Option>
  1161. <Option value="mark">mark</Option>
  1162. </Select>
  1163. <br />
  1164. <br />
  1165. <span>value + onChange , 多选</span>
  1166. <Select
  1167. value={value3}
  1168. onChange={setValue3}
  1169. multiple
  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. <Option value="nick2">nick2</Option>
  1178. <Option value="jerry2">jerry2</Option>
  1179. <Option value="mark2">mark2</Option>
  1180. </Select>
  1181. <br />
  1182. <br />
  1183. <span>value, 多选</span>
  1184. <Select
  1185. value={value4}
  1186. multiple
  1187. style={{
  1188. width: 200,
  1189. }}
  1190. >
  1191. <Option value="nick">nick</Option>
  1192. <Option value="jerry">jerry</Option>
  1193. <Option value="mark">mark</Option>
  1194. </Select>
  1195. <br />
  1196. <h5>filter为true,但option label为node时</h5>
  1197. <Select
  1198. style={{
  1199. width: '250px',
  1200. }}
  1201. filter={customFilter}
  1202. onChange={v => console.log(v)}
  1203. insetLabel="insetLabel"
  1204. value={value5}
  1205. onChange={setValue5}
  1206. >
  1207. {colorOptions.map(option => (
  1208. <Option value={option.value} key={option.value}>
  1209. <div style={alignStyle}>
  1210. <span style={option.spanStyle}></span>
  1211. {option.value}
  1212. </div>
  1213. </Option>
  1214. ))}
  1215. </Select>
  1216. </>
  1217. );
  1218. };
  1219. export const Controlled = () => <ControlledSelect></ControlledSelect>;
  1220. Controlled.story = {
  1221. name: 'controlled',
  1222. };
  1223. const UnControlledSelect = () => {
  1224. const onChange = value => {
  1225. console.log(value);
  1226. };
  1227. return (
  1228. <>
  1229. <h5>defaultValue在list中不存在</h5>
  1230. <Select
  1231. defaultValue={90}
  1232. onChange={onChange}
  1233. style={{
  1234. width: 200,
  1235. }}
  1236. >
  1237. <Option value={20}>nick</Option>
  1238. <Option value={10}>jerry</Option>
  1239. <Option value={5}>mark</Option>
  1240. </Select>
  1241. <h5>defaultValue在list中存在</h5>
  1242. <Select
  1243. defaultValue={10}
  1244. onChange={onChange}
  1245. style={{
  1246. width: 200,
  1247. }}
  1248. >
  1249. <Option value={20}>nick</Option>
  1250. <Option value={10}>jerry</Option>
  1251. <Option value={5}>mark</Option>
  1252. </Select>
  1253. </>
  1254. );
  1255. };
  1256. export { UnControlledSelect };
  1257. UnControlledSelect.story = {
  1258. name: '非受控组件'
  1259. };
  1260. export const TestScroll = () => (
  1261. <div
  1262. style={{
  1263. marginTop: '600px',
  1264. marginBottom: '50px',
  1265. }}
  1266. >
  1267. <Select
  1268. style={{
  1269. width: '150px',
  1270. }}
  1271. >
  1272. <Option value="tony">IronMan</Option>
  1273. <Option value="Thor" disabled>
  1274. Thor
  1275. </Option>
  1276. <Option value="steve">Caption</Option>
  1277. <Option value="peter">SpiderBoy</Option>
  1278. </Select>
  1279. </div>
  1280. );
  1281. TestScroll.story = {
  1282. name: 'test scroll',
  1283. };
  1284. let optionList = [
  1285. {
  1286. value: 'tony',
  1287. label: 'Ironman',
  1288. },
  1289. {
  1290. value: 'Thor',
  1291. label: 'Thor',
  1292. },
  1293. {
  1294. value: 'steve',
  1295. label: 'Caption',
  1296. },
  1297. {
  1298. value: 'peter',
  1299. label: 'SpiderBoy',
  1300. },
  1301. ];
  1302. export const OptionList = () => (
  1303. <Select
  1304. style={{
  1305. width: '100px',
  1306. }}
  1307. optionList={optionList}
  1308. ></Select>
  1309. );
  1310. OptionList.story = {
  1311. name: 'optionList',
  1312. };
  1313. export const InsetLabel = () => (
  1314. <>
  1315. <Select
  1316. style={{
  1317. width: 300,
  1318. }}
  1319. insetLabel="主播类型"
  1320. placeholder="请选择"
  1321. optionList={optionList}
  1322. ></Select>
  1323. <Select
  1324. style={{
  1325. width: 300,
  1326. }}
  1327. multiple
  1328. insetLabel="主播类型"
  1329. optionList={optionList}
  1330. ></Select>
  1331. <Select
  1332. style={{
  1333. width: 300,
  1334. }}
  1335. filter
  1336. insetLabel="主播类型"
  1337. optionList={optionList}
  1338. ></Select>
  1339. <Select
  1340. style={{
  1341. width: 300,
  1342. }}
  1343. filter
  1344. multiple
  1345. insetLabel="主播类型"
  1346. optionList={optionList}
  1347. ></Select>
  1348. </>
  1349. );
  1350. InsetLabel.story = {
  1351. name: 'insetLabel',
  1352. };
  1353. export const ChangeOptionDynamic = () => {
  1354. function App() {
  1355. let [options, setOptions] = useState([]);
  1356. let [index, setIndex] = useState(0);
  1357. const addOption = () => {
  1358. const randomItem = optionList[index];
  1359. index = index + 1;
  1360. setIndex(index);
  1361. options = [...options, { ...randomItem }];
  1362. setOptions(options);
  1363. };
  1364. const reset = () => {
  1365. setOptions([]);
  1366. setIndex(0);
  1367. };
  1368. return (
  1369. <div>
  1370. <Select
  1371. style={{
  1372. width: '150px',
  1373. }}
  1374. defaultValue="tony"
  1375. >
  1376. {options.map((option, idx) => (
  1377. <Select.Option key={option.key || idx} value={option.value}>
  1378. {option.label}
  1379. </Select.Option>
  1380. ))}
  1381. </Select>
  1382. <h4>多选</h4>
  1383. <Select
  1384. style={{
  1385. width: '150px',
  1386. }}
  1387. multiple
  1388. defaultValue={['tony']}
  1389. >
  1390. {options.map((option, idx) => (
  1391. <Select.Option key={option.key || idx} value={option.value}>
  1392. {option.label}
  1393. </Select.Option>
  1394. ))}
  1395. </Select>
  1396. <button onClick={addOption}>add option</button>
  1397. <button onClick={reset}>reset</button>
  1398. </div>
  1399. );
  1400. }
  1401. return <App />;
  1402. };
  1403. ChangeOptionDynamic.story = {
  1404. name: 'change option dynamic',
  1405. };
  1406. let list = [
  1407. {
  1408. value: 'tony',
  1409. label: 'Ironman',
  1410. otherKey: {
  1411. role: 1,
  1412. },
  1413. },
  1414. {
  1415. value: 'Thor',
  1416. label: 'Thor',
  1417. otherKey: {
  1418. role: 2,
  1419. },
  1420. },
  1421. {
  1422. value: 'steve',
  1423. label: 'Caption',
  1424. otherKey: {
  1425. role: 3,
  1426. },
  1427. },
  1428. {
  1429. value: 'peter',
  1430. label: 'SpiderBoy',
  1431. otherKey: {
  1432. role: 4,
  1433. },
  1434. },
  1435. ];
  1436. const SearchDemo1 = () => {
  1437. const [optionList, setOptionList] = useState(list);
  1438. const [loading, setLoading] = useState(false);
  1439. const handleSearch = value => {
  1440. setLoading(true);
  1441. let length = Math.ceil(Math.random() * 10);
  1442. let result = Array.from(
  1443. {
  1444. length,
  1445. },
  1446. (v, i) => {
  1447. return {
  1448. value: value + i,
  1449. label: value + i,
  1450. otherKey: {
  1451. role: i,
  1452. },
  1453. };
  1454. }
  1455. );
  1456. setTimeout(() => {
  1457. setOptionList(result);
  1458. setLoading(false);
  1459. }, 1000);
  1460. };
  1461. const [value, setValue] = useState(optionList[0].value);
  1462. const onChange = value => {
  1463. console.log(value);
  1464. setValue(value);
  1465. };
  1466. return (
  1467. <div>
  1468. 受控:
  1469. <Select
  1470. filter
  1471. style={{
  1472. width: '150px',
  1473. }}
  1474. onSearch={v => handleSearch(v)}
  1475. optionList={optionList}
  1476. value={value}
  1477. loading={loading}
  1478. showClear
  1479. onChange={onChange}
  1480. ></Select>
  1481. 非受控:
  1482. <Select
  1483. style={{
  1484. width: '150px',
  1485. }}
  1486. filter
  1487. showClear
  1488. onSearch={v => handleSearch(v)}
  1489. optionList={optionList}
  1490. loading={loading}
  1491. onChange={onChange}
  1492. ></Select>
  1493. 多选非受控
  1494. <Select
  1495. style={{
  1496. width: '150px',
  1497. }}
  1498. showClear
  1499. filter
  1500. multiple
  1501. onSearch={v => handleSearch(v)}
  1502. optionList={optionList}
  1503. loading={loading}
  1504. onChange={onChange}
  1505. ></Select>
  1506. </div>
  1507. );
  1508. };
  1509. import debounce from 'lodash/debounce';
  1510. class SearchDemo2 extends React.Component {
  1511. constructor() {
  1512. super();
  1513. this.state = {
  1514. loading: false,
  1515. optionList: [
  1516. {
  1517. value: 'abc',
  1518. label: '抖音',
  1519. type: 1,
  1520. },
  1521. {
  1522. value: 'hotsoon',
  1523. label: '火山小视频',
  1524. type: 2,
  1525. },
  1526. {
  1527. value: 'pipixia',
  1528. label: '皮皮虾',
  1529. type: 3,
  1530. },
  1531. {
  1532. value: 'toutiao',
  1533. label: '今日头条',
  1534. type: 4,
  1535. },
  1536. ],
  1537. value: [],
  1538. };
  1539. this.handleSearch = debounce(this.handleSearch, 800).bind(this);
  1540. this.onChange = this.onChange.bind(this);
  1541. this.customRender = this.customRender.bind(this);
  1542. }
  1543. handleSearch(inputValue) {
  1544. this.setState({
  1545. loading: true,
  1546. });
  1547. let length = Math.ceil(Math.random() * 100);
  1548. let result = Array.from(
  1549. {
  1550. length,
  1551. },
  1552. (v, i) => {
  1553. return {
  1554. value: inputValue + i,
  1555. label: 'label' + i,
  1556. type: i + 1,
  1557. };
  1558. }
  1559. );
  1560. setTimeout(() => {
  1561. this.setState({
  1562. optionList: result,
  1563. loading: false,
  1564. });
  1565. }, 2000);
  1566. }
  1567. onChange(value) {
  1568. this.setState({
  1569. value,
  1570. });
  1571. console.log(value);
  1572. }
  1573. customRender(optionNode) {
  1574. return optionNode.value + optionNode.label;
  1575. }
  1576. render() {
  1577. const { loading, optionList, value } = this.state;
  1578. return (
  1579. <div>
  1580. <Select
  1581. style={{
  1582. width: 150,
  1583. }}
  1584. showClear
  1585. filter
  1586. labelInValue
  1587. onSearch={this.handleSearch}
  1588. optionList={optionList}
  1589. loading={loading}
  1590. onChange={this.onChange}
  1591. placeholder="请选择"
  1592. ></Select>
  1593. <br />
  1594. <br />
  1595. <Select
  1596. style={{
  1597. width: 180,
  1598. }}
  1599. filter // labelInValue
  1600. showClear
  1601. multiple
  1602. value={value}
  1603. renderSelectedItem={this.customRender}
  1604. onSearch={this.handleSearch}
  1605. optionList={optionList}
  1606. loading={loading}
  1607. onChange={this.onChange}
  1608. placeholder="请选择"
  1609. ></Select>
  1610. </div>
  1611. );
  1612. }
  1613. }
  1614. export const Search = () => (
  1615. <>
  1616. <SearchDemo1 />
  1617. <SearchDemo2 />
  1618. </>
  1619. );
  1620. Search.story = {
  1621. name: 'search',
  1622. };
  1623. export const IncomeDetail = ({ config = {}, params = {} }) => {
  1624. const [detailList, setDetailList] = useState([]);
  1625. const [hasMore, setHasMore] = useState(true);
  1626. const [loading, setLoading] = useState();
  1627. let lock;
  1628. const fetchData = (outParams = {}) => {
  1629. if (lock) {
  1630. return;
  1631. }
  1632. setLoading(true); // 参数
  1633. // 请求
  1634. fetch({
  1635. url: URL.user_profit,
  1636. method: 'get',
  1637. baseURL: config.webcast_host,
  1638. params,
  1639. })
  1640. .then(res => {
  1641. lock = false;
  1642. setLoading(false);
  1643. console.log('++++', data);
  1644. })
  1645. .catch(() => {
  1646. setLoading(false);
  1647. Toast.show('网络异常,请稍后重试');
  1648. });
  1649. };
  1650. useEffect(fetchData, []); // 监听滚动设置吸顶 以及加载更多
  1651. useEffect(() => {
  1652. window.addEventListener('scroll', function() {
  1653. // 加载更多
  1654. const scrollY = window.scrollY;
  1655. const scrollHeight = document.documentElement.scrollHeight;
  1656. const screenHeight = screen.height;
  1657. if (!loading && hasMore && scrollY + screenHeight + 300 > scrollHeight) {
  1658. fetchData();
  1659. }
  1660. });
  1661. }, [detailList.length]);
  1662. return (
  1663. <div>
  1664. <Select></Select>
  1665. </div>
  1666. );
  1667. };
  1668. export const AllowCreate = () => (
  1669. <Select
  1670. style={{
  1671. width: 500,
  1672. }}
  1673. optionList={optionList}
  1674. allowCreate={true}
  1675. multiple={true}
  1676. filter={true}
  1677. onChange={v => console.log(v)}
  1678. ></Select>
  1679. );
  1680. AllowCreate.story = {
  1681. name: 'allowCreate',
  1682. };
  1683. export const AllowCreateCustomRender = () => (
  1684. <Select
  1685. style={{
  1686. width: 500,
  1687. }}
  1688. optionList={optionList}
  1689. allowCreate={true}
  1690. multiple={true}
  1691. filter={true}
  1692. onChange={v => console.log(v)}
  1693. renderCreateItem={v => `semi: ${v}`}
  1694. ></Select>
  1695. );
  1696. AllowCreateCustomRender.story = {
  1697. name: 'allowCreate custom render',
  1698. };
  1699. let AllowCreateControlledDemo = () => {
  1700. let [value, setValue] = useState();
  1701. const optionList = [
  1702. {
  1703. value: 'abc',
  1704. label: '抖音',
  1705. },
  1706. {
  1707. value: 'hotsoon',
  1708. label: '火山小视频',
  1709. },
  1710. {
  1711. value: 'pipixia',
  1712. label: '皮皮虾',
  1713. },
  1714. {
  1715. value: 'toutiao',
  1716. label: '今日头条',
  1717. },
  1718. ];
  1719. const [list, setList] = useState(optionList);
  1720. const handleSelect = v => {
  1721. var lastOne = v[v.length - 1];
  1722. if (lastOne && list.findIndex(item => item.value === lastOne) == -1) {
  1723. list.push({
  1724. value: lastOne,
  1725. label: lastOne,
  1726. });
  1727. }
  1728. setList(list);
  1729. setValue(v);
  1730. };
  1731. return (
  1732. <Select
  1733. style={{
  1734. width: 400,
  1735. }}
  1736. optionList={list}
  1737. allowCreate={true}
  1738. multiple={true}
  1739. filter={true}
  1740. value={value}
  1741. onChange={handleSelect}
  1742. ></Select>
  1743. );
  1744. };
  1745. const AllowCreateDemo = () => {
  1746. let [value, setValue] = useState();
  1747. const optionList = [
  1748. {
  1749. value: 'abc',
  1750. label: '抖音',
  1751. },
  1752. {
  1753. value: 'hotsoon',
  1754. label: '火山小视频',
  1755. },
  1756. {
  1757. value: 'pipixia',
  1758. label: '皮皮虾',
  1759. },
  1760. {
  1761. value: 'toutiao',
  1762. label: '今日头条',
  1763. },
  1764. ];
  1765. const [list, setList] = useState(optionList);
  1766. const handleSelect = v => {
  1767. var lastOne = v[v.length - 1];
  1768. if (lastOne && list.findIndex(item => item.value === lastOne) == -1) {
  1769. list.push({
  1770. value: lastOne,
  1771. label: lastOne,
  1772. });
  1773. }
  1774. setList(list); // setValue(v)
  1775. };
  1776. return (
  1777. <Select
  1778. style={{
  1779. width: 400,
  1780. }}
  1781. optionList={list}
  1782. defaultValue={['abc', 'hotsoon']}
  1783. allowCreate={true}
  1784. multiple={true}
  1785. filter={true}
  1786. onChange={handleSelect}
  1787. ></Select>
  1788. );
  1789. };
  1790. export const AllowCreateWithDefaultValue = () => <AllowCreateDemo />;
  1791. AllowCreateWithDefaultValue.story = {
  1792. name: 'allowCreate with defaultValue',
  1793. };
  1794. class HideDemo extends React.Component {
  1795. constructor(props) {
  1796. super(props);
  1797. this.state = {
  1798. optionList: [
  1799. {
  1800. value: 'abc',
  1801. label: '抖音',
  1802. },
  1803. {
  1804. value: 'hotsoon',
  1805. label: '火山小视频',
  1806. },
  1807. {
  1808. value: 'pipixia',
  1809. label: '皮皮虾',
  1810. },
  1811. {
  1812. value: 'toutiao',
  1813. label: '今日头条',
  1814. },
  1815. ],
  1816. selectedItems: [],
  1817. };
  1818. this.onChange = this.onChange.bind(this);
  1819. }
  1820. onChange(selectedItems) {
  1821. this.setState({
  1822. selectedItems,
  1823. });
  1824. }
  1825. render() {
  1826. let { optionList, selectedItems } = this.state;
  1827. let filterOptions = optionList.filter(option => !selectedItems.includes(option.value));
  1828. return (
  1829. <Select
  1830. value={selectedItems}
  1831. multiple
  1832. style={{
  1833. width: 300,
  1834. }}
  1835. onChange={this.onChange}
  1836. optionList={filterOptions}
  1837. ></Select>
  1838. );
  1839. }
  1840. }
  1841. export const AutoHiddenSelectedItem = () => <HideDemo></HideDemo>;
  1842. AutoHiddenSelectedItem.story = {
  1843. name: 'auto hidden selected item',
  1844. };
  1845. class CustomCreate extends React.Component {
  1846. constructor(props) {
  1847. super(props);
  1848. this.state = {
  1849. optionList: [
  1850. {
  1851. value: 'abc',
  1852. label: '抖音',
  1853. },
  1854. {
  1855. value: 'hotsoon',
  1856. label: '火山小视频',
  1857. },
  1858. {
  1859. value: 'pipixia',
  1860. label: '皮皮虾',
  1861. },
  1862. {
  1863. value: 'toutiao',
  1864. label: '今日头条',
  1865. },
  1866. {
  1867. value: 0,
  1868. label: 0,
  1869. },
  1870. ],
  1871. selectedItems: ['fefe'],
  1872. };
  1873. this.onChange = this.onChange.bind(this);
  1874. this.customRender = this.customRender.bind(this);
  1875. this.search = this.search.bind(this);
  1876. }
  1877. onChange(selectedItems) {
  1878. console.log(selectedItems); // this.setState({ selectedItems, optionList: [] });
  1879. this.setState({
  1880. selectedItems,
  1881. }); // this.setState({ optionList: [] });
  1882. }
  1883. customRender(v) {
  1884. return (
  1885. <>
  1886. <span>label:{v.label}</span>
  1887. <span>value:{v.value}</span>
  1888. </>
  1889. );
  1890. }
  1891. customCreate(inputValue, isFocus) {
  1892. let style = {
  1893. padding: 12,
  1894. cursor: 'pointer',
  1895. backgroundColor: isFocus ? 'var(--semi-color-fill-0)' : '#FFF',
  1896. };
  1897. return <div style={style}>{'create' + inputValue}</div>;
  1898. }
  1899. search(inputValue) {
  1900. let length = Math.ceil(Math.random() * 10);
  1901. let result = Array.from(
  1902. {
  1903. length,
  1904. },
  1905. (v, i) => {
  1906. return {
  1907. value: inputValue + i,
  1908. label: inputValue + i,
  1909. type: i + 1,
  1910. };
  1911. }
  1912. );
  1913. console.log(result); // result = result.concat(selectedOption);
  1914. this.setState({
  1915. optionList: result,
  1916. });
  1917. }
  1918. render() {
  1919. let { optionList, selectedItems } = this.state;
  1920. return (
  1921. <>
  1922. <Select
  1923. defaultValue={['abc']}
  1924. filter
  1925. style={{
  1926. width: 300,
  1927. }}
  1928. multiple
  1929. optionList={optionList}
  1930. onSearch={this.search}
  1931. onChange={this.onChange}
  1932. emptyContent={null} // onChangeWithObject
  1933. ></Select>
  1934. </>
  1935. );
  1936. }
  1937. }
  1938. export const _CustomCreate = () => <CustomCreate></CustomCreate>;
  1939. _CustomCreate.story = {
  1940. name: 'CustomCreate',
  1941. };
  1942. class OptionGroupDemo extends React.Component {
  1943. constructor(props) {
  1944. super(props);
  1945. this.handleSearch = this.handleSearch.bind(this);
  1946. this.state = {
  1947. groups: [
  1948. {
  1949. label: 'Asia',
  1950. children: [
  1951. {
  1952. label: 'China',
  1953. value: 'zhongguo',
  1954. },
  1955. {
  1956. label: 'Koera',
  1957. value: 'hanguo',
  1958. },
  1959. ],
  1960. },
  1961. {
  1962. label: 'Europe',
  1963. children: [
  1964. {
  1965. label: 'Germany',
  1966. value: 'deguo',
  1967. },
  1968. {
  1969. label: 'France',
  1970. value: 'faguo',
  1971. },
  1972. ],
  1973. },
  1974. {
  1975. label: 'Other',
  1976. children: [
  1977. {
  1978. label: 'vf',
  1979. value: 'Sourth',
  1980. },
  1981. ],
  1982. },
  1983. ],
  1984. };
  1985. }
  1986. handleSearch(input) {
  1987. let groups = [1, 2, 3].map(i => {
  1988. return {
  1989. label: i,
  1990. // label: Math.random(),
  1991. children: [10, 20].map(j => {
  1992. return {
  1993. label: Math.random(),
  1994. value: Math.random(),
  1995. };
  1996. }),
  1997. };
  1998. });
  1999. this.setState({
  2000. groups,
  2001. });
  2002. }
  2003. renderGroup(group, index) {
  2004. const options = group.children.map(option => (
  2005. <Select.Option value={option.value} label={option.label} key={option.label} />
  2006. ));
  2007. return <Select.OptGroup key={`${index}-${group.label}`} label={group.label}>{options}</Select.OptGroup>;
  2008. }
  2009. render() {
  2010. const { groups } = this.state;
  2011. return (
  2012. <>
  2013. <Select
  2014. placeholder=""
  2015. style={{
  2016. width: 180,
  2017. }}
  2018. filter
  2019. onSearch={this.handleSearch}
  2020. remote
  2021. >
  2022. {groups.map((group, index) => this.renderGroup(group, index))}
  2023. </Select>
  2024. </>
  2025. );
  2026. }
  2027. }
  2028. export const SelectOptionGroup = () => <OptionGroupDemo />;
  2029. SelectOptionGroup.story = {
  2030. name: 'Select OptionGroup',
  2031. };
  2032. const BlurDemo = () => {
  2033. const onBlur = (value, e) => {
  2034. console.log(value);
  2035. console.log(e);
  2036. };
  2037. const onFocus = (value, e) => {
  2038. console.log(value);
  2039. console.log(e);
  2040. };
  2041. return (
  2042. <>
  2043. <Select
  2044. filter
  2045. placeholder=""
  2046. style={{
  2047. width: 180,
  2048. }}
  2049. onBlur={onBlur}
  2050. onFocus={onFocus}
  2051. >
  2052. <Select.Option value="zhongguo">China</Select.Option>
  2053. <Select.Option value="hanguo">Koera</Select.Option>
  2054. <Select.Option value="deguo">Germany</Select.Option>
  2055. <Select.Option value="faguo">France</Select.Option>
  2056. </Select>
  2057. </>
  2058. );
  2059. };
  2060. export const SelectOnBlurOnFocus = () => <BlurDemo></BlurDemo>;
  2061. SelectOnBlurOnFocus.story = {
  2062. name: 'Select onBlur/onFocus',
  2063. };
  2064. const AutoAdjustOverflowDemo = () => {
  2065. const [list, setList] = useState([
  2066. {
  2067. value: 'abc',
  2068. label: '1111',
  2069. },
  2070. {
  2071. value: 'hotsoon',
  2072. label: '1112',
  2073. },
  2074. {
  2075. value: 'pipixia',
  2076. label: '1113',
  2077. },
  2078. {
  2079. value: 'toutiao',
  2080. label: '1114',
  2081. },
  2082. ]);
  2083. const onSearch = () => {
  2084. let newList = Array.from(
  2085. {
  2086. length: Math.floor(Math.random() * 10),
  2087. },
  2088. (v, i) => {
  2089. return {
  2090. value: i,
  2091. label: i,
  2092. };
  2093. }
  2094. );
  2095. setList(newList);
  2096. console.log(newList);
  2097. };
  2098. return (
  2099. <div
  2100. style={{
  2101. height: 180,
  2102. margin: 250,
  2103. border: '1px solid pink',
  2104. }}
  2105. >
  2106. <Select
  2107. optionList={list}
  2108. filter={true}
  2109. remote={true}
  2110. onSearch={onSearch}
  2111. style={{
  2112. width: 200,
  2113. }}
  2114. multiple
  2115. />
  2116. </div>
  2117. );
  2118. };
  2119. export const AutoAdjustOverflow = () => <AutoAdjustOverflowDemo></AutoAdjustOverflowDemo>;
  2120. AutoAdjustOverflow.story = {
  2121. name: 'autoAdjustOverflow',
  2122. };
  2123. const AllowCreateWithFilter = () => {
  2124. const [list, setList] = useState([
  2125. {
  2126. value: 'abc',
  2127. label: 'abc',
  2128. otherKey: 'abc',
  2129. },
  2130. {
  2131. value: 'hotsoon',
  2132. label: 'hotsoon',
  2133. otherKey: 'efg',
  2134. },
  2135. {
  2136. value: 'pipixia',
  2137. label: 'pipixia',
  2138. otherKey: 'hij',
  2139. },
  2140. {
  2141. value: 'toutiao',
  2142. label: 'toutiao',
  2143. otherKey: 'klm',
  2144. },
  2145. ]);
  2146. const filter = (sugInput, option) => {
  2147. let compareKey = option.otherKey ? option.otherKey.toUpperCase() : '';
  2148. let sug = sugInput.toUpperCase();
  2149. return compareKey.includes(sug);
  2150. };
  2151. return (
  2152. <div
  2153. style={{
  2154. height: 180,
  2155. margin: 250,
  2156. }}
  2157. >
  2158. <Select
  2159. optionList={list}
  2160. multiple
  2161. filter={filter}
  2162. style={{
  2163. width: 200,
  2164. }}
  2165. allowCreate
  2166. />
  2167. </div>
  2168. );
  2169. };
  2170. export const FilterAllowCreate = () => <AllowCreateWithFilter></AllowCreateWithFilter>;
  2171. FilterAllowCreate.story = {
  2172. name: 'Filter + allowCreate',
  2173. };
  2174. const SelectRefDemo = () => {
  2175. const ref = useRef();
  2176. const secondRef = useRef();
  2177. const [open, setOpen] = useState(false);
  2178. const list = [
  2179. {
  2180. value: 'abc',
  2181. label: 'Abc',
  2182. },
  2183. {
  2184. value: 'hotsoon',
  2185. label: 'Hotsoon',
  2186. },
  2187. {
  2188. value: 'pipixia',
  2189. label: 'Pipixia',
  2190. },
  2191. {
  2192. value: 'toutiao',
  2193. label: 'TooBuzz',
  2194. },
  2195. ];
  2196. const change = () => {
  2197. if (!open) {
  2198. ref.current.open();
  2199. setOpen(true);
  2200. } else {
  2201. ref.current.close();
  2202. setOpen(false);
  2203. }
  2204. };
  2205. const focus = () => {
  2206. ref.current.focus();
  2207. };
  2208. const clearInput = () => {
  2209. ref.current.clearInput();
  2210. };
  2211. const deselectAll = () => {
  2212. ref.current.deselectAll();
  2213. };
  2214. const selectAll = () => {
  2215. ref.current.selectAll();
  2216. };
  2217. return (
  2218. <>
  2219. <h4>onChangeWithObject = false</h4>
  2220. <Select
  2221. innerBottomSlot={
  2222. <div>
  2223. <Space>
  2224. <Button onClick={change}>close</Button>
  2225. <Button onClick={clearInput}>clearInput</Button>
  2226. <Button onClick={deselectAll}>deselectAll</Button>
  2227. <Button onClick={selectAll}>selectAll</Button>
  2228. </Space>
  2229. </div>
  2230. }
  2231. ref={ref}
  2232. onChange={e => console.log(e)}
  2233. placeholder="Business line"
  2234. style={{
  2235. width: 180,
  2236. }}
  2237. optionList={list}
  2238. filter
  2239. multiple
  2240. ></Select>
  2241. <Space>
  2242. <Button onClick={change}>open</Button>
  2243. <Button onClick={focus}>focus</Button>
  2244. <Button onClick={clearInput}>clearInput</Button>
  2245. <Button onClick={deselectAll}>deselectAll</Button>
  2246. <Button onClick={selectAll}>selectAll</Button>
  2247. </Space>
  2248. <h4
  2249. style={{
  2250. marginTop: 20,
  2251. }}
  2252. >
  2253. onChangeWithObject = true
  2254. </h4>
  2255. <Select
  2256. innerBottomSlot={
  2257. <div>
  2258. <Space></Space>
  2259. </div>
  2260. }
  2261. onChange={e => console.log(e)}
  2262. onChangeWithObject
  2263. ref={secondRef}
  2264. placeholder="Business line"
  2265. style={{
  2266. width: 180,
  2267. }}
  2268. optionList={list}
  2269. filter
  2270. multiple
  2271. ></Select>
  2272. <Space>
  2273. <Button onClick={() => secondRef.current.deselectAll()}>deselectAll</Button>
  2274. <Button onClick={() => secondRef.current.selectAll()}>selectAll</Button>
  2275. </Space>
  2276. </>
  2277. );
  2278. };
  2279. export const Ref = () => <SelectRefDemo />;
  2280. Ref.story = {
  2281. name: 'ref',
  2282. };
  2283. export const CustomTriggerDemo = () => <CustomTrigger />;
  2284. CustomTriggerDemo.story = {
  2285. name: 'custom trigger'
  2286. }
  2287. class VirtualizeClassDemo extends React.Component {
  2288. constructor(props) {
  2289. super(props);
  2290. // this.handleSearch = this.handleSearch.bind(this);
  2291. let newOptions = Array.from({ length: 1000 }, (v, i) => ({ label: `o-${i}`, value: `v-${v}-${i}` }));
  2292. this.state = {
  2293. optionList: newOptions,
  2294. };
  2295. }
  2296. render() {
  2297. let { groups, optionList } = this.state;
  2298. let virtualize = {
  2299. height: 300,
  2300. widht: '100%',
  2301. itemSize: 36,
  2302. };
  2303. return (
  2304. <>
  2305. <Select
  2306. placeholder=""
  2307. style={{ width: 180 }}
  2308. filter
  2309. onSearch={this.handleSearch}
  2310. virtualize={virtualize}
  2311. optionList={optionList}
  2312. ></Select>
  2313. </>
  2314. );
  2315. }
  2316. }
  2317. export const VirtualizeDemo = () => <VirtualizeClassDemo />;
  2318. VirtualizeDemo.story = {
  2319. name: 'virtualize select'
  2320. }
  2321. const SelectPosition = () => {
  2322. return (
  2323. <div
  2324. style={{
  2325. height: 500,
  2326. border: '1px solid red',
  2327. overflow: 'auto',
  2328. }}
  2329. >
  2330. <p>p</p>
  2331. <p>p</p>
  2332. <p>p</p>
  2333. <p>p</p>
  2334. <p>p</p>
  2335. <p>p</p>
  2336. <p>p</p>
  2337. <p>p</p>
  2338. <p>p</p>
  2339. <p>p</p>
  2340. <p>p</p>
  2341. <p>p</p>
  2342. <p>p</p>
  2343. <p>p</p>
  2344. <p>p</p>
  2345. <p>p</p>
  2346. <p>p</p>
  2347. <p>p</p>
  2348. <p>p</p>
  2349. <p>p</p>
  2350. <p>p</p>
  2351. <p>p</p>
  2352. <p>p</p>
  2353. <Select
  2354. defaultValue="abc"
  2355. style={{
  2356. width: 120,
  2357. }}
  2358. >
  2359. <Option value="abc">抖音</Option>
  2360. <Option value="hotsoon">火山</Option>
  2361. <Option value="pipixia" disabled>
  2362. 皮皮虾
  2363. </Option>
  2364. <Option value="xigua">西瓜视频</Option>
  2365. </Select>
  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. <p>p</p>
  2381. <p>p</p>
  2382. <p>p</p>
  2383. <p>p</p>
  2384. <p>p</p>
  2385. <p>p</p>
  2386. <p>p</p>
  2387. <p>p</p>
  2388. <p>p</p>
  2389. <p>p</p>
  2390. <p>p</p>
  2391. <p>p</p>
  2392. <p>p</p>
  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. </div>
  2409. );
  2410. };
  2411. export { SelectPosition };
  2412. SelectPosition.story = {
  2413. name: 'Select position problem'
  2414. }
  2415. const RenderOptionDemo = () => {
  2416. const renderOptionItem = renderProps => {
  2417. const {
  2418. disabled,
  2419. selected,
  2420. label,
  2421. value,
  2422. focused,
  2423. className,
  2424. style,
  2425. onMouseEnter,
  2426. onClick,
  2427. empty,
  2428. emptyContent,
  2429. ...rest
  2430. } = renderProps;
  2431. const optionCls = classNames({
  2432. ['custom-option-render']: true,
  2433. ['custom-option-render-focused']: focused,
  2434. ['custom-option-render-disabled']: disabled,
  2435. ['custom-option-render-selected']: selected,
  2436. }); // Notice:
  2437. // 1.props传入的style需在wrapper dom上进行消费,否则在虚拟化场景下会无法正常使用
  2438. // 2.选中(selected)、聚焦(focused)、禁用(disabled)等状态的样式需自行加上,你可以从props中获取到相对的boolean值
  2439. // 3.onMouseEnter需在wrapper dom上绑定,否则上下键盘操作时显示会有问题
  2440. return (
  2441. <div
  2442. style={style}
  2443. className={optionCls}
  2444. onClick={() => onClick()}
  2445. onMouseEnter={e => onMouseEnter()}
  2446. >
  2447. <Checkbox checked={selected} />
  2448. <div className="option-right">{label}</div>
  2449. </div>
  2450. );
  2451. };
  2452. return (
  2453. <>
  2454. <Select
  2455. filter
  2456. dropdownClassName="components-select-demo-renderOptionItem"
  2457. optionList={optionList}
  2458. style={{
  2459. width: 300,
  2460. }}
  2461. renderOptionItem={renderOptionItem}
  2462. />
  2463. <br />
  2464. <br />
  2465. <Select
  2466. filter
  2467. multiple
  2468. dropdownClassName="components-select-demo-renderOptionItem"
  2469. optionList={optionList}
  2470. style={{
  2471. width: 450,
  2472. }}
  2473. renderOptionItem={renderOptionItem}
  2474. />
  2475. </>
  2476. );
  2477. };
  2478. export const RenderOptionItem = () => <RenderOptionDemo />;
  2479. RenderOptionItem.story = {
  2480. name: 'renderOptionItem',
  2481. };
  2482. const FilterDefaultOpen = () => {
  2483. const [value1, setValue1] = useState('a-1');
  2484. return (
  2485. <>
  2486. <Select
  2487. placeholder=""
  2488. style={{
  2489. width: 180,
  2490. }}
  2491. filter
  2492. defaultOpen
  2493. >
  2494. <Select.OptGroup label="Asia">
  2495. <Select.Option value="a-1">China</Select.Option>
  2496. <Select.Option value="a-2">Koera</Select.Option>
  2497. </Select.OptGroup>
  2498. <Select.OptGroup label="Europe">
  2499. <Select.Option value="b-1">Germany</Select.Option>
  2500. <Select.Option value="b-2">France</Select.Option>
  2501. </Select.OptGroup>
  2502. <Select.OptGroup label="South America">
  2503. <Select.Option value="c-1">Peru</Select.Option>
  2504. </Select.OptGroup>
  2505. </Select>
  2506. <Select
  2507. placeholder=""
  2508. style={{
  2509. width: 180,
  2510. marginLeft: 20,
  2511. }}
  2512. filter
  2513. defaultOpen
  2514. defaultValue="a-2"
  2515. >
  2516. <Select.OptGroup label="Asia">
  2517. <Select.Option value="a-1">China</Select.Option>
  2518. <Select.Option value="a-2">Koera</Select.Option>
  2519. </Select.OptGroup>
  2520. <Select.OptGroup label="Europe">
  2521. <Select.Option value="b-1">Germany</Select.Option>
  2522. <Select.Option value="b-2">France</Select.Option>
  2523. </Select.OptGroup>
  2524. <Select.OptGroup label="South America">
  2525. <Select.Option value="c-1">Peru</Select.Option>
  2526. </Select.OptGroup>
  2527. </Select>
  2528. <Select
  2529. placeholder=""
  2530. style={{
  2531. width: 180,
  2532. marginLeft: 20,
  2533. }}
  2534. filter
  2535. defaultOpen
  2536. value={value1}
  2537. onChange={val => setValue1(val)}
  2538. >
  2539. <Select.Option value="a-1">China</Select.Option>
  2540. <Select.Option value="a-2">Koera</Select.Option>
  2541. <Select.Option value="b-1">Germany</Select.Option>
  2542. <Select.Option value="b-2">France</Select.Option>
  2543. <Select.Option value="c-1">Peru</Select.Option>
  2544. </Select>
  2545. </>
  2546. );
  2547. };
  2548. export { FilterDefaultOpen };
  2549. FilterDefaultOpen.story = {
  2550. name: 'Filter + defaultOpen'
  2551. };
  2552. const CustomSelect = props => {
  2553. const { fieldRef, ...rest } = props;
  2554. return <Select {...rest} ref={fieldRef} />;
  2555. };
  2556. const CustomFieldSelect = withField(CustomSelect);
  2557. const RefDemo = () => {
  2558. const fieldRef = useRef(null);
  2559. const onChange = () => {
  2560. console.log(fieldRef);
  2561. fieldRef.current.open();
  2562. debugger;
  2563. };
  2564. return (
  2565. <Form>
  2566. <CustomFieldSelect field="test" initValue="se" fieldRef={fieldRef}></CustomFieldSelect>
  2567. <Button onClick={onChange}>change</Button>
  2568. </Form>
  2569. );
  2570. };
  2571. export const RefFieldDemo = () => <RefDemo />;
  2572. RefFieldDemo.story = {
  2573. name: 'Ref field demo',
  2574. };
  2575. const ValueZeroDemo = () => {
  2576. const list = [
  2577. {
  2578. value: 6,
  2579. label: '抖音小视频',
  2580. otherKey: 0,
  2581. },
  2582. {
  2583. value: 1,
  2584. label: '火山小视频',
  2585. disabled: true,
  2586. otherKey: 1,
  2587. },
  2588. {
  2589. value: 'pipixia',
  2590. label: '皮皮虾',
  2591. otherKey: 2,
  2592. },
  2593. {
  2594. value: 'toutiao',
  2595. label: '今日头条',
  2596. otherKey: 3,
  2597. },
  2598. ];
  2599. return (
  2600. <Select
  2601. placeholder="请选择业务线"
  2602. style={{
  2603. width: 180,
  2604. }}
  2605. optionList={list}
  2606. value={0}
  2607. renderSelectedItem={option => option.label + 1}
  2608. ></Select>
  2609. );
  2610. };
  2611. export const Value0 = () => <ValueZeroDemo />;
  2612. Value0.story = {
  2613. name: 'value=0',
  2614. };
  2615. const Highlight = () => {
  2616. const searchWords = ['do', 'dollar'];
  2617. const sourceString = 'aaa do dollar aaa';
  2618. const result = getHighLightTextHTML({
  2619. searchWords,
  2620. sourceString,
  2621. });
  2622. const result2 = getHighLightTextHTML({
  2623. searchWords: ['z'],
  2624. sourceString: 'aaazaaazaaa',
  2625. });
  2626. return result2;
  2627. };
  2628. export const _Highlight = () => <Highlight />;
  2629. _Highlight.story = {
  2630. name: 'highlight',
  2631. };
  2632. export const ScrollIntoView = () => (
  2633. <div>
  2634. <p>single selection</p>
  2635. <Select defaultValue='v-11' defaultOpen style={{ width: 120, marginBottom: 300 }}>
  2636. {new Array(50).fill(null).map((item, idx) => (
  2637. <Option value={`v-${idx}`} key={idx}>{`option-${idx}`}</Option>
  2638. ))}
  2639. </Select>
  2640. <p>single selection with no selected item</p>
  2641. <Select style={{ marginBottom: 300, width: 120 }}>
  2642. {new Array(50).fill(null).map((item, idx) => (
  2643. <Option value={`v-${idx}`} key={idx}>{`option-${idx}`}</Option>
  2644. ))}
  2645. </Select>
  2646. <p>The selected node is the last</p>
  2647. <Select defaultValue='v-49' defaultOpen style={{ marginBottom: 300, width: 120 }}>
  2648. {new Array(50).fill(null).map((item, idx) => (
  2649. <Option value={`v-${idx}`} key={idx}>{`option-${idx}`}</Option>
  2650. ))}
  2651. </Select>
  2652. <p>The selected node is the first</p>
  2653. <Select defaultValue='v-0' style={{ marginBottom: 300, width: 120 }}>
  2654. {new Array(50).fill(null).map((item, idx) => (
  2655. <Option value={`v-${idx}`} key={idx}>{`option-${idx}`}</Option>
  2656. ))}
  2657. </Select>
  2658. <p>multiple selection</p>
  2659. <Select defaultValue={['v-25', 'v-9']} multiple style={{ marginBottom: 300, width: 220 }}>
  2660. {new Array(30).fill(null).map((item, idx) => (
  2661. <Option value={`v-${idx}`} key={idx}>{`option-${idx}`}</Option>
  2662. ))}
  2663. </Select>
  2664. <p>multiple selection with no selected item</p>
  2665. <Select multiple style={{ marginBottom: 300, width: 220 }}>
  2666. {new Array(30).fill(null).map((item, idx) => (
  2667. <Option value={`v-${idx}`} key={idx}>{`option-${idx}`}</Option>
  2668. ))}
  2669. </Select>
  2670. </div>
  2671. );
  2672. ScrollIntoView.story = {
  2673. name: 'scroll into view',
  2674. };
  2675. export const SelectInputPropsDemo = () => {
  2676. const inputProps = {
  2677. className: 'ttt',
  2678. onCompositionEnd: (v) => console.log(v.target.value)
  2679. };
  2680. return (
  2681. <Select
  2682. // onSearch={(v) => console.log(v)}
  2683. optionList={list}
  2684. inputProps={inputProps}
  2685. multiple
  2686. filter
  2687. style={{ width: 200 }}
  2688. >
  2689. </Select>
  2690. )
  2691. };
  2692. SelectInputPropsDemo.story = {
  2693. name: 'inputProps',
  2694. };
  2695. export const AutoClearSearchValue = () => {
  2696. const [val, setVal] = useState(['semi1']);
  2697. const optionList = [
  2698. { label: 'semi1', value: 'semi1' },
  2699. { label: 'semi2', value: 'semi2' },
  2700. { label: 'semi3', value: 'semi3' },
  2701. { label: 'semi4', value: 'semi4' },
  2702. { label: 'semi5', value: 'semi5' },
  2703. { label: 'semi6', value: 'semi6' },
  2704. ];
  2705. return (
  2706. <>
  2707. <h4>Controlled mode + multiple</h4>
  2708. <Select style={{ width: 400 }} multiple optionList={optionList} filter value={val} onChange={value => setVal(value)} autoClearSearchValue={false}></Select>
  2709. <br />
  2710. <br />
  2711. <h4>Uncontrolled mode + multiple</h4>
  2712. <Select style={{ width: 400 }} multiple optionList={optionList} filter autoClearSearchValue={false}></Select>
  2713. <h4>Uncontrolled mode + multiple + defaultValue</h4>
  2714. <Select style={{ width: 400 }} multiple optionList={optionList} filter defaultValue={['semi2']} autoClearSearchValue={false}></Select>
  2715. </>
  2716. )
  2717. }
  2718. SelectInputPropsDemo.story = {
  2719. name: 'AutoClearSearchValue',
  2720. };
  2721. export const RenderSelectedItemCallCount = () => {
  2722. const list = [
  2723. { "name": "夏可漫", "email": "[email protected]", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/avatarDemo.jpeg" },
  2724. { "name": "申悦", "email": "[email protected]", "avatar": "https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bag.jpeg" },
  2725. { "name": "曲晨一", "email": "[email protected]", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/8bd8224511db085ed74fea37205aede5.jpg" },
  2726. { "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" },
  2727. { "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" },
  2728. { "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" },
  2729. ]
  2730. const renderMultipleWithCustomTag = (optionNode, { onClose }) => {
  2731. console.count('rerender')
  2732. const content = (
  2733. <Tag
  2734. avatarSrc={optionNode.avatar}
  2735. avatarShape='circle'
  2736. closable={true}
  2737. onClose={onClose}
  2738. size='large'
  2739. >
  2740. {optionNode.name}
  2741. </Tag>
  2742. );
  2743. return {
  2744. isRenderInTag: false,
  2745. content
  2746. };
  2747. }
  2748. const renderCustomOption = (item, index) => {
  2749. const optionStyle = {
  2750. display: 'flex',
  2751. paddingLeft: 24,
  2752. paddingTop: 10,
  2753. paddingBottom: 10
  2754. }
  2755. return (
  2756. <Select.Option key={index} value={item.name} style={optionStyle} showTick={true} {...item} key={item.email}>
  2757. <Avatar size="small" src={item.avatar} />
  2758. <div style={{ marginLeft: 8 }}>
  2759. <div style={{ fontSize: 14 }}>{item.name}</div>
  2760. <div style={{ color: 'var(--color-text-2)', fontSize: 12, lineHeight: '16px', fontWeight: 'normal' }}>{item.email}</div>
  2761. </div>
  2762. </Select.Option>
  2763. )
  2764. }
  2765. return (
  2766. <>
  2767. <Select
  2768. placeholder='请选择'
  2769. showClear
  2770. multiple
  2771. maxTagCount={2}
  2772. style={{ width: 280, height: 40 }}
  2773. onChange={v => console.log(v)}
  2774. defaultValue={'夏可漫'}
  2775. renderSelectedItem={renderMultipleWithCustomTag}
  2776. >
  2777. {list.map((item, index) => renderCustomOption(item, index))}
  2778. </Select>
  2779. </>
  2780. );
  2781. }
  2782. RenderSelectedItemCallCount.story = {
  2783. name: 'RenderSelectedItemCallCount',
  2784. };