datePicker.stories.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. import React, { useState, useRef } from 'react';
  2. import {
  3. addDays,
  4. addWeeks,
  5. addMonths,
  6. isBefore,
  7. startOfMonth,
  8. endOfMonth,
  9. parseISO,
  10. startOfWeek,
  11. endOfWeek,
  12. } from 'date-fns';
  13. import { Space, ConfigProvider, InputGroup, InputNumber, Form, withField, Button } from '../../index';
  14. // stores
  15. import NeedConfirmDemo from './NeedConfirm';
  16. import RenderDate from './RenderDate';
  17. import RenderFullDate from './RenderFullDate';
  18. import DateOffset from './DateOffset';
  19. import AllTypesDemo from './AllTypes';
  20. import Callbacks from './Callbacks';
  21. import DatePicker from '../index';
  22. import ExceptionDemo from './ExceptionDemo';
  23. import ControlledDemo from './ControlledDemo';
  24. import DisabledDate from './DisabledDate';
  25. import CustomTrigger from './CustomTrigger';
  26. import OverPopover from './OverPopover';
  27. import OnChangeWithDateFirst from './OnChangeWithDateFirst';
  28. import Multiple from './Multiple';
  29. import Autofocus from './Autofocus';
  30. import CycledDatePicker from './Cycled';
  31. import AutoSwitchDate from './AutoSwitchDate';
  32. import TimepikcerOpts from './TimePickerOpts';
  33. import Density from './Density';
  34. import DatePickerSlot from './DatePickerSlot';
  35. import DatePickerTimeZone from './DatePickerTimeZone';
  36. import BetterRangePicker from './BetterRangePicker';
  37. import SyncSwitchMonth from './SyncSwitchMonth';
  38. export * from './v2';
  39. export default {
  40. title: 'DatePicker',
  41. parameters: {
  42. chromatic: { disableSnapshot: true },
  43. },
  44. }
  45. export {
  46. ControlledDemo,
  47. NeedConfirmDemo,
  48. ExceptionDemo,
  49. AllTypesDemo,
  50. Callbacks,
  51. DisabledDate,
  52. CustomTrigger,
  53. OverPopover,
  54. OnChangeWithDateFirst,
  55. RenderDate,
  56. RenderFullDate,
  57. Autofocus,
  58. DateOffset,
  59. CycledDatePicker,
  60. AutoSwitchDate,
  61. TimepikcerOpts,
  62. Density,
  63. DatePickerSlot,
  64. DatePickerTimeZone,
  65. BetterRangePicker,
  66. SyncSwitchMonth,
  67. }
  68. const demoDiv = {
  69. marginTop: '20px',
  70. marginLeft: '20px',
  71. };
  72. export const DatePickerDefault = () => (
  73. <div style={demoDiv}>
  74. <span>datePicker施工现场</span>
  75. <DatePicker
  76. insetLabel={<span>日期</span>}
  77. onChange={(str, date) => console.log(str)}
  78. onOpenChange={status => console.log(status)}
  79. placeholder="请选择日期"
  80. />
  81. <br />
  82. <span>datePicker默认显示</span>
  83. <DatePicker defaultOpen />
  84. <br />
  85. <span>defaultValue: new Date('2019-07-07')</span>
  86. <DatePicker
  87. defaultValue={new Date('2019-07-07')}
  88. onOpenChange={isOpen => console.log(isOpen)}
  89. />
  90. <br />
  91. <span>defaultValue: 2019-07-09</span>
  92. <DatePicker defaultValue="2019-07-09" />
  93. <br />
  94. <span>defaultValue: 1569888000000</span>
  95. <DatePicker
  96. defaultValue={1569888000000}
  97. onChange={(input, value) => console.log({ input, value })}
  98. />
  99. </div>
  100. );
  101. DatePickerDefault.parameters = {
  102. chromatic: {
  103. disableSnapshot: false,
  104. delay: 300
  105. }
  106. };
  107. export const DatePickerCallbacks = () => {
  108. const printArgs = (...args) => console.log(...args);
  109. return (
  110. <div style={demoDiv}>
  111. <span>datePicker施工现场</span>
  112. <DatePicker onOpenChange={printArgs} />
  113. <br />
  114. <span>defaultValue: new Date('2019-07-07')</span>
  115. <DatePicker defaultValue={new Date('2019-07-07')} />
  116. <br />
  117. <span>defaultValue: 2019-07-09</span>
  118. <DatePicker defaultValue="2019-07-09" />
  119. <br />
  120. <span>defaultValue: 1569888000000</span>
  121. <DatePicker
  122. defaultValue={1569888000000}
  123. onChange={(input, value) => console.log(input, value)}
  124. />
  125. </div>
  126. );
  127. };
  128. export const DatePickerMultiple = () => <Multiple />;
  129. export const DateRangePicker = () => (
  130. <div style={demoDiv}>
  131. <div>dateRangePicker</div>
  132. <DatePicker type="dateRange" insetLabel="结束日期" prefix="test" validateStatus="error" />
  133. <br />
  134. <div>small dateRangePicker</div>
  135. <DatePicker type="dateRange" size="small" disabled prefix="test" />
  136. <br />
  137. <div>large dateRangePicker</div>
  138. <DatePicker type="dateRange" size="large" />
  139. <br />
  140. <div>compact dateRangePicker</div>
  141. <DatePicker type="dateRange" density="compact" validateStatus="warning" />
  142. <br />
  143. <div>dateRangePicker with offset</div>
  144. <DatePicker
  145. type="dateRange"
  146. startDateOffset={date => startOfWeek(date, { weekStartsOn: 1 })}
  147. endDateOffset={date => endOfWeek(date, { weekStartsOn: 1 })}
  148. />
  149. <br />
  150. <div>defaultValue:07/01-08/02</div>
  151. <DatePicker type="dateRange" defaultValue={[new Date('2019-07-01'), new Date('2019-08-02')]} />
  152. </div>
  153. );
  154. DateRangePicker.parameters = {
  155. chromatic: { disableSnapshot: false },
  156. };
  157. const presets = [
  158. {
  159. text: 'Today',
  160. start: new Date(),
  161. end: new Date(),
  162. },
  163. {
  164. text: 'Tomorrow',
  165. start: addDays(new Date(), 1),
  166. end: addDays(new Date(), 1),
  167. },
  168. {
  169. text: 'Next Week',
  170. start: addWeeks(new Date(), 1),
  171. end: addWeeks(new Date(), 2),
  172. },
  173. {
  174. text: 'Next Month',
  175. start: startOfMonth(addMonths(new Date(), 1)),
  176. end: endOfMonth(addMonths(new Date(), 1)),
  177. },
  178. {
  179. text: 'Today',
  180. start: new Date(),
  181. end: new Date(),
  182. },
  183. {
  184. text: 'Tomorrow',
  185. start: addDays(new Date(), 1),
  186. end: addDays(new Date(), 1),
  187. },
  188. {
  189. text: 'Next Week',
  190. start: addWeeks(new Date(), 1),
  191. end: addWeeks(new Date(), 2),
  192. },
  193. {
  194. text: 'Next Month',
  195. start: startOfMonth(addMonths(new Date(), 1)),
  196. end: endOfMonth(addMonths(new Date(), 1)),
  197. },
  198. ];
  199. export const DatePickerWithPresets = () => {
  200. const onPresetClick = (item, e) => {
  201. console.log('preset click', item, e);
  202. };
  203. return (
  204. <div style={demoDiv}>
  205. <span>带快捷选择的DatePicker</span>
  206. <DatePicker
  207. type="dateRange"
  208. presets={presets}
  209. onPresetClick={onPresetClick}
  210. onChange={(...args) => console.log(...args)}
  211. />
  212. <DatePicker
  213. type="dateTime"
  214. presets={presets.map(preset => ({
  215. text: preset.text,
  216. start: preset.start,
  217. }))}
  218. onPresetClick={onPresetClick}
  219. onChange={(...args) => console.log(...args)}
  220. />
  221. <DatePicker
  222. type="dateTime"
  223. needConfirm
  224. presets={presets.map(preset => ({
  225. text: preset.text,
  226. start: preset.start,
  227. }))}
  228. onPresetClick={onPresetClick}
  229. onChange={(...args) => console.log(...args)}
  230. />
  231. <DatePicker
  232. type="month"
  233. presets={presets.map(preset => ({
  234. text: preset.text,
  235. start: preset.start,
  236. }))}
  237. onPresetClick={onPresetClick}
  238. onChange={(...args) => console.log(...args)}
  239. />
  240. </div>
  241. );
  242. };
  243. function isDisabled(dayStr) {
  244. return isBefore(new Date(dayStr), new Date());
  245. }
  246. export const DatePickerDisabledDate = () => (
  247. <div style={demoDiv}>
  248. <span>不可选日期</span>
  249. <DatePicker type="dateRange" presets={presets} disabledDate={isDisabled} />
  250. </div>
  251. );
  252. export const DateTimePicker = () => (
  253. <div style={demoDiv}>
  254. <span>dateTimePicker</span>
  255. <DatePicker
  256. defaultPickerValue={parseISO('2020-02-20 20:00:00')}
  257. type="dateTime"
  258. onChange={(...args) => console.log('onChange: ', ...args)}
  259. />
  260. </div>
  261. );
  262. export const DateTimeRangePicker = () => (
  263. <div style={demoDiv}>
  264. <span>dateTimeRangePicker</span>
  265. <DatePicker type="dateTimeRange" defaultPickerValue={parseISO('2020-02-20 20:00:00')} />
  266. <br />
  267. <span>dateTimeRangePicker</span>
  268. <DatePicker type="dateTimeRange" presets={presets} />
  269. <br />
  270. <span>dateTimeRangePicker - multiple</span>
  271. <DatePicker type="dateTimeRange" multiple />
  272. <br />
  273. </div>
  274. );
  275. export const YearPicker = () => (
  276. <>
  277. <div>
  278. <span>Year Picker</span>
  279. <DatePicker type="dateTimeRange" />
  280. </div>
  281. <div>
  282. <span>Year Picker</span>
  283. <DatePicker type="dateTimeRange" presets={presets} />
  284. </div>
  285. </>
  286. );
  287. export const MonthPicker = () => {
  288. const Demo = () => {
  289. const [controlledValue, setControlledValue] = useState('2019-09');
  290. const _setControlledValue = value => setControlledValue(value);
  291. return (
  292. <>
  293. <div>
  294. <span>MonthPicker</span>
  295. <DatePicker type="month" />
  296. </div>
  297. <div>
  298. <span>MonthPicker with presets</span>
  299. <DatePicker type="month" presets={presets} />
  300. </div>
  301. <div>
  302. <span>MonthPicker with disabledDate</span>
  303. <DatePicker
  304. type="month"
  305. disabledDate={str => {
  306. const date = new Date(str);
  307. if (str.length <= 4) {
  308. return date.getFullYear() < 2015;
  309. }
  310. return date.getMonth() + 1 < 10;
  311. }}
  312. />
  313. </div>
  314. <div>
  315. <span>MonthPicker with presets</span>
  316. <DatePicker type="month" presets={presets} />
  317. </div>
  318. <div>
  319. <span>MonthPicker with controlledValue</span>
  320. <DatePicker type="month" value={controlledValue} onChange={_setControlledValue} />
  321. </div>
  322. </>
  323. );
  324. };
  325. return <Demo />;
  326. };
  327. export const PropTypesAndDefaultProps = () => (
  328. <div>
  329. <article>
  330. <p>{JSON.stringify(Object.keys(DatePicker.propTypes))}</p>
  331. <p>{JSON.stringify(DatePicker.defaultProps)}</p>
  332. </article>
  333. </div>
  334. );
  335. export const InputReadOnly = () => <DatePicker inputReadOnly={true} />;
  336. export const DropdownClassNameDropdownStyle = () => (
  337. <div>
  338. <h4>fontSize: 16,dropdownClassName: 'my-datePicker'</h4>
  339. <DatePicker
  340. dropdownStyle={{ fontSize: 16 }}
  341. dropdownClassName="my-datePicker"
  342. onChange={(date, dateString) => console.log(dateString)}
  343. />
  344. </div>
  345. );
  346. export const CustomPlaceholder = () => (
  347. <Space wrap>
  348. <DatePicker placeholder="请选择日期" insetLabel="默认" />
  349. <DatePicker placeholder={undefined} insetLabel="undefined" />
  350. <DatePicker placeholder="" insetLabel="空字符串" />
  351. <DatePicker placeholder={false} insetLabel="false" />
  352. <DatePicker placeholder={null} insetLabel="null" />
  353. <DatePicker placeholder="" type="dateRange" insetLabel="空字符串" />
  354. </Space>
  355. );
  356. CustomPlaceholder.parameters = {
  357. chromatic: { disableSnapshot: false },
  358. };
  359. export const FixNotifyChange = () => {
  360. function Demo() {
  361. const [tz, setTz] = useState(0);
  362. const [value, setVal] = useState();
  363. const [value2, setVal2] = useState();
  364. const [value3, setVal3] = useState();
  365. const [value4, setVal4] = useState();
  366. const withLog = fn => {
  367. return val => {
  368. console.log('notifyChange', val);
  369. fn(val);
  370. };
  371. };
  372. return (
  373. <ConfigProvider timeZone={tz}>
  374. <InputGroup>
  375. <InputNumber defaultValue={0} onChange={setTz} hideButtons />
  376. <DatePicker type="dateTimeRange" value={value} onChange={withLog(setVal)} />
  377. <DatePicker
  378. type="dateTimeRange"
  379. needConfirm
  380. value={value2}
  381. onConfirm={withLog(setVal2)}
  382. />
  383. <DatePicker type="date" value={value3} onChange={withLog(setVal3)} />
  384. <DatePicker type="dateRange" value={value4} onChange={withLog(setVal4)} />
  385. </InputGroup>
  386. </ConfigProvider>
  387. );
  388. }
  389. return <Demo />;
  390. };
  391. export const SelectNotDisabledDateV126 = () => {
  392. const defaultValue = ['2021-08-06', '2021-08-15'];
  393. const disabledMonth = dateStr => {
  394. const date = new Date(dateStr);
  395. const month = date.getMonth();
  396. if (month === 7) {
  397. return true;
  398. }
  399. return false;
  400. };
  401. const disabledDate = dateStr => {
  402. const date = new Date(dateStr);
  403. const day = date.getDate();
  404. if (day > 20 && day < 25) {
  405. return true;
  406. }
  407. return false;
  408. };
  409. let props = {
  410. type: 'dateRange',
  411. motion: false,
  412. defaultValue,
  413. onChange: (...args) => console.log('changed', ...args),
  414. style: { width: 300 },
  415. };
  416. return (
  417. <>
  418. <h4>dateRange type + disabled rangeStart and select rangeEnd</h4>
  419. <DatePicker {...props} disabledDate={disabledMonth} />
  420. <h4>date type + multiple select + given disabled defaultValue</h4>
  421. <DatePicker {...props} type="date" multiple disabledDate={disabledDate} />
  422. </>
  423. );
  424. };
  425. SelectNotDisabledDateV126.story = {
  426. name: 'select not disabled date(v1.26+)',
  427. };
  428. const CustomDatePicker = props => {
  429. const { fieldRef, ...rest } = props;
  430. return <DatePicker {...rest} ref={fieldRef} />;
  431. };
  432. const CustomFieldDatePicker = withField(CustomDatePicker);
  433. export const FixOnFocus = () => {
  434. function FocusDemo() {
  435. const [open1, setOpen1] = useState(false);
  436. const [open2, setOpen2] = useState(false);
  437. const [open3, setOpen3] = useState(false);
  438. const ref = useRef();
  439. const ref2 = useRef();
  440. const presets = [
  441. {
  442. text: 'Today',
  443. start: new Date(),
  444. end: new Date(),
  445. },
  446. {
  447. text: 'Tomorrow',
  448. start: new Date(new Date().valueOf() + 1000 * 3600 * 24),
  449. end: new Date(new Date().valueOf() + 1000 * 3600 * 24),
  450. },
  451. ];
  452. return (
  453. <>
  454. <DatePicker
  455. type="date"
  456. presets={presets}
  457. open={open1}
  458. onPresetClick={() => {
  459. setOpen1(false);
  460. }}
  461. onFocus={() => {
  462. console.log('focus');
  463. setOpen1(true);
  464. }}
  465. onBlur={() => {
  466. console.log('blur');
  467. }}
  468. style={{ width: 300 }}
  469. />
  470. <br />
  471. <br />
  472. <DatePicker
  473. type="dateTimeRange"
  474. presets={presets}
  475. open={open2}
  476. onPresetClick={() => {
  477. console.log('click presets', ref);
  478. setOpen2(false);
  479. setTimeout(() => {
  480. ref.current.foundation.closePanel();
  481. console.log(ref);
  482. }, 0);
  483. }}
  484. onFocus={() => {
  485. console.log('focus');
  486. setOpen2(true);
  487. }}
  488. onBlur={() => {
  489. console.log('blur');
  490. }}
  491. style={{ width: 500 }}
  492. ref={ref}
  493. />
  494. <Form>
  495. <CustomFieldDatePicker
  496. type="dateTimeRange"
  497. field="a"
  498. label="Form.DatePicker"
  499. presets={presets}
  500. open={open3}
  501. onPresetClick={() => {
  502. console.log('click presets', ref2);
  503. setOpen3(false);
  504. setTimeout(() => {
  505. ref2.current && ref2.current.foundation.closePanel();
  506. }, 0);
  507. }}
  508. onFocus={() => {
  509. console.log('focus');
  510. setOpen3(true);
  511. }}
  512. onBlur={() => {
  513. console.log('blur');
  514. }}
  515. style={{ width: 500 }}
  516. fieldRef={ref2}
  517. />
  518. </Form>
  519. </>
  520. );
  521. }
  522. return <FocusDemo />;
  523. };
  524. FixOnFocus.story = {
  525. name: 'fix onFocus',
  526. };
  527. export const FixDisabledTimeCallback1418 = () => {
  528. function Demo() {
  529. const disabledTime2 = (date, panelType) => {
  530. console.log('disabledTime callback parameter: ', date, panelType);
  531. if (panelType === 'left') {
  532. return { disabledHours: () => [17, 18] };
  533. } else {
  534. return { disabledHours: () => [12, 13, 14, 15, 16, 17, 18] };
  535. }
  536. };
  537. return (
  538. <>
  539. <strong>fix disabledTime callback parameter bug</strong>
  540. <DatePicker
  541. type="dateTimeRange"
  542. hideDisabledOptions={false}
  543. disabledTime={disabledTime2}
  544. defaultValue={['2021-09-08', '2021-10-03']}
  545. style={{ width: 400 }}
  546. />
  547. <DatePicker
  548. type="dateTime"
  549. hideDisabledOptions={false}
  550. defaultValue={'2021-09-08'}
  551. disabledTime={disabledTime2}
  552. style={{ width: 400 }}
  553. />
  554. </>
  555. );
  556. }
  557. return <Demo />;
  558. };
  559. FixDisabledTimeCallback1418.story = {
  560. name: 'fix disabledTime callback #1418',
  561. };
  562. export const RangeSeparator = () => (
  563. <Space wrap>
  564. <div>
  565. <div>custom rangeSeparator</div>
  566. <DatePicker
  567. type="dateRange"
  568. rangeSeparator="-"
  569. defaultValue={[new Date('2019-07-01'), new Date('2019-08-02')]}
  570. />
  571. <DatePicker
  572. type="dateTimeRange"
  573. rangeSeparator="-"
  574. defaultValue={[new Date('2019-07-01'), new Date('2019-08-02')]}
  575. />
  576. </div>
  577. <div>
  578. <div>default rangeSeparator</div>
  579. <DatePicker
  580. type="dateRange"
  581. defaultValue={[new Date('2019-07-01'), new Date('2019-08-02')]}
  582. />
  583. <DatePicker
  584. type="dateTimeRange"
  585. defaultValue={[new Date('2019-07-01'), new Date('2019-08-02')]}
  586. />
  587. </div>
  588. </Space>
  589. );
  590. /**
  591. * 修复输入 '20221-12-20' 类似这种年份的日期会崩溃问题
  592. * https://github.com/DouyinFE/semi-design/issues/422
  593. *
  594. * 非法日期的来源
  595. * - 用户输入
  596. * - 受控传入
  597. * @returns
  598. */
  599. export const FixParseISOBug = () => (
  600. <div>
  601. <label>
  602. <div>选择一个合法值,然后输入一个非法年份</div>
  603. <DatePicker defaultValue={'2021-12-20'} onChange={v => console.log('onChange', v)} />
  604. </label>
  605. <label>
  606. <div>defaultValue='20221-12-20'</div>
  607. <DatePicker defaultValue={'20221-12-20'} defaultOpen={true} motion={false} onChange={v => console.log('onChange', v)} />
  608. </label>
  609. </div>
  610. );
  611. FixParseISOBug.storyName = '修复 parseISO bug';
  612. FixParseISOBug.parameters = {
  613. chromatic: { disableSnapshot: false },
  614. };
  615. export const FixNeedConfirm = () => {
  616. const defaultDate = '2021-12-27 10:37:13';
  617. const defaultDateRange = ['2021-12-27 10:37:13', '2022-01-28 10:37:13' ];
  618. const props = {
  619. needConfirm: true,
  620. onConfirm: (...args) => {
  621. console.log('Confirmed: ', ...args);
  622. },
  623. onChange: (...args) => {
  624. console.log('Changed: ', ...args);
  625. },
  626. onCancel: (...args) => {
  627. console.log('Canceled: ', ...args);
  628. },
  629. };
  630. return (
  631. <div>
  632. <div data-cy="1">
  633. <span>dateTime + needConfirm + defaultValue</span>
  634. <div>
  635. <DatePicker
  636. type="dateTime"
  637. defaultValue={defaultDate}
  638. {...props}
  639. />
  640. </div>
  641. </div>
  642. <div data-cy="2">
  643. <span>dateTime + needConfirm</span>
  644. <div>
  645. <DatePicker
  646. type="dateTime"
  647. {...props}
  648. />
  649. </div>
  650. </div>
  651. <div data-cy="3">
  652. <span>dateTimeRange + needConfirm + defaultValue</span>
  653. <div>
  654. <DatePicker
  655. type="dateTimeRange"
  656. defaultValue={defaultDateRange}
  657. {...props}
  658. />
  659. </div>
  660. </div>
  661. <div data-cy="4">
  662. <span>dateTimeRange + needConfirm</span>
  663. <div>
  664. <DatePicker
  665. type="dateTimeRange"
  666. {...props}
  667. />
  668. </div>
  669. </div>
  670. </div>
  671. )
  672. }
  673. FixNeedConfirm.storyName = '修复 needConfirm 取消后输入框显示错误';
  674. /**
  675. * fix https://github.com/DouyinFE/semi-design/issues/388
  676. */
  677. export const FixPresetsClick = () => {
  678. const presets = [
  679. {
  680. text: '清空',
  681. start: '',
  682. end: '',
  683. },
  684. {
  685. text: 'Tomorrow',
  686. start: new Date(new Date().valueOf() + 1000 * 3600 * 24),
  687. end: new Date(new Date().valueOf() + 1000 * 3600 * 24),
  688. },
  689. ];
  690. const handleChange = v => {
  691. console.log('change', v);
  692. };
  693. const handleConfirm = v => {
  694. console.log('confirm', v);
  695. }
  696. return (
  697. <div>
  698. <div>
  699. <label>
  700. <span>不设置 needConfirm</span>
  701. <DatePicker onChange={console.log} type="dateRange" presets={presets} />
  702. </label>
  703. </div>
  704. <div>
  705. <label>
  706. <span>设置 needConfirm</span>
  707. <DatePicker needConfirm onChange={handleChange} onConfirm={handleConfirm} type="dateTimeRange" presets={presets} />
  708. </label>
  709. </div>
  710. </div>
  711. );
  712. };
  713. FixPresetsClick.storyName = '修复 presets 点击后不收起问题';
  714. /**
  715. * fix https://github.com/DouyinFE/semi-design/issues/410
  716. */
  717. export const FixTriggerRenderClosePanel = () => {
  718. const [value, setValue] = useState([]);
  719. const handleChange = v => {
  720. console.log('change', v);
  721. setValue(v);
  722. };
  723. const formatValue = (dates) => {
  724. const dateStrs = dates.map(v => String(v));
  725. return dateStrs.join(' ~ ');
  726. };
  727. const showClear = Array.isArray(value) && value.length > 1;
  728. return (
  729. <Space>
  730. <DatePicker
  731. value={value}
  732. type="dateRange"
  733. onChange={handleChange}
  734. motion={false}
  735. triggerRender={({ placeholder }) => (
  736. <Button>
  737. {(value && formatValue(value)) || placeholder}
  738. </Button>
  739. )}
  740. />
  741. {showClear && (
  742. <Button onClick={() => setValue([])}>清除</Button>
  743. )}
  744. </Space>
  745. );
  746. };
  747. FixTriggerRenderClosePanel.storyName = "fix triggerRender close bug"