input.stories.js 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909
  1. import React, { useState, useCallback } from 'react';
  2. import GraphemeSplitter from 'grapheme-splitter';
  3. import { isFunction, isString } from 'lodash';
  4. import {
  5. Input,
  6. InputGroup,
  7. TextArea,
  8. TimePicker,
  9. DatePicker,
  10. AutoComplete,
  11. Cascader,
  12. Select,
  13. TagInput,
  14. Tree,
  15. TreeSelect,
  16. Icon,
  17. TabPane,
  18. Tabs,
  19. Button,
  20. Typography,
  21. Switch,
  22. Form,
  23. Space,
  24. } from '../../index';
  25. import './input.scss';
  26. import RTLWrapper from '../../configProvider/_story/RTLDirection/RTLWrapper';
  27. import { IconSearch, IconCopy, IconClear, IconStar } from '@douyinfe/semi-icons';
  28. export default {
  29. title: 'Input',
  30. parameters: {
  31. chromatic: { disableSnapshot: true },
  32. }
  33. }
  34. const { Title, Text } = Typography;
  35. const log = (...args) => console.log(...args);
  36. export const _Input = () => (
  37. <div
  38. className="input"
  39. style={{
  40. width: 200,
  41. }}
  42. >
  43. <Input />
  44. <Input validateStatus="warning" />
  45. <Input validateStatus="error" />
  46. <br />
  47. <br />
  48. <Input size="large" />
  49. <Input size="large" validateStatus="warning" />
  50. <Input size="large" validateStatus="error" />
  51. <br />
  52. <br />
  53. <Input size="small" />
  54. <Input size="small" validateStatus="warning" />
  55. <Input size="small" validateStatus="error" />
  56. </div>
  57. );
  58. _Input.parameters = {
  59. chromatic: { disableSnapshot: false },
  60. };
  61. export const InputAutofocus = () => (
  62. <div className="input">
  63. <Input placeholder="ies input" autofocus />
  64. </div>
  65. );
  66. InputAutofocus.story = {
  67. name: 'Input autofocus',
  68. };
  69. export const InputPlaceholder = () => (
  70. <div className="input">
  71. <Input placeholder="ies input" />
  72. </div>
  73. );
  74. InputPlaceholder.story = {
  75. name: 'Input placeholder',
  76. };
  77. export const InputDisabled = () => (
  78. <div className="input">
  79. <Input disabled value="禁用文本框值" />
  80. </div>
  81. );
  82. InputDisabled.parameters = {
  83. chromatic: { disableSnapshot: false },
  84. };
  85. InputDisabled.story = {
  86. name: 'Input disabled',
  87. };
  88. export const InputClearable = () => (
  89. <div className="input">
  90. <Input showClear defaultValue="ies" />
  91. </div>
  92. );
  93. InputClearable.story = {
  94. name: 'Input clearable',
  95. };
  96. export const InputPrefixSuffixDemo = () => (
  97. <div className="input">
  98. <Input prefix="search" showClear defaultValue="Semi Design" />
  99. <Input prefix={<span>pre</span>} showClear defaultValue="Semi Design" />
  100. <Input prefix={<span>pre</span>} showClear defaultValue="Semi Design" />
  101. <Input suffix={<IconSearch />} autofocus showClear defaultValue="Semi Design"></Input>
  102. <Input suffix="Semi Design" showClear defaultValue="Semi Design"></Input>
  103. <Input
  104. suffix={
  105. <Typography.Text
  106. strong
  107. type="secondary"
  108. style={{
  109. margin: '0 8px',
  110. }}
  111. >
  112. Suffix
  113. </Typography.Text>
  114. }
  115. showClear
  116. defaultValue="Semi Design"
  117. ></Input>
  118. </div>
  119. );
  120. InputPrefixSuffixDemo.story = {
  121. name: '前缀/后缀 Input prefix suffix',
  122. };
  123. InputPrefixSuffixDemo.parameters = {
  124. chromatic: { disableSnapshot: false },
  125. };
  126. export const InputAddonBeforeAddonAfter = () => (
  127. <div className="input">
  128. <Input addonBefore="https://" addonAfter=".com" />
  129. </div>
  130. );
  131. InputAddonBeforeAddonAfter.story = {
  132. name: '前置/后置标签 Input addonBefore addonAfter',
  133. };
  134. InputAddonBeforeAddonAfter.parameters = {
  135. chromatic: { disableSnapshot: false },
  136. };
  137. export const InputPassword = () => (
  138. <div className="input">
  139. <Input mode="password" placeholder="请输入密码" />
  140. <Input mode="password" defaultValue="ies" />
  141. <Input mode="password" showClear defaultValue="ies" />
  142. <Input mode="password" disabled defaultValue="ies" />
  143. </div>
  144. );
  145. InputPassword.story = {
  146. name: 'Input password',
  147. };
  148. InputPassword.parameters = {
  149. chromatic: { disableSnapshot: false },
  150. };
  151. export const ControlInput = () => {
  152. const [value, setValue] = useState('initString');
  153. return (
  154. <div className="input">
  155. <Input value={value} onChange={setValue} showClear />
  156. <Input value={value} onChange={log} showClear />
  157. </div>
  158. );
  159. };
  160. ControlInput.story = { name: '受控组件' };
  161. export const UnControlInput = () => (
  162. <div className="input">
  163. <Input onChange={v => console.log(v)} defaultValue="initString" />
  164. </div>
  165. );
  166. UnControlInput.story = { name: '非受控组件' };
  167. export const Password = () => (
  168. <div className="input">
  169. <Input type="password" />
  170. </div>
  171. );
  172. Password.story = {
  173. name: 'password',
  174. };
  175. const treeData = [
  176. {
  177. label: '亚洲',
  178. value: 'Asia',
  179. key: '0',
  180. children: [
  181. {
  182. label: '中国',
  183. value: 'China',
  184. key: '0-0',
  185. children: [
  186. {
  187. label: '北京',
  188. value: 'Beijing',
  189. key: '0-0-0',
  190. },
  191. {
  192. label: '上海',
  193. value: 'Shanghai',
  194. key: '0-0-1',
  195. },
  196. ],
  197. },
  198. ],
  199. },
  200. {
  201. label: '北美洲',
  202. value: 'North America',
  203. key: '1',
  204. },
  205. ];
  206. export const Group = () => (
  207. <div className="input">
  208. <InputGroup>
  209. <Select
  210. placeholder="Name"
  211. style={{
  212. width: 100,
  213. }}
  214. optionList={[
  215. {
  216. value: 1,
  217. label: 1,
  218. },
  219. {
  220. value: 2,
  221. label: 2,
  222. },
  223. ]}
  224. />
  225. <Select
  226. placeholder="Score"
  227. style={{
  228. width: 140,
  229. }}
  230. optionList={[
  231. {
  232. value: 1,
  233. label: 1,
  234. },
  235. {
  236. value: 2,
  237. label: 2,
  238. },
  239. ]}
  240. />
  241. </InputGroup>
  242. <br />
  243. <br />
  244. {/* <InputGroup>
  245. <Input placeholder="Name" style={{ width: 100 }} />
  246. <InputNumber placeholder="Score" style={{ width: 140 }} />
  247. </InputGroup>
  248. <br/><br/>
  249. <InputGroup size={'small'}>
  250. <Select style={{ width: '100px' }} defaultValue='home'>
  251. <Option value='home'>Home</Option>
  252. <Option value='work'>Work</Option>
  253. </Select>
  254. <AutoComplete
  255. data={['Beijing Haidian']}
  256. placeholder='Address: '
  257. style={{ width: 180 }}
  258. >
  259. </AutoComplete>
  260. </InputGroup>
  261. <br/><br/>
  262. <InputGroup size={'small'}>
  263. <Select style={{ width: '100px' }} defaultValue='signup'>
  264. <Option value='signup'>Sign Up</Option>
  265. <Option value='signin'>Sign In</Option>
  266. </Select>
  267. <Input placeholder="Email" style={{ width: 180 }} />
  268. </InputGroup>
  269. <br/><br/>
  270. <InputGroup>
  271. <Select style={{ width: '100px' }} defaultValue='signup'>
  272. <Option value='signup'>Sign Up</Option>
  273. <Option value='signin'>Sign In</Option>
  274. </Select>
  275. <TreeSelect
  276. style={{ width: 300 }}
  277. treeData={treeData}
  278. placeholder="Please select"
  279. />
  280. </InputGroup>
  281. <br/><br/>
  282. <InputGroup>
  283. <Select style={{ width: 100 }} defaultValue='signup'>
  284. <Option value='signup'>Sign Up</Option>
  285. <Option value='signin'>Sign In</Option>
  286. </Select>
  287. <TreeSelect
  288. style={{ width: 300 }}
  289. treeData={treeData}
  290. placeholder="Please select"
  291. />
  292. <Cascader
  293. style={{ width: 300 }}
  294. treeData={treeData}
  295. placeholder="Please select"
  296. />
  297. </InputGroup> */}
  298. </div>
  299. );
  300. Group.story = {
  301. name: 'group',
  302. };
  303. Group.parameters = {
  304. chromatic: { disableSnapshot: false },
  305. };
  306. export const Textarea = () => <TextArea limit={100} onChange={v => console.log(v)} />;
  307. Textarea.story = {
  308. name: 'textarea',
  309. };
  310. export const AutosizeTextarea = () => (
  311. <div className="input">
  312. <TextArea autosize onChange={v => console.log(v)} />
  313. {/* <TextArea autosize limit={500} onChange={v => console.log(v)} />
  314. <TextArea autosize rows={1} onChange={v => console.log(v)} /> */}
  315. </div>
  316. );
  317. AutosizeTextarea.story = {
  318. name: 'autosize textarea',
  319. };
  320. export const TextareaInnerMaxCount = () => (
  321. <div className="input">
  322. <TextArea defaultValue="TextArea without maxCount" />
  323. <br />
  324. <br />
  325. <TextArea maxCount={10} defaultValue="0123456789" />
  326. <br />
  327. <br />
  328. <TextArea maxCount={10} defaultValue="Semi Design System exceed maxCount" />
  329. <br />
  330. <br />
  331. <TextArea maxCount={10} defaultValue="Semi Design System autosize" autosize rows={2} />
  332. <br />
  333. <br />
  334. <TextArea maxCount={10} defaultValue="Semi Design System disabled" disabled />
  335. <br />
  336. <br />
  337. <TextArea maxCount={10} defaultValue="Semi Design System readonly" readonly />
  338. <br />
  339. <br />
  340. <TextArea maxCount={10} defaultValue="Semi Design System warning" validateStatus="warning" />
  341. <br />
  342. <br />
  343. <TextArea maxCount={10} defaultValue="Semi Design System error" validateStatus="error" />
  344. <br />
  345. <br />
  346. <TextArea maxCount={10} defaultValue="Semi Design System normal" validateStatus="normal" />
  347. <br />
  348. <br />
  349. </div>
  350. );
  351. TextareaInnerMaxCount.story = {
  352. name: 'textarea inner maxCount ',
  353. };
  354. TextareaInnerMaxCount.parameters = {
  355. chromatic: { disableSnapshot: false },
  356. };
  357. class RefDemo extends React.Component {
  358. constructor() {
  359. super();
  360. this.state = {
  361. loading: false,
  362. };
  363. this.inputRef = React.createRef();
  364. this.focus = this.focus.bind(this);
  365. }
  366. focus(inputValue) {
  367. console.log(this.inputRef);
  368. debugger;
  369. this.inputRef.current.focus();
  370. }
  371. render() {
  372. return (
  373. <div>
  374. <Input ref={this.inputRef} />
  375. <Button onClick={this.focus}>focus</Button>
  376. </div>
  377. );
  378. }
  379. }
  380. class TARefDemo extends React.Component {
  381. constructor() {
  382. super();
  383. this.ref = React.createRef();
  384. this.focus = this.focus.bind(this);
  385. this.blur = this.blur.bind(this);
  386. }
  387. focus(val) {
  388. console.log(this.ref, val);
  389. this.ref.current.focus();
  390. }
  391. blur() {
  392. this.ref.current.blur();
  393. }
  394. render() {
  395. return (
  396. <div>
  397. <TextArea ref={this.ref} />
  398. <Button onClick={this.focus}>focus</Button>
  399. <Button onClick={this.blur}>blur</Button>
  400. </div>
  401. );
  402. }
  403. }
  404. export const InputRefDemo = () => (
  405. <>
  406. <RefDemo />
  407. <TARefDemo />
  408. </>
  409. );
  410. InputRefDemo.story = {
  411. name: 'ref的使用',
  412. };
  413. export const InputHideSuffix = () => (
  414. <div className="input" onClick={() => console.log('clicking DIV....')}>
  415. <Input suffix={<IconCopy onClick={() => console.log('clicking')} />} showClear hideSuffix />
  416. </div>
  417. );
  418. InputHideSuffix.story = {
  419. name: 'Input hideSuffix',
  420. };
  421. InputHideSuffix.parameters = {
  422. chromatic: { disableSnapshot: false },
  423. };
  424. export const TextareaInTabPane = () => (
  425. <div>
  426. <Tabs type="line">
  427. <TabPane tab="文档" itemKey="1">
  428. <TextArea
  429. autosize={true}
  430. value={
  431. '卡垃圾速度快;发神经地方;京阿是;大家;发生空间的浪费空间阿莱克斯\n决定分开了京阿是快进到风口浪尖阿斯顿克己复礼卡就是快乐减肥空间就是快乐的健康京阿是快的\n解放路口京阿是来对\n抗肌肤阿就是大家阿节点空间阿斯顿空间卡经典款九分裤阿是加快立法开始饭卡空间发考\n虑时间快放假啊肯德基快放辣椒的;放假啊;江东父老卡快放假\n啊快到家快放假啊的快乐减肥咖哩鸡的卡上看到肌肤卡经典空间卡;框架'
  432. }
  433. />
  434. </TabPane>
  435. <TabPane tab="快速起步" itemKey="2">
  436. <TextArea
  437. autosize={true}
  438. value={
  439. '1234\n卡垃圾速度快;发神经地方;京阿是;大家;发生空间的浪费空间阿莱克斯\n决定分开了京阿是快进到风口浪尖阿斯顿克己复礼卡就是快乐减肥空间就是快乐的健康京阿是快的\n解放路口京阿是来对\n抗肌肤阿就是大家阿节点空间阿斯顿空间卡经典款九分裤阿是加快立法开始饭卡空间发考\n虑时间快放假啊肯德基快放辣椒的;放假啊;江东父老卡快放假\n啊快到家快放假啊的快乐减肥咖哩鸡的卡上看到肌肤卡经典空间卡;框架'
  440. }
  441. />
  442. </TabPane>
  443. </Tabs>
  444. </div>
  445. );
  446. TextareaInTabPane.story = {
  447. name: 'Textarea in TabPane',
  448. };
  449. const ControlTextarea = () => {
  450. const [value, setValue] = useState('initString');
  451. return (
  452. <>
  453. <TextArea value={value} onChange={setValue} />
  454. <br />
  455. <TextArea value={value} onChange={setValue} autosize />
  456. </>
  457. );
  458. };
  459. export const ControlledTextarea = () => <ControlTextarea />;
  460. ControlledTextarea.story = {
  461. name: '受控textarea'
  462. }
  463. export const FixAddonBeforeShowClear = () => (
  464. <Space wrap>
  465. <Input
  466. style={{
  467. width: 300,
  468. }}
  469. autofocus
  470. defaultValue="Semi Design"
  471. addonBefore="http://"
  472. showClear
  473. />
  474. <Input
  475. style={{
  476. width: 300,
  477. }}
  478. defaultValue="Semi Design"
  479. addonBefore="http://"
  480. addonAfter=".com"
  481. showClear
  482. />
  483. <Input
  484. style={{
  485. width: 300,
  486. }}
  487. defaultValue="Semi Design"
  488. showClear
  489. />
  490. <Input
  491. style={{
  492. width: 300,
  493. }}
  494. defaultValue="Semi Design"
  495. addonBefore="http://"
  496. />
  497. <Input
  498. style={{
  499. width: 300,
  500. }}
  501. defaultValue="Semi Design"
  502. />
  503. <Input
  504. style={{
  505. width: 300,
  506. }}
  507. defaultValue="Semi Design"
  508. addonBefore="http://"
  509. showClear
  510. validateStatus="warning"
  511. />
  512. <Input
  513. style={{
  514. width: 300,
  515. }}
  516. defaultValue="Semi Design"
  517. addonBefore="http://"
  518. showClear
  519. validateStatus="error"
  520. />
  521. <Input
  522. style={{
  523. width: 300,
  524. }}
  525. defaultValue="Semi Design"
  526. addonBefore="http://"
  527. mode="password"
  528. showClear
  529. />
  530. <Input
  531. style={{
  532. width: 300,
  533. }}
  534. defaultValue="Semi Design"
  535. addonBefore="http://"
  536. addonAfter=".com"
  537. mode="password"
  538. showClear
  539. />
  540. <Input
  541. style={{
  542. width: 300,
  543. }}
  544. defaultValue="Semi Design"
  545. addonBefore="http://"
  546. addonAfter=".com"
  547. mode="password"
  548. showClear
  549. size="small"
  550. />
  551. <Input
  552. style={{
  553. width: 300,
  554. }}
  555. defaultValue="Semi Design"
  556. addonBefore="http://"
  557. addonAfter=".com"
  558. mode="password"
  559. showClear
  560. size="large"
  561. />
  562. </Space>
  563. );
  564. FixAddonBeforeShowClear.story = {
  565. name: 'fix addonBefore + showClear',
  566. };
  567. FixAddonBeforeShowClear.parameters = {
  568. chromatic: { disableSnapshot: false },
  569. };
  570. export const FocusWhenClickPrefixSuffix = () => (
  571. <Space wrap>
  572. <Input
  573. style={{ width: 200 }}
  574. onFocus={() => console.log('focused')}
  575. prefix="search"
  576. defaultValue="Semi Design"
  577. />
  578. <Input
  579. style={{ width: 200 }}
  580. onFocus={() => console.log('focused')}
  581. onBlur={() => {
  582. console.log('blur');
  583. }}
  584. suffix={<IconSearch />}
  585. defaultValue="Semi Design"
  586. ></Input>
  587. <Input
  588. disabled
  589. style={{ width: 200 }}
  590. onFocus={() => console.log('focused')}
  591. prefix="search"
  592. suffix={<IconSearch />}
  593. defaultValue="disabled"
  594. />
  595. </Space>
  596. );
  597. FocusWhenClickPrefixSuffix.story = {
  598. name: 'focus when click prefix/suffix',
  599. };
  600. export const GetValueLengthEmojiLengthProcess = () => {
  601. function getValueLength(str) {
  602. if (isString(str)) {
  603. const splitter = new GraphemeSplitter();
  604. return splitter.countGraphemes(str);
  605. } else {
  606. return -1;
  607. }
  608. }
  609. const [getVisibleLengthFC, setGetVisibleLength] = useState(() => getValueLength);
  610. const [value, setValue] = useState();
  611. const handleSwitch = useCallback(value => {
  612. if (value) {
  613. setGetVisibleLength(() => getValueLength);
  614. } else {
  615. setGetVisibleLength(value);
  616. }
  617. }, []);
  618. const strExceed10 = '0123456789semi design';
  619. return (
  620. <div className="input">
  621. <div>
  622. <Title
  623. heading={6}
  624. style={{
  625. margin: 8,
  626. }}
  627. >
  628. getValueLength = {isFunction(getVisibleLengthFC) ? 'function' : 'null'}
  629. </Title>
  630. <Switch checked={isFunction(getVisibleLengthFC)} onChange={handleSwitch}>
  631. getValueLength
  632. </Switch>
  633. </div>
  634. <h4>maxLength=10</h4>
  635. <Input
  636. maxLength={10}
  637. getValueLength={getVisibleLengthFC}
  638. style={{
  639. width: 200,
  640. }}
  641. />
  642. <h4>controlled mode + maxLength=10</h4>
  643. <Input
  644. value={value}
  645. onChange={value => {
  646. console.log('input change', value);
  647. setValue(value);
  648. }}
  649. maxLength={10}
  650. getValueLength={getVisibleLengthFC}
  651. style={{
  652. width: 200,
  653. }}
  654. />
  655. <h4>controlled mode + given value exceed maxLength</h4>
  656. <div>
  657. <Input
  658. value={strExceed10}
  659. maxLength={10}
  660. getValueLength={getVisibleLengthFC}
  661. style={{
  662. width: 200,
  663. }}
  664. />
  665. {getVisibleLengthFC && (
  666. <Text>{`getValueLength('${strExceed10}')=${getVisibleLengthFC(strExceed10)}`}</Text>
  667. )}
  668. </div>
  669. <h4>maxCount=10</h4>
  670. <TextArea
  671. maxCount={10}
  672. getValueLength={getVisibleLengthFC}
  673. style={{
  674. width: 200,
  675. }}
  676. />
  677. <h4>maxCount=10 + maxLength=10</h4>
  678. <TextArea
  679. maxCount={10}
  680. maxLength={10}
  681. getValueLength={getVisibleLengthFC}
  682. style={{
  683. width: 200,
  684. }}
  685. />
  686. <h4>form.input + minLength=4</h4>
  687. <Form>
  688. <Form.Input
  689. field="username"
  690. minLength={4}
  691. getValueLength={getVisibleLengthFC}
  692. style={{
  693. width: 200,
  694. }}
  695. />
  696. <Button type="primary" htmlType="submit">
  697. 提交
  698. </Button>
  699. </Form>
  700. </div>
  701. );
  702. };
  703. GetValueLengthEmojiLengthProcess.story = {
  704. name: 'getValueLength emoji length process',
  705. };
  706. GetValueLengthEmojiLengthProcess.parameters = {
  707. chromatic: { disableSnapshot: false },
  708. };
  709. const ShowClearTextarea = () => {
  710. const [value, setValue] = useState('initString');
  711. const handleChange = value => {
  712. setValue(value);
  713. };
  714. return (
  715. <>
  716. <div>受控+onFocus/onBlur</div>
  717. <TextArea
  718. value={value}
  719. onChange={v => handleChange(v)}
  720. showClear
  721. onClear={e => console.log('clear', e)}
  722. onFocus={() => console.log('focus')}
  723. onBlur={() => console.log('blur')}
  724. />
  725. <br />
  726. <br />
  727. <div>disabled</div>
  728. <TextArea defaultValue="123" disabled showClear onClear={e => console.log('clear', e)} />
  729. <br />
  730. <br />
  731. <div>readonly</div>
  732. <TextArea defaultValue="123" readonly showClear onClear={e => console.log('clear', e)} />
  733. <br />
  734. <br />
  735. <div>rows=1,cols=1</div>
  736. <TextArea rows={1} cols={1} showClear onClear={e => console.log('clear', e)} />
  737. </>
  738. );
  739. };
  740. export const TextareaShowClear = () => <ShowClearTextarea />;
  741. TextareaShowClear.story = {
  742. name: 'textarea showClear',
  743. };
  744. export const ClearButton = () => {
  745. const [direction, setDirection] = React.useState('ltr');
  746. const treeData = [
  747. {
  748. label: '亚洲',
  749. value: 'Asia',
  750. key: '0',
  751. children: [
  752. {
  753. label: '中国',
  754. value: 'China',
  755. key: '0-0',
  756. children: [
  757. {
  758. label: '北京',
  759. value: 'Beijing',
  760. key: '0-0-0',
  761. },
  762. {
  763. label: '上海',
  764. value: 'Shanghai',
  765. key: '0-0-1',
  766. },
  767. ],
  768. },
  769. ],
  770. },
  771. {
  772. label: '北美洲',
  773. value: 'North America',
  774. key: '1',
  775. },
  776. ];
  777. return (
  778. <RTLWrapper
  779. onDirectionChange={dir => {
  780. console.log('dir', dir);
  781. setDirection(dir);
  782. }}
  783. >
  784. <Input defaultValue="semi" suffix={<IconClear />} />
  785. <Input defaultValue="semi" showClear suffix={<IconStar />} />
  786. <Input
  787. defaultValue="semi"
  788. showClear
  789. suffix={
  790. <Typography.Text
  791. strong
  792. type="secondary"
  793. style={direction === 'ltr' ? { marginRight: 8 } : { marginLeft: 8 }}
  794. >
  795. Suffix
  796. </Typography.Text>
  797. }
  798. showClear
  799. ></Input>
  800. <Input showClear defaultValue="semi" />
  801. <Input showClear mode="password" defaultValue="semi" />
  802. <Input mode="password" defaultValue="semi" />
  803. <br />
  804. <br />
  805. <Cascader defaultValue="semi design" showClear />
  806. <Select defaultValue="semi design" showClear />
  807. <TagInput defaultValue={['semi design']} showClear />
  808. {/* <Transfer showClear /> */}
  809. <TimePicker defaultValue={new Date()} showClear />
  810. <DatePicker defaultValue={new Date()} showClear />
  811. <Tree filterTreeNode treeData={treeData} showClear />
  812. <TreeSelect defaultValue="semi design" showClear />
  813. </RTLWrapper>
  814. );
  815. };
  816. ClearButton.story = {
  817. name: 'clear button',
  818. };
  819. export const InputFocus = () => {
  820. const ref = React.useRef();
  821. const handleClick = () => {
  822. ref.current.focus();
  823. };
  824. return (
  825. <>
  826. <Button onClick={handleClick}>focus input</Button>
  827. <Input ref={ref} onChange={() => console.log('ref', ref) } onFocus={() => console.log('focus')} />
  828. </>
  829. );
  830. };
  831. export const TextAreaAutosize = () => {
  832. return (
  833. <div style={{ width: 200 }}>
  834. <TextArea autosize />
  835. </div>
  836. )
  837. };
  838. TextAreaAutosize.storyName = "textarea autosize";