@douyinfe/semi-ui 2.17.0-alpha.0 → 2.17.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/_base/_story/a11y.jsx +2 -2
  2. package/avatar/__test__/avatar.test.js +3 -3
  3. package/avatar/interface.ts +1 -1
  4. package/cascader/_story/cascader.stories.js +91 -1
  5. package/cascader/index.tsx +35 -26
  6. package/collapse/__test__/collapse.test.js +22 -2
  7. package/collapse/_story/accordion.stories.js +2 -2
  8. package/collapse/item.tsx +20 -6
  9. package/collapsible/_story/collapsible.stories.js +6 -6
  10. package/configProvider/_story/RTLDirection/RTLForm.jsx +1 -1
  11. package/datePicker/__test__/datePicker.test.js +5 -5
  12. package/datePicker/_story/datePicker.stories.js +138 -22
  13. package/datePicker/datePicker.tsx +42 -7
  14. package/datePicker/monthsGrid.tsx +22 -10
  15. package/datePicker/quickControl.tsx +62 -16
  16. package/datePicker/yearAndMonth.tsx +31 -5
  17. package/dist/css/semi.css +327 -46
  18. package/dist/css/semi.min.css +1 -1
  19. package/dist/umd/semi-ui.js +45912 -45405
  20. package/dist/umd/semi-ui.js.map +1 -1
  21. package/dist/umd/semi-ui.min.js +1 -1
  22. package/dist/umd/semi-ui.min.js.map +1 -1
  23. package/empty/index.tsx +3 -3
  24. package/lib/cjs/avatar/interface.d.ts +1 -1
  25. package/lib/cjs/cascader/index.js +36 -25
  26. package/lib/cjs/collapse/item.d.ts +8 -0
  27. package/lib/cjs/collapse/item.js +19 -8
  28. package/lib/cjs/datePicker/datePicker.d.ts +3 -0
  29. package/lib/cjs/datePicker/datePicker.js +56 -9
  30. package/lib/cjs/datePicker/monthsGrid.d.ts +3 -0
  31. package/lib/cjs/datePicker/monthsGrid.js +14 -3
  32. package/lib/cjs/datePicker/quickControl.d.ts +6 -0
  33. package/lib/cjs/datePicker/quickControl.js +61 -14
  34. package/lib/cjs/datePicker/yearAndMonth.d.ts +3 -0
  35. package/lib/cjs/datePicker/yearAndMonth.js +15 -3
  36. package/lib/cjs/empty/index.js +1 -1
  37. package/lib/cjs/popover/index.d.ts +3 -0
  38. package/lib/cjs/popover/index.js +4 -2
  39. package/lib/cjs/select/index.d.ts +6 -1
  40. package/lib/cjs/select/index.js +130 -72
  41. package/lib/cjs/select/option.js +4 -2
  42. package/lib/cjs/tag/index.js +6 -4
  43. package/lib/cjs/tag/interface.d.ts +1 -0
  44. package/lib/cjs/tagInput/index.d.ts +13 -1
  45. package/lib/cjs/tagInput/index.js +217 -91
  46. package/lib/cjs/timePicker/TimePicker.js +1 -1
  47. package/lib/cjs/tooltip/index.d.ts +4 -0
  48. package/lib/cjs/tooltip/index.js +5 -3
  49. package/lib/cjs/typography/base.js +3 -15
  50. package/lib/cjs/typography/text.js +1 -11
  51. package/lib/es/avatar/interface.d.ts +1 -1
  52. package/lib/es/cascader/index.js +40 -29
  53. package/lib/es/collapse/item.d.ts +8 -0
  54. package/lib/es/collapse/item.js +19 -8
  55. package/lib/es/datePicker/datePicker.d.ts +3 -0
  56. package/lib/es/datePicker/datePicker.js +56 -9
  57. package/lib/es/datePicker/monthsGrid.d.ts +3 -0
  58. package/lib/es/datePicker/monthsGrid.js +14 -3
  59. package/lib/es/datePicker/quickControl.d.ts +6 -0
  60. package/lib/es/datePicker/quickControl.js +61 -15
  61. package/lib/es/datePicker/yearAndMonth.d.ts +3 -0
  62. package/lib/es/datePicker/yearAndMonth.js +14 -3
  63. package/lib/es/empty/index.js +1 -1
  64. package/lib/es/popover/index.d.ts +3 -0
  65. package/lib/es/popover/index.js +4 -2
  66. package/lib/es/select/index.d.ts +6 -1
  67. package/lib/es/select/index.js +129 -71
  68. package/lib/es/select/option.js +4 -2
  69. package/lib/es/tag/index.js +6 -4
  70. package/lib/es/tag/interface.d.ts +1 -0
  71. package/lib/es/tagInput/index.d.ts +13 -1
  72. package/lib/es/tagInput/index.js +217 -93
  73. package/lib/es/timePicker/TimePicker.js +1 -1
  74. package/lib/es/tooltip/index.d.ts +4 -0
  75. package/lib/es/tooltip/index.js +5 -3
  76. package/lib/es/typography/base.js +3 -15
  77. package/lib/es/typography/text.js +1 -10
  78. package/package.json +10 -8
  79. package/popover/index.tsx +4 -1
  80. package/select/__test__/select.test.js +5 -3
  81. package/select/_story/select.stories.js +1 -1
  82. package/select/_story/select.stories.tsx +2 -2
  83. package/select/index.tsx +65 -30
  84. package/select/option.tsx +2 -0
  85. package/table/_story/Perf/Render/complex.jsx +1 -1
  86. package/table/_story/Perf/Render/resizableSelection.jsx +1 -1
  87. package/tag/index.tsx +3 -2
  88. package/tag/interface.ts +1 -0
  89. package/tagInput/_story/tagInput.stories.js +20 -2
  90. package/tagInput/index.tsx +126 -26
  91. package/timePicker/TimePicker.tsx +1 -1
  92. package/tooltip/index.tsx +5 -2
  93. package/typography/_story/typography.stories.js +3 -15
  94. package/typography/base.tsx +4 -9
  95. package/typography/text.tsx +1 -9
  96. package/upload/__test__/upload.test.js +9 -9
  97. package/upload/_story/upload.stories.js +5 -5
@@ -10,7 +10,7 @@ import {
10
10
  startOfWeek,
11
11
  endOfWeek,
12
12
  } from 'date-fns';
13
- import { Space, ConfigProvider, InputGroup, InputNumber, Form, withField, Button } from '../../index';
13
+ import { Space, ConfigProvider, InputGroup, InputNumber, Form, withField, Button, RadioGroup, Radio } from '../../index';
14
14
 
15
15
  // stores
16
16
  import NeedConfirmDemo from './NeedConfirm';
@@ -36,6 +36,7 @@ import DatePickerSlot from './DatePickerSlot';
36
36
  import DatePickerTimeZone from './DatePickerTimeZone';
37
37
  import BetterRangePicker from './BetterRangePicker';
38
38
  import SyncSwitchMonth from './SyncSwitchMonth';
39
+ import { Checkbox } from '../../checkbox';
39
40
  export * from './v2';
40
41
 
41
42
  export default {
@@ -189,6 +190,11 @@ const presets = [
189
190
  start: addDays(new Date(), 1),
190
191
  end: addDays(new Date(), 1),
191
192
  },
193
+ {
194
+ text: 'Today After Tomorrow',
195
+ start: addDays(new Date(), 2),
196
+ end: addDays(new Date(), 2),
197
+ },
192
198
  {
193
199
  text: 'Next Week',
194
200
  start: addWeeks(new Date(), 1),
@@ -200,24 +206,14 @@ const presets = [
200
206
  end: endOfMonth(addMonths(new Date(), 1)),
201
207
  },
202
208
  {
203
- text: 'Today',
204
- start: new Date(),
205
- end: new Date(),
206
- },
207
- {
208
- text: 'Tomorrow',
209
- start: addDays(new Date(), 1),
210
- end: addDays(new Date(), 1),
211
- },
212
- {
213
- text: 'Next Week',
214
- start: addWeeks(new Date(), 1),
215
- end: addWeeks(new Date(), 2),
209
+ text: 'Next Bimonthly',
210
+ start: startOfMonth(addMonths(new Date(), 1)),
211
+ end: endOfMonth(addMonths(new Date(), 2)),
216
212
  },
217
213
  {
218
- text: 'Next Month',
219
- start: startOfMonth(addMonths(new Date(), 1)),
220
- end: endOfMonth(addMonths(new Date(), 1)),
214
+ text: 'Next Quarter',
215
+ start: startOfMonth(addMonths(new Date(), 3)),
216
+ end: endOfMonth(addMonths(new Date(), 3)),
221
217
  },
222
218
  ];
223
219
 
@@ -225,40 +221,160 @@ export const DatePickerWithPresets = () => {
225
221
  const onPresetClick = (item, e) => {
226
222
  console.log('preset click', item, e);
227
223
  };
224
+ const [presetPosition, setPresetPosition] = useState('right');
225
+ const [insetInput, setInsetInput] = useState(false);
226
+ const [presetArr, setPresetArr] = useState(presets);
227
+
228
+ const BottomSlot = function(props) {
229
+ const { style } = props;
230
+ return (
231
+ <div style={{ padding: '12px 20px', ...style }}>
232
+ <div strong style={{ color: 'var(--semi-color-text-2)' }}>
233
+ 定版前请阅读
234
+ </div>
235
+ <div link={{ href: 'https://semi.design/', target: '_blank' }}>发版须知</div>
236
+ </div>
237
+ );
238
+ };
228
239
  return (
229
240
  <div style={demoDiv}>
230
241
  <span>带快捷选择的DatePicker</span>
242
+ <br/>
243
+ <br/>
244
+ <RadioGroup onChange={e=>setPresetPosition(e.target.value)} value={presetPosition} aria-label="选择快捷选择面板位置" name="preset-radio-group">
245
+ <Radio value={'left'}>left</Radio>
246
+ <Radio value={'right'}>right</Radio>
247
+ <Radio value={'top'}>top</Radio>
248
+ <Radio value={'bottom'}>bottom</Radio>
249
+ </RadioGroup>
250
+ <Checkbox value={insetInput} onChange={e=>setInsetInput(e.target.checked)}>insetInput</Checkbox>
251
+ <Checkbox value={presetArr} onChange={e=>setPresetArr(e.target.checked ? [...presets, ...presets, ...presets]:presets)}>more presets</Checkbox>
252
+ <br/>
253
+ <div>type="date"</div>
231
254
  <DatePicker
232
- type="dateRange"
233
- presets={presets}
255
+ type="date"
256
+ presets={presetArr}
257
+ insetInput={insetInput}
258
+ presetPosition={presetPosition}
234
259
  onPresetClick={onPresetClick}
235
260
  onChange={(...args) => console.log(...args)}
236
261
  />
262
+ <br/>
263
+ <br/>
264
+ <div>type="dateTime"</div>
237
265
  <DatePicker
238
266
  type="dateTime"
239
- presets={presets.map(preset => ({
267
+ insetInput={insetInput}
268
+ needConfirm
269
+ bottomSlot={<BottomSlot/>}
270
+ presetPosition={presetPosition}
271
+ presets={presetArr.map(preset => ({
272
+ text: preset.text,
273
+ start: preset.start,
274
+ }))}
275
+ onPresetClick={onPresetClick}
276
+ onChange={(...args) => console.log(...args)}
277
+ />
278
+ <br/>
279
+ <br/>
280
+ <div>type="dateRange"</div>
281
+ <DatePicker
282
+ type="dateRange"
283
+ presets={presetArr}
284
+ insetInput={insetInput}
285
+ presetPosition={presetPosition}
286
+ onPresetClick={onPresetClick}
287
+ onChange={(...args) => console.log(...args)}
288
+ />
289
+ <br/>
290
+ <br/>
291
+ <div>type="dateTimeRange"</div>
292
+ <DatePicker
293
+ type="dateTimeRange"
294
+ presets={presetArr}
295
+ insetInput={insetInput}
296
+ presetPosition={presetPosition}
297
+ onPresetClick={onPresetClick}
298
+ onChange={(...args) => console.log(...args)}
299
+ />
300
+ <br/>
301
+ <br/>
302
+ <div>type="month"</div>
303
+ <DatePicker
304
+ type="month"
305
+ insetInput={insetInput}
306
+ presetPosition={presetPosition}
307
+ presets={presetArr.map(preset => ({
240
308
  text: preset.text,
241
309
  start: preset.start,
242
310
  }))}
243
311
  onPresetClick={onPresetClick}
244
312
  onChange={(...args) => console.log(...args)}
245
313
  />
314
+ <br/>
315
+ <br/>
316
+ <div>type="date" density="compact"</div>
317
+ <DatePicker
318
+ type="date"
319
+ presets={presetArr}
320
+ insetInput={insetInput}
321
+ density="compact"
322
+ presetPosition={presetPosition}
323
+ onPresetClick={onPresetClick}
324
+ onChange={(...args) => console.log(...args)}
325
+ />
326
+ <br/>
327
+ <br/>
328
+ <div>type="dateTime" density="compact"</div>
246
329
  <DatePicker
247
330
  type="dateTime"
331
+ insetInput={insetInput}
248
332
  needConfirm
249
- presets={presets.map(preset => ({
333
+ density="compact"
334
+ presetPosition={presetPosition}
335
+ presets={presetArr.map(preset => ({
250
336
  text: preset.text,
251
337
  start: preset.start,
252
338
  }))}
253
339
  onPresetClick={onPresetClick}
254
340
  onChange={(...args) => console.log(...args)}
255
341
  />
342
+ <br/>
343
+ <br/>
344
+ <div>type="dateRange" density="compact"</div>
345
+ <DatePicker
346
+ type="dateRange"
347
+ presets={presetArr}
348
+ density="compact"
349
+ insetInput={insetInput}
350
+ presetPosition={presetPosition}
351
+ onPresetClick={onPresetClick}
352
+ onChange={(...args) => console.log(...args)}
353
+ />
354
+ <br/>
355
+ <br/>
356
+ <div>type="dateTimeRange" density="compact"</div>
357
+ <DatePicker
358
+ type="dateTimeRange"
359
+ density="compact"
360
+ presets={presetArr}
361
+ insetInput={insetInput}
362
+ presetPosition={presetPosition}
363
+ onPresetClick={onPresetClick}
364
+ onChange={(...args) => console.log(...args)}
365
+ />
366
+ <br/>
367
+ <br/>
368
+ <div>type="month" density="compact"</div>
256
369
  <DatePicker
257
370
  type="month"
258
- presets={presets.map(preset => ({
371
+ insetInput={insetInput}
372
+ presetPosition={presetPosition}
373
+ presets={presetArr.map(preset => ({
259
374
  text: preset.text,
260
375
  start: preset.start,
261
376
  }))}
377
+ density="compact"
262
378
  onPresetClick={onPresetClick}
263
379
  onChange={(...args) => console.log(...args)}
264
380
  />
@@ -76,6 +76,7 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
76
76
  max: PropTypes.number, // only work when multiple is true
77
77
  placeholder: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
78
78
  presets: PropTypes.array,
79
+ presetPosition: PropTypes.oneOf(strings.PRESET_POSITION_SET),
79
80
  onChange: PropTypes.func,
80
81
  onChangeWithDateFirst: PropTypes.bool,
81
82
  weekStartsOn: PropTypes.number,
@@ -134,6 +135,7 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
134
135
  stopPropagation: true,
135
136
  motion: true,
136
137
  prefixCls: cssClasses.PREFIX,
138
+ presetPosition: 'bottom',
137
139
  // position: 'bottomLeft',
138
140
  zIndex: popoverNumbers.DEFAULT_Z_INDEX,
139
141
  type: 'date',
@@ -415,7 +417,8 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
415
417
  onPanelChange,
416
418
  timeZone,
417
419
  triggerRender,
418
- insetInput
420
+ insetInput,
421
+ presetPosition
419
422
  } = this.props;
420
423
  const { cachedSelectedValue, motionEnd, rangeInputFocus } = this.state;
421
424
 
@@ -456,21 +459,49 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
456
459
  focusRecordsRef={this.focusRecordsRef}
457
460
  triggerRender={triggerRender}
458
461
  insetInput={insetInput}
462
+ presetPosition={presetPosition}
463
+ renderQuickControls={this.renderQuickControls()}
464
+ renderDateInput={this.renderDateInput()}
459
465
  />
460
466
  );
461
467
  }
462
468
 
463
469
  renderQuickControls() {
464
- const { presets, type } = this.props;
470
+ const { presets, type, presetPosition, insetInput } = this.props;
465
471
  return (
466
472
  <QuickControl
467
473
  type={type}
468
474
  presets={presets}
475
+ insetInput={insetInput}
476
+ presetPosition={presetPosition}
469
477
  onPresetClick={(item, e) => this.foundation.handlePresetClick(item, e)}
470
478
  />
471
479
  );
472
480
  }
473
481
 
482
+ renderDateInput() {
483
+ const { insetInput, dateFnsLocale, density, type, format, rangeSeparator, defaultPickerValue } = this.props;
484
+ const { insetInputValue, value } = this.state;
485
+
486
+ const insetInputProps = {
487
+ dateFnsLocale,
488
+ format,
489
+ insetInputValue,
490
+ rangeSeparator,
491
+ type,
492
+ value: value as Date[],
493
+ handleInsetDateFocus: this.handleInsetDateFocus,
494
+ handleInsetTimeFocus: this.handleInsetTimeFocus,
495
+ onInsetInputChange: this.handleInsetInputChange,
496
+ rangeInputStartRef: this.rangeInputStartRef,
497
+ rangeInputEndRef: this.rangeInputEndRef,
498
+ density,
499
+ defaultPickerValue
500
+ };
501
+
502
+ return insetInput ? <DateInput {...insetInputProps} insetInput={true} /> : null;
503
+ }
504
+
474
505
  handleOpenPanel = () => this.foundation.openPanel();
475
506
  handleInputChange: DatePickerFoundation['handleInputChange'] = (...args) => this.foundation.handleInputChange(...args);
476
507
  handleInsetInputChange = (options: InsetInputChangeProps) => this.foundation.handleInsetInputChange(options);
@@ -626,7 +657,7 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
626
657
  };
627
658
 
628
659
  renderPanel = (locale: Locale['DatePicker'], localeCode: string, dateFnsLocale: Locale['dateFnsLocale']) => {
629
- const { dropdownClassName, dropdownStyle, density, topSlot, bottomSlot, insetInput, type, format, rangeSeparator, defaultPickerValue } = this.props;
660
+ const { dropdownClassName, dropdownStyle, density, topSlot, bottomSlot, insetInput, type, format, rangeSeparator, defaultPickerValue, presetPosition } = this.props;
630
661
  const { insetInputValue, value } = this.state;
631
662
  const wrapCls = classnames(
632
663
  cssClasses.PREFIX,
@@ -654,17 +685,18 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
654
685
  };
655
686
 
656
687
  return (
657
- <div ref={this.panelRef} className={wrapCls} style={dropdownStyle}>
688
+ <div ref={this.panelRef} className={wrapCls} style={dropdownStyle} >
658
689
  {topSlot && (
659
690
  <div className={`${cssClasses.PREFIX}-topSlot`} x-semi-prop="topSlot">
660
691
  {topSlot}
661
692
  </div>
662
693
  )}
663
- {insetInput && <DateInput {...insetInputProps} insetInput={true} />}
694
+ {presetPosition === "top" && this.renderQuickControls()}
695
+ {/* {insetInput && <DateInput {...insetInputProps} insetInput={true} />} */}
664
696
  {this.adapter.typeIsYearOrMonth()
665
697
  ? this.renderYearMonthPanel(locale, localeCode)
666
698
  : this.renderMonthGrid(locale, localeCode, dateFnsLocale)}
667
- {this.renderQuickControls()}
699
+ {presetPosition === "bottom" && this.renderQuickControls()}
668
700
  {bottomSlot && (
669
701
  <div className={`${cssClasses.PREFIX}-bottomSlot`} x-semi-prop="bottomSlot">
670
702
  {bottomSlot}
@@ -676,7 +708,7 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
676
708
  };
677
709
 
678
710
  renderYearMonthPanel = (locale: Locale['DatePicker'], localeCode: string) => {
679
- const { density } = this.props;
711
+ const { density, presetPosition } = this.props;
680
712
 
681
713
  const date = this.state.value[0];
682
714
  let year = 0;
@@ -698,6 +730,9 @@ export default class DatePicker extends BaseComponent<DatePickerProps, DatePicke
698
730
  currentYear={year}
699
731
  currentMonth={month}
700
732
  density={density}
733
+ presetPosition={presetPosition}
734
+ renderQuickControls={this.renderQuickControls()}
735
+ renderDateInput={this.renderDateInput()}
701
736
  />
702
737
  );
703
738
  };
@@ -76,6 +76,9 @@ export default class MonthsGrid extends BaseComponent<MonthsGridProps, MonthsGri
76
76
  onPanelChange: PropTypes.func,
77
77
  focusRecordsRef: PropTypes.object,
78
78
  triggerRender: PropTypes.func,
79
+ presetPosition: PropTypes.oneOf(strings.PRESET_POSITION_SET),
80
+ renderQuickControls: PropTypes.node,
81
+ renderDateInput: PropTypes.node
79
82
  };
80
83
 
81
84
  static defaultProps = {
@@ -600,9 +603,10 @@ export default class MonthsGrid extends BaseComponent<MonthsGridProps, MonthsGri
600
603
  );
601
604
  }
602
605
 
606
+
603
607
  render() {
604
608
  const { monthLeft, monthRight } = this.state;
605
- const { type, insetInput } = this.props;
609
+ const { type, insetInput, presetPosition, renderQuickControls, renderDateInput } = this.props;
606
610
  const monthGridCls = classnames({
607
611
  [`${prefixCls }-month-grid`]: true,
608
612
  });
@@ -622,15 +626,23 @@ export default class MonthsGrid extends BaseComponent<MonthsGridProps, MonthsGri
622
626
  const yearOpenType = this.getYAMOpenType();
623
627
 
624
628
  return (
625
- <div
626
- className={monthGridCls}
627
- x-type={type}
628
- x-panel-yearandmonth-open-type={yearOpenType}
629
- // FIXME:
630
- x-insetinput={insetInput ? "true" : "false"}
631
- ref={current => this.cacheRefCurrent('monthGrid', current)}
632
- >
633
- {content}
629
+ <div style={{ display: 'flex' }}>
630
+ {presetPosition === "left" && renderQuickControls}
631
+ <div>
632
+ {renderDateInput}
633
+ <div
634
+ className={monthGridCls}
635
+ x-type={type}
636
+ x-panel-yearandmonth-open-type={yearOpenType}
637
+ // FIXME:
638
+ x-insetinput={insetInput ? "true" : "false"}
639
+ x-preset-position={renderQuickControls === null ? 'null' : presetPosition}
640
+ ref={current => this.cacheRefCurrent('monthGrid', current)}
641
+ >
642
+ {content}
643
+ </div>
644
+ </div>
645
+ {presetPosition === "right" && renderQuickControls}
634
646
  </div>
635
647
  );
636
648
  }
@@ -2,52 +2,98 @@
2
2
  import React, { PureComponent } from 'react';
3
3
  import classNames from 'classnames';
4
4
  import PropTypes from 'prop-types';
5
- import { cssClasses } from '@douyinfe/semi-foundation/datePicker/constants';
5
+ import { cssClasses, strings } from '@douyinfe/semi-foundation/datePicker/constants';
6
6
  import Button from '../button/index';
7
+ import Typography from '../typography/index';
7
8
  import { noop } from '@douyinfe/semi-foundation/utils/function';
8
9
  import { PresetsType, PresetType } from '@douyinfe/semi-foundation/datePicker/foundation';
9
10
 
10
11
  const prefixCls = cssClasses.PREFIX;
12
+ const { Text } = Typography;
11
13
 
12
14
  export interface QuickControlProps {
13
15
  presets: PresetsType;
16
+ presetPosition: typeof strings.PRESET_POSITION_SET[number];
14
17
  onPresetClick: (preset: PresetType, e: React.MouseEvent) => void;
15
18
  type: string;
19
+ insetInput: boolean;
16
20
  }
17
21
 
18
22
  class QuickControl extends PureComponent<QuickControlProps> {
19
23
  static propTypes = {
20
24
  presets: PropTypes.array,
25
+ presetPosition: PropTypes.oneOf(strings.PRESET_POSITION_SET),
21
26
  onPresetClick: PropTypes.func,
22
- type: PropTypes.string
27
+ type: PropTypes.string,
28
+ insetInput: PropTypes.bool
23
29
  };
24
30
 
25
31
  static defaultProps = {
26
32
  presets: [] as PresetsType,
33
+ presetPosition: 'bottom',
27
34
  onPresetClick: noop,
28
35
  };
29
36
 
30
37
  render() {
31
- const { presets, onPresetClick, type } = this.props;
38
+ const { presets, onPresetClick, type, presetPosition, insetInput } = this.props;
39
+ const isTypeRange = type === 'dateRange' || type === 'dateTimeRange';
40
+ const isPanelTopAndBottom = presetPosition === 'top' || presetPosition === 'bottom';
41
+ const isMonth = type === 'month';
42
+ const isTopAndBottomRange = isPanelTopAndBottom && isTypeRange;
43
+ const isTopAndBottomMonth = isPanelTopAndBottom && isMonth;
44
+
32
45
  const wrapperCls = classNames(`${prefixCls}-quick-control`, {
33
- [`${prefixCls}-quick-control-${type}`]: type
46
+ [`${prefixCls}-quick-control-${type}`]: type,
47
+ [`${prefixCls}-quick-control-${presetPosition}`]: true,
48
+ });
49
+ const headerCls = classNames({
50
+ [`${prefixCls}-quick-control-header`]: true,
51
+ });
52
+ const contentWrapperCls = classNames({
53
+ [`${prefixCls}-quick-control-${presetPosition}-content-wrapper`]: true,
54
+ });
55
+ const contentCls = classNames({
56
+ [`${prefixCls}-quick-control-${presetPosition}-content`]: !isTopAndBottomRange && !isTopAndBottomMonth,
57
+ [`${prefixCls}-quick-control-${presetPosition}-range-content`]: isTopAndBottomRange,
58
+ [`${prefixCls}-quick-control-${presetPosition}-month-content`]: isTopAndBottomMonth,
34
59
  });
35
- const itemCls = classNames(`${prefixCls}-quick-control-item`);
60
+ const itemCls = classNames({
61
+ [`${prefixCls}-quick-control-${presetPosition}-content-item`]: !isTopAndBottomRange && !isTopAndBottomMonth,
62
+ [`${prefixCls}-quick-control-${presetPosition}-range-content-item`]: isTopAndBottomRange,
63
+ [`${prefixCls}-quick-control-${presetPosition}-month-content-item`]: isTopAndBottomMonth,
64
+ });
65
+ const ellipsisCls = classNames({
66
+ [`${prefixCls}-quick-control-${presetPosition}-content-item-ellipsis`]: !isTopAndBottomRange && !isTopAndBottomMonth,
67
+ [`${prefixCls}-quick-control-${presetPosition}-range-content-item-ellipsis`]: isTopAndBottomRange,
68
+ [`${prefixCls}-quick-control-${presetPosition}-month-content-item-ellipsis`]: isTopAndBottomMonth,
69
+ });
70
+
71
+
36
72
  if (!presets.length) {
37
73
  return null;
38
74
  }
39
75
  return (
40
- <div className={wrapperCls}>
41
- {presets.map((item, index) => {
42
- const _item: PresetType = typeof item === 'function' ? item() : item;
43
- return (
44
- <div className={itemCls} onClick={e => onPresetClick(_item, e)} key={index}>
45
- <Button size="small" theme="borderless" type="primary">
46
- <span>{_item.text}</span>
47
- </Button>
48
- </div>
49
- );
50
- })}
76
+ <div className={wrapperCls} x-insetinput={insetInput ? "true" : "false"}>
77
+ { !isPanelTopAndBottom && <div className={headerCls}>快捷选择</div>}
78
+ <div className={contentWrapperCls}>
79
+ <div className={contentCls}>
80
+ {presets.map((item, index) => {
81
+ const _item: PresetType = typeof item === 'function' ? item() : item;
82
+ return (
83
+ <Button size="small" type="primary" onClick={e => onPresetClick(_item, e)} key={index}>
84
+ <div className={itemCls}>
85
+ <Text
86
+ ellipsis={{ showTooltip: true }}
87
+ className={ellipsisCls}
88
+ >
89
+ {_item.text}
90
+ </Text>
91
+ </div>
92
+ </Button>
93
+ );
94
+ })}
95
+ </div>
96
+ </div>
51
97
  </div>
52
98
  );
53
99
  }
@@ -15,6 +15,8 @@ import { BASE_CLASS_PREFIX } from '@douyinfe/semi-foundation/base/constants';
15
15
  import { noop, stubFalse } from 'lodash';
16
16
  import { setYear, setMonth } from 'date-fns';
17
17
  import { Locale } from '../locale/interface';
18
+ import { strings } from '@douyinfe/semi-foundation/datePicker/constants';
19
+
18
20
 
19
21
  const prefixCls = `${BASE_CLASS_PREFIX}-datepicker`;
20
22
 
@@ -36,6 +38,9 @@ class YearAndMonth extends BaseComponent<YearAndMonthProps, YearAndMonthState> {
36
38
  noBackBtn: PropTypes.bool,
37
39
  disabledDate: PropTypes.func,
38
40
  density: PropTypes.string,
41
+ presetPosition: PropTypes.oneOf(strings.PRESET_POSITION_SET),
42
+ renderQuickControls: PropTypes.node,
43
+ renderDateInput: PropTypes.node
39
44
  };
40
45
 
41
46
  static defaultProps = {
@@ -195,7 +200,7 @@ class YearAndMonth extends BaseComponent<YearAndMonthProps, YearAndMonthState> {
195
200
  };
196
201
 
197
202
  render() {
198
- const { locale, noBackBtn, density } = this.props;
203
+ const { locale, noBackBtn, density, presetPosition, renderQuickControls, renderDateInput } = this.props;
199
204
  const prefix = `${prefixCls}-yearmonth-header`;
200
205
  // i18n
201
206
  const selectDateText = locale.selectDate;
@@ -216,10 +221,31 @@ class YearAndMonth extends BaseComponent<YearAndMonthProps, YearAndMonthState> {
216
221
  </IconButton>
217
222
  </div>
218
223
  )}
219
- <ScrollList>
220
- {this.renderColYear()}
221
- {this.renderColMonth()}
222
- </ScrollList>
224
+ {
225
+ presetPosition ? (
226
+ <div style={{ display: 'flex' }}>
227
+ {presetPosition === "left" && renderQuickControls}
228
+ <div>
229
+ {renderDateInput}
230
+ <ScrollList>
231
+ {this.renderColYear()}
232
+ {this.renderColMonth()}
233
+ </ScrollList>
234
+ </div>
235
+ {presetPosition === "right" && renderQuickControls}
236
+ </div>
237
+ ) :
238
+ <>
239
+ {renderDateInput}
240
+ <ScrollList>
241
+ {this.renderColYear()}
242
+ {this.renderColMonth()}
243
+ </ScrollList>
244
+ </>
245
+
246
+
247
+ }
248
+
223
249
  </React.Fragment>
224
250
  );
225
251
  }