amis 1.9.1-beta.28 → 1.9.1-beta.30

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. package/lib/components/AnchorNav.d.ts +9 -2
  2. package/lib/components/AnchorNav.js +32 -5
  3. package/lib/components/AnchorNav.js.map +2 -2
  4. package/lib/components/DatePicker.d.ts +41 -40
  5. package/lib/components/DatePicker.js +3 -5
  6. package/lib/components/DatePicker.js.map +2 -2
  7. package/lib/components/DateRangePicker.d.ts +45 -42
  8. package/lib/components/DateRangePicker.js +43 -11
  9. package/lib/components/DateRangePicker.js.map +2 -2
  10. package/lib/components/MonthRangePicker.d.ts +41 -40
  11. package/lib/components/MonthRangePicker.js +2 -2
  12. package/lib/components/MonthRangePicker.js.map +2 -2
  13. package/lib/components/SearchBox.d.ts +124 -42
  14. package/lib/components/SearchBox.js +181 -19
  15. package/lib/components/SearchBox.js.map +2 -2
  16. package/lib/components/Tag.d.ts +12 -10
  17. package/lib/components/Tag.js +18 -7
  18. package/lib/components/Tag.js.map +2 -2
  19. package/lib/components/calendar/Calendar.d.ts +1 -0
  20. package/lib/components/calendar/Calendar.js +8 -8
  21. package/lib/components/calendar/Calendar.js.map +2 -2
  22. package/lib/components/calendar/DaysView.d.ts +2 -1
  23. package/lib/components/calendar/DaysView.js +5 -4
  24. package/lib/components/calendar/DaysView.js.map +2 -2
  25. package/lib/index.js +1 -1
  26. package/lib/locale/de-DE.js +1 -0
  27. package/lib/locale/de-DE.js.map +2 -2
  28. package/lib/locale/en-US.js +1 -0
  29. package/lib/locale/en-US.js.map +2 -2
  30. package/lib/locale/zh-CN.js +1 -0
  31. package/lib/locale/zh-CN.js.map +2 -2
  32. package/lib/renderers/CRUD.d.ts +2 -0
  33. package/lib/renderers/CRUD.js +8 -2
  34. package/lib/renderers/CRUD.js.map +2 -2
  35. package/lib/renderers/Card.d.ts +7 -2
  36. package/lib/renderers/Card.js +11 -7
  37. package/lib/renderers/Card.js.map +2 -2
  38. package/lib/renderers/Form/InputColor.d.ts +0 -458
  39. package/lib/renderers/Form/InputColor.js +8 -9
  40. package/lib/renderers/Form/InputColor.js.map +2 -2
  41. package/lib/renderers/Form/InputExcel.d.ts +1 -0
  42. package/lib/renderers/Form/InputExcel.js +5 -0
  43. package/lib/renderers/Form/InputExcel.js.map +2 -2
  44. package/lib/renderers/Form/InputFile.d.ts +2 -2
  45. package/lib/renderers/Form/InputFile.js +6 -5
  46. package/lib/renderers/Form/InputFile.js.map +2 -2
  47. package/lib/renderers/Form/InputTable.js +16 -2
  48. package/lib/renderers/Form/InputTable.js.map +2 -2
  49. package/lib/renderers/Form/InputText.d.ts +8 -0
  50. package/lib/renderers/Form/InputText.js +8 -8
  51. package/lib/renderers/Form/InputText.js.map +2 -2
  52. package/lib/renderers/IFrame.d.ts +4 -0
  53. package/lib/renderers/IFrame.js +2 -2
  54. package/lib/renderers/IFrame.js.map +2 -2
  55. package/lib/renderers/Table/index.js +2 -2
  56. package/lib/renderers/Table/index.js.map +2 -2
  57. package/lib/renderers/Tag.js +2 -2
  58. package/lib/renderers/Tag.js.map +2 -2
  59. package/lib/renderers/Wizard.d.ts +1 -1
  60. package/lib/renderers/Wizard.js +72 -75
  61. package/lib/renderers/Wizard.js.map +2 -2
  62. package/lib/store/formItem.js +2 -1
  63. package/lib/store/formItem.js.map +2 -2
  64. package/lib/themes/ang-ie11.css +134 -21
  65. package/lib/themes/ang.css +138 -21
  66. package/lib/themes/ang.css.map +1 -1
  67. package/lib/themes/antd-ie11.css +134 -21
  68. package/lib/themes/antd.css +138 -21
  69. package/lib/themes/antd.css.map +1 -1
  70. package/lib/themes/cxd-ie11.css +134 -21
  71. package/lib/themes/cxd.css +138 -21
  72. package/lib/themes/cxd.css.map +1 -1
  73. package/lib/themes/dark-ie11.css +134 -21
  74. package/lib/themes/dark.css +138 -21
  75. package/lib/themes/dark.css.map +1 -1
  76. package/lib/themes/default-ie11.css +134 -21
  77. package/lib/themes/default.css +138 -21
  78. package/lib/themes/default.css.map +1 -1
  79. package/lib/utils/dom.js +3 -2
  80. package/lib/utils/dom.js.map +2 -2
  81. package/package.json +3 -3
  82. package/schema.json +35 -14
  83. package/scss/_properties.scss +5 -0
  84. package/scss/components/_anchor-nav.scss +1 -0
  85. package/scss/components/_calendar.scss +32 -14
  86. package/scss/components/_search-box.scss +116 -10
  87. package/scss/components/_tag.scss +12 -3
  88. package/scss/components/form/_date-range.scss +1 -1
  89. package/scss/components/form/_date.scss +28 -24
  90. package/sdk/ang-ie11.css +146 -20
  91. package/sdk/ang.css +150 -20
  92. package/sdk/antd-ie11.css +146 -20
  93. package/sdk/antd.css +150 -20
  94. package/sdk/barcode.js +51 -51
  95. package/sdk/charts.js +14 -14
  96. package/sdk/codemirror.js +7 -7
  97. package/sdk/cropperjs.js +2 -2
  98. package/sdk/cxd-ie11.css +146 -20
  99. package/sdk/cxd.css +150 -20
  100. package/sdk/dark-ie11.css +146 -20
  101. package/sdk/dark.css +150 -20
  102. package/sdk/exceljs.js +1 -1
  103. package/sdk/locale/de-DE.js +1 -0
  104. package/sdk/markdown.js +69 -69
  105. package/sdk/papaparse.js +1 -1
  106. package/sdk/renderers/Form/CityDB.js +1 -1
  107. package/sdk/rest.js +9 -23
  108. package/sdk/rich-text.js +62 -62
  109. package/sdk/sdk-ie11.css +146 -20
  110. package/sdk/sdk.css +150 -20
  111. package/sdk/sdk.js +1480 -1336
  112. package/sdk/thirds/hls.js/hls.js +1 -1
  113. package/sdk/thirds/mpegts.js/mpegts.js +1 -1
  114. package/sdk/tinymce.js +57 -57
  115. package/src/components/AnchorNav.tsx +48 -7
  116. package/src/components/DatePicker.tsx +9 -8
  117. package/src/components/DateRangePicker.tsx +62 -11
  118. package/src/components/MonthRangePicker.tsx +4 -2
  119. package/src/components/SearchBox.tsx +262 -29
  120. package/src/components/Tag.tsx +14 -3
  121. package/src/components/calendar/Calendar.tsx +30 -14
  122. package/src/components/calendar/DaysView.tsx +17 -5
  123. package/src/locale/de-DE.ts +1 -0
  124. package/src/locale/en-US.ts +1 -0
  125. package/src/locale/zh-CN.ts +1 -0
  126. package/src/renderers/CRUD.tsx +10 -0
  127. package/src/renderers/Card.tsx +24 -12
  128. package/src/renderers/Form/InputColor.tsx +14 -19
  129. package/src/renderers/Form/InputExcel.tsx +6 -0
  130. package/src/renderers/Form/InputFile.tsx +19 -18
  131. package/src/renderers/Form/InputTable.tsx +25 -4
  132. package/src/renderers/Form/InputText.tsx +20 -5
  133. package/src/renderers/IFrame.tsx +30 -1
  134. package/src/renderers/Table/index.tsx +2 -1
  135. package/src/renderers/Tag.tsx +2 -0
  136. package/src/renderers/Wizard.tsx +2 -1
  137. package/src/store/formItem.ts +4 -1
  138. package/src/utils/dom.tsx +3 -2
  139. package/sdk/color-picker.js +0 -130
@@ -1,10 +1,31 @@
1
1
  import React from 'react';
2
+ import moment from 'moment';
3
+ import _ from 'lodash';
4
+ import debounce from 'lodash/debounce';
5
+ import isInteger from 'lodash/isInteger';
2
6
  import {ThemeProps, themeable} from '../theme';
3
7
  import {Icon} from './icons';
4
8
  import {uncontrollable} from 'uncontrollable';
5
9
  import {autobind} from '../utils/helper';
6
10
  import {LocaleProps, localeable} from '../locale';
7
- import debounce from 'lodash/debounce';
11
+
12
+ export interface HistoryRecord {
13
+ /** 历史记录值 */
14
+ value: string;
15
+ /** 历史记录生成的unix时间戳 */
16
+ timestamp?: number;
17
+ }
18
+
19
+ export interface SearchHistoryOptions {
20
+ /** 是否开启历史记录 */
21
+ enable: boolean;
22
+ /** 本地存储历史记录的key */
23
+ key?: string;
24
+ /** 历史记录数量上限 */
25
+ limit?: number;
26
+ /** 历史记录下拉面板CSS类名 */
27
+ dropdownClassName?: string;
28
+ }
8
29
 
9
30
  export interface SearchBoxProps extends ThemeProps, LocaleProps {
10
31
  name?: string;
@@ -22,29 +43,46 @@ export interface SearchBoxProps extends ThemeProps, LocaleProps {
22
43
  onActiveChange?: (active: boolean) => void;
23
44
  onSearch?: (value: string) => void;
24
45
  onCancel?: () => void;
46
+ /** 历史记录配置 */
47
+ history?: SearchHistoryOptions;
25
48
  }
26
49
 
27
50
  export interface SearchBoxState {
28
51
  isFocused: boolean;
52
+ isHistoryOpened: boolean;
53
+ inputValue: string;
54
+ historyRecords: HistoryRecord[];
29
55
  }
30
56
 
57
+ const historyDefaultOptions: Required<SearchHistoryOptions> = {
58
+ enable: false,
59
+ key: 'amis:search_history',
60
+ limit: 5,
61
+ dropdownClassName: ''
62
+ };
63
+
31
64
  export class SearchBox extends React.Component<SearchBoxProps, SearchBoxState> {
32
65
  inputRef: React.RefObject<HTMLInputElement> = React.createRef();
66
+
33
67
  static defaultProps = {
34
68
  mini: true,
35
69
  enhance: false,
36
70
  clearable: false,
37
- searchImediately: true
71
+ searchImediately: true,
72
+ history: historyDefaultOptions
38
73
  };
39
74
 
40
75
  state = {
41
- isFocused: false
76
+ isHistoryOpened: false,
77
+ isFocused: false,
78
+ inputValue: this.props.value ?? '',
79
+ historyRecords: this.getHistoryRecords()
42
80
  };
43
81
 
44
82
  lazyEmitSearch = debounce(
45
83
  () => {
46
84
  const onSearch = this.props.onSearch;
47
- onSearch?.(this.props.value || '');
85
+ onSearch?.(this.state.inputValue ?? '');
48
86
  },
49
87
  250,
50
88
  {
@@ -53,6 +91,12 @@ export class SearchBox extends React.Component<SearchBoxProps, SearchBoxState> {
53
91
  }
54
92
  );
55
93
 
94
+ componentDidUpdate(prevProps: SearchBoxProps) {
95
+ if (prevProps.value !== this.props.value) {
96
+ this.setState({inputValue: this.props.value ?? ''});
97
+ }
98
+ }
99
+
56
100
  componentWillUnmount() {
57
101
  this.lazyEmitSearch.cancel();
58
102
  }
@@ -67,22 +111,35 @@ export class SearchBox extends React.Component<SearchBoxProps, SearchBoxState> {
67
111
  @autobind
68
112
  handleCancel() {
69
113
  const {onActiveChange, onCancel, onChange} = this.props;
114
+
70
115
  onActiveChange?.(false);
71
116
  onCancel?.();
72
- onChange?.('');
117
+ this.setState({inputValue: ''}, () => onChange?.(''));
73
118
  }
74
119
 
75
120
  @autobind
76
121
  handleChange(e: React.ChangeEvent<HTMLInputElement>) {
77
122
  const {searchImediately, onChange} = this.props;
78
- onChange?.(e.currentTarget.value);
79
- searchImediately && this.lazyEmitSearch();
123
+ const inputValue = e.currentTarget.value;
124
+
125
+ this.setState({inputValue}, () => {
126
+ onChange?.(inputValue);
127
+ searchImediately && this.lazyEmitSearch();
128
+ });
80
129
  }
81
130
 
82
131
  @autobind
83
132
  handleSearch() {
84
- const {onSearch, value} = this.props;
85
- onSearch?.(value || '');
133
+ const {onSearch} = this.props;
134
+ const {inputValue} = this.state;
135
+ const {enable} = this.getHistoryOptions();
136
+
137
+ if (enable) {
138
+ this.insertHistoryRecord(inputValue);
139
+ this.setState({isFocused: false, isHistoryOpened: false});
140
+ }
141
+
142
+ onSearch?.(inputValue || '');
86
143
  }
87
144
 
88
145
  @autobind
@@ -96,11 +153,117 @@ export class SearchBox extends React.Component<SearchBoxProps, SearchBoxState> {
96
153
  @autobind
97
154
  handleClear() {
98
155
  const {searchImediately, onChange} = this.props;
99
- onChange?.('');
100
- searchImediately && this.lazyEmitSearch();
156
+
157
+ this.setState({inputValue: ''}, () => {
158
+ onChange?.('');
159
+ searchImediately && this.lazyEmitSearch();
160
+ });
101
161
  }
102
162
 
103
- render() {
163
+ @autobind
164
+ handleFocus() {
165
+ const {enable} = this.getHistoryOptions();
166
+ this.setState({isFocused: true, isHistoryOpened: enable});
167
+ }
168
+
169
+ @autobind
170
+ handleBlur(e: React.FocusEvent<HTMLInputElement>) {
171
+ this.setState({isFocused: false, isHistoryOpened: false});
172
+ }
173
+
174
+ handleHistoryRecordSelect(record: HistoryRecord) {
175
+ this.setState(
176
+ {inputValue: record.value, isHistoryOpened: false, isFocused: false},
177
+ () => this.handleSearch()
178
+ );
179
+ }
180
+
181
+ /** 获取历史搜索配置 */
182
+ getHistoryOptions(): Required<SearchHistoryOptions> {
183
+ const {history} = this.props;
184
+ const options = {
185
+ enable: !!history?.enable,
186
+ key: history?.key ?? historyDefaultOptions.key,
187
+ limit:
188
+ history?.limit && isInteger(history?.limit) && history?.limit > 0
189
+ ? history?.limit
190
+ : historyDefaultOptions.limit,
191
+ dropdownClassName: history?.dropdownClassName ?? ''
192
+ };
193
+
194
+ return options;
195
+ }
196
+
197
+ /** 获取历史记录 */
198
+ getHistoryRecords() {
199
+ const {key, limit} = this.getHistoryOptions();
200
+
201
+ try {
202
+ const storageValues = localStorage.getItem(key);
203
+
204
+ return _.chain(storageValues ? JSON.parse(storageValues) : [])
205
+ .uniqBy('value')
206
+ .orderBy(['timestamp'], ['desc'])
207
+ .slice(0, limit)
208
+ .value();
209
+ } catch {}
210
+
211
+ return [];
212
+ }
213
+
214
+ /** 清空历史记录 */
215
+ clearHistoryRecords(): HistoryRecord[] {
216
+ const {key} = this.getHistoryOptions();
217
+ localStorage.removeItem(key);
218
+ this.setState({historyRecords: []});
219
+
220
+ return [];
221
+ }
222
+
223
+ /** 删除一条历史记录 */
224
+ removeHistoryRecord(record: HistoryRecord): HistoryRecord[] {
225
+ const {key} = this.getHistoryOptions();
226
+ const datasource = this.getHistoryRecords();
227
+ const recordIndex = datasource.findIndex(
228
+ item => item.value === record.value
229
+ );
230
+
231
+ if (~recordIndex) {
232
+ datasource.splice(recordIndex, 1);
233
+ localStorage.setItem(key, JSON.stringify(datasource));
234
+ this.setState({historyRecords: datasource});
235
+ }
236
+
237
+ return datasource;
238
+ }
239
+
240
+ /** 新增一条历史记录 */
241
+ insertHistoryRecord(value: string): HistoryRecord[] {
242
+ const datasource = this.getHistoryRecords();
243
+
244
+ if (!value || datasource.find(item => item.value === value)) {
245
+ return datasource;
246
+ }
247
+
248
+ try {
249
+ const {key, limit} = this.getHistoryOptions();
250
+ const newDatasource = _.chain([
251
+ ...datasource,
252
+ {value, timestamp: moment().unix()}
253
+ ])
254
+ .orderBy(['timestamp'], ['desc'])
255
+ .slice(0, limit)
256
+ .value();
257
+
258
+ localStorage.setItem(key, JSON.stringify(newDatasource));
259
+ this.setState({historyRecords: newDatasource});
260
+ return newDatasource;
261
+ } catch {}
262
+
263
+ return datasource;
264
+ }
265
+
266
+ renderInput(isHistoryMode?: boolean) {
104
267
  const {
105
268
  classnames: cx,
106
269
  active,
@@ -111,43 +274,41 @@ export class SearchBox extends React.Component<SearchBoxProps, SearchBoxState> {
111
274
  mini,
112
275
  enhance,
113
276
  clearable,
114
- value,
115
277
  translate: __
116
278
  } = this.props;
117
-
118
- const isFocused = this.state.isFocused;
279
+ const {isFocused, inputValue} = this.state;
280
+ const {enable} = this.getHistoryOptions();
119
281
 
120
282
  return (
121
283
  <div
122
284
  className={cx(
123
285
  'SearchBox',
124
286
  enhance && 'SearchBox--enhance',
125
- className,
287
+ !!isHistoryMode ? '' : className,
126
288
  disabled ? 'is-disabled' : '',
127
289
  isFocused ? 'is-focused' : '',
128
290
  !mini || active ? 'is-active' : '',
291
+ {'is-history': enable}
129
292
  )}
130
293
  >
131
294
  <input
132
295
  name={name}
133
- disabled={disabled}
296
+ ref={this.inputRef}
297
+ onFocus={this.handleFocus}
298
+ onBlur={this.handleBlur}
134
299
  onChange={this.handleChange}
135
- value={value || ''}
300
+ onKeyDown={this.handleKeyDown}
301
+ value={inputValue ?? ''}
302
+ disabled={disabled}
136
303
  placeholder={__(placeholder || 'placeholder.enter')}
137
- ref={this.inputRef}
138
304
  autoComplete="off"
139
- onFocus={() => this.setState({ isFocused: true })}
140
- onBlur={() => this.setState({ isFocused: false })}
141
- onKeyDown={this.handleKeyDown}
142
305
  />
143
306
 
144
- {
145
- !mini && clearable && value && !disabled ? (
146
- <div className={cx('SearchBox-clearable')} onClick={this.handleClear}>
147
- <Icon icon="input-clear" className="icon"/>
148
- </div>
149
- ) : null
150
- }
307
+ {!mini && clearable && inputValue && !disabled ? (
308
+ <div className={cx('SearchBox-clearable')} onClick={this.handleClear}>
309
+ <Icon icon="input-clear" className="icon" />
310
+ </div>
311
+ ) : null}
151
312
 
152
313
  {!mini ? (
153
314
  <a className={cx('SearchBox-searchBtn')} onClick={this.handleSearch}>
@@ -165,6 +326,78 @@ export class SearchBox extends React.Component<SearchBoxProps, SearchBoxState> {
165
326
  </div>
166
327
  );
167
328
  }
329
+
330
+ renderTag(item: HistoryRecord, index: number) {
331
+ const {classnames: cx} = this.props;
332
+
333
+ return (
334
+ <span className={cx('Tag', 'SearchBox-history-tag')} key={index}>
335
+ <span
336
+ className={cx('SearchBox-history-tag-text')}
337
+ onMouseDown={(e: React.MouseEvent<any>) => {
338
+ e.preventDefault();
339
+ this.handleHistoryRecordSelect(item);
340
+ }}
341
+ >
342
+ {item.value}
343
+ </span>
344
+ <span
345
+ className={cx(`SearchBox-history-tag-close`)}
346
+ onMouseDown={(e: React.MouseEvent<any>) => {
347
+ e.preventDefault();
348
+ this.removeHistoryRecord(item);
349
+ }}
350
+ >
351
+ <Icon icon="close" className="icon" />
352
+ </span>
353
+ </span>
354
+ );
355
+ }
356
+
357
+ renderHitoryMode() {
358
+ const {classnames: cx, translate: __, className} = this.props;
359
+ const {isHistoryOpened, inputValue, historyRecords} = this.state;
360
+ const {dropdownClassName} = this.getHistoryOptions();
361
+ const showDropdown =
362
+ isHistoryOpened && !inputValue && historyRecords.length > 0;
363
+
364
+ return (
365
+ <div
366
+ id="searchbox-history"
367
+ className={cx('SearchBox-history', className)}
368
+ >
369
+ {this.renderInput(true)}
370
+
371
+ <div
372
+ className={cx('SearchBox-history-dropdown', dropdownClassName, {
373
+ 'is-active': showDropdown
374
+ })}
375
+ >
376
+ <header>
377
+ <h4>{__('searchHistory')}</h4>
378
+ <a
379
+ onMouseDown={(e: React.MouseEvent<any>) => {
380
+ e.preventDefault();
381
+ this.clearHistoryRecords();
382
+ }}
383
+ >
384
+ {__('clear')}
385
+ </a>
386
+ </header>
387
+
388
+ <div className={cx('SearchBox-history-content')}>
389
+ {historyRecords.map((item, index) => this.renderTag(item, index))}
390
+ </div>
391
+ </div>
392
+ </div>
393
+ );
394
+ }
395
+
396
+ render() {
397
+ const {enable} = this.getHistoryOptions();
398
+
399
+ return enable ? this.renderHitoryMode() : this.renderInput();
400
+ }
168
401
  }
169
402
 
170
403
  export default themeable(
@@ -18,6 +18,7 @@ export interface TagProps extends ThemeProps {
18
18
  disabled?: boolean;
19
19
  closeIcon?: string | React.ReactNode;
20
20
  onClose?: (e: React.MouseEvent) => void;
21
+ onClick?: (e: React.MouseEvent) => void;
21
22
  }
22
23
 
23
24
  export interface CheckableTagProps extends TagProps {
@@ -82,6 +83,12 @@ export class Tag extends React.Component<TagProps> {
82
83
  onClose?.(e);
83
84
  }
84
85
 
86
+ @autobind
87
+ handleClick(e: React.MouseEvent<HTMLElement>) {
88
+ const {onClick} = this.props;
89
+ onClick?.(e);
90
+ }
91
+
85
92
  render() {
86
93
  const {
87
94
  children,
@@ -92,7 +99,8 @@ export class Tag extends React.Component<TagProps> {
92
99
  color,
93
100
  icon,
94
101
  style,
95
- label
102
+ label,
103
+ closable
96
104
  } = this.props;
97
105
 
98
106
  const isPresetColor =
@@ -131,9 +139,12 @@ export class Tag extends React.Component<TagProps> {
131
139
  [`Tag--disabled`]: disabled
132
140
  })}
133
141
  style={tagStyle}
142
+ onClick={this.handleClick}
134
143
  >
135
- {prevIcon}
136
- {label || children}
144
+ <span className={cx('Tag-text')}>
145
+ {prevIcon}
146
+ {label || children}
147
+ </span>
137
148
  {this.renderCloseIcon()}
138
149
  </span>
139
150
  );
@@ -65,7 +65,12 @@ interface BaseDatePickerProps {
65
65
  currentDate: moment.Moment,
66
66
  selectedDate: moment.Moment
67
67
  ) => JSX.Element;
68
- renderMonth?: (props: any, month: number, year: number, date: any) => JSX.Element;
68
+ renderMonth?: (
69
+ props: any,
70
+ month: number,
71
+ year: number,
72
+ date: any
73
+ ) => JSX.Element;
69
74
  renderQuarter?: (
70
75
  props: any,
71
76
  quartar: number,
@@ -92,6 +97,7 @@ interface BaseDatePickerProps {
92
97
  displayTimeZone?: string;
93
98
  timeConstraints?: any;
94
99
  timeRangeHeader?: string;
100
+ timeRangeContext?: 'start' | 'end';
95
101
  }
96
102
 
97
103
  interface BaseDatePickerState {
@@ -558,7 +564,7 @@ class BaseDatePicker extends React.Component<
558
564
  }
559
565
  }
560
566
 
561
- that.props.onChange(date);
567
+ that.props.onChange(date, this.props.timeRangeContext);
562
568
  };
563
569
 
564
570
  getDateBoundary = (currentDate: moment.Moment) => {
@@ -640,7 +646,13 @@ class BaseDatePicker extends React.Component<
640
646
  };
641
647
 
642
648
  render() {
643
- const {viewMode, timeFormat, dateFormat, timeRangeHeader} = this.props;
649
+ const {
650
+ viewMode,
651
+ timeFormat,
652
+ dateFormat,
653
+ timeRangeHeader,
654
+ timeRangeContext
655
+ } = this.props;
644
656
  const Component = CustomCalendarContainer as any;
645
657
  const viewProps = this.getComponentProps();
646
658
 
@@ -649,11 +661,9 @@ class BaseDatePicker extends React.Component<
649
661
  'quarters',
650
662
  this.props.renderQuarter
651
663
  ];
652
- }
653
- else if (viewMode === 'years') {
664
+ } else if (viewMode === 'years') {
654
665
  viewProps.updateOn = 'years';
655
- }
656
- else if (viewMode === 'months') {
666
+ } else if (viewMode === 'months') {
657
667
  viewProps.updateOn = 'months';
658
668
  }
659
669
 
@@ -668,28 +678,34 @@ class BaseDatePicker extends React.Component<
668
678
  className={cx(
669
679
  'rdt rdtStatic rdtOpen',
670
680
  this.props.className,
671
- (timeFormat && !dateFormat || typeof dateFormat !== 'string')
681
+ (timeFormat && !dateFormat) || typeof dateFormat !== 'string'
672
682
  ? 'rdtTimeWithoutD'
673
- : (timeFormat && timeFormat.toLowerCase().indexOf('s') > 0)
683
+ : timeFormat && timeFormat.toLowerCase().indexOf('s') > 0
674
684
  ? 'rdtTimeWithS'
675
685
  : timeFormat
676
686
  ? 'rdtTime'
677
687
  : ''
678
688
  )}
679
689
  >
680
- <div key="dt"
690
+ <div
691
+ key="dt"
681
692
  className={cx(
682
693
  'rdtPicker',
683
- (timeFormat && !dateFormat)
694
+ timeFormat && !dateFormat
684
695
  ? 'rdtPickerTimeWithoutD'
685
- : (timeFormat && dateFormat)
696
+ : timeFormat && dateFormat
686
697
  ? 'rdtPickerTime'
687
- : (dateFormat && !timeFormat)
698
+ : dateFormat && !timeFormat
688
699
  ? 'rdtPickerDate'
689
700
  : ''
690
701
  )}
691
702
  >
692
- <Component view={this.state.currentView} viewProps={viewProps} timeRangeHeader={timeRangeHeader}/>
703
+ <Component
704
+ view={this.state.currentView}
705
+ viewProps={viewProps}
706
+ timeRangeHeader={timeRangeHeader}
707
+ timeRangeContext={timeRangeContext}
708
+ />
693
709
  </div>
694
710
  </div>
695
711
  );
@@ -55,7 +55,11 @@ interface CustomDaysViewProps extends LocaleProps {
55
55
  selected?: moment.Moment
56
56
  ) => boolean;
57
57
  showView: (view: string) => () => void;
58
- updateSelectedDate: (event: React.MouseEvent<any>, close?: boolean) => void;
58
+ updateSelectedDate: (
59
+ event: React.MouseEvent<any>,
60
+ close?: boolean,
61
+ timeRangeContext?: 'start' | 'end'
62
+ ) => void;
59
63
  handleClickOutside: () => void;
60
64
  classnames: ClassNamesFn;
61
65
  schedules?: Array<{
@@ -70,6 +74,7 @@ interface CustomDaysViewProps extends LocaleProps {
70
74
  getColumns: (types: DateType[], dateBoundary: void) => any;
71
75
  getDateBoundary: (currentDate: moment.Moment) => any;
72
76
  timeConstraints?: any;
77
+ timeRangeContext?: 'start' | 'end';
73
78
  }
74
79
 
75
80
  export class CustomDaysView extends React.Component<CustomDaysViewProps> {
@@ -494,7 +499,11 @@ export class CustomDaysView extends React.Component<CustomDaysViewProps> {
494
499
  );
495
500
  }
496
501
  }
497
- return <td {...props}><span>{currentDate.date()}</span></td>;
502
+ return (
503
+ <td {...props}>
504
+ <span>{currentDate.date()}</span>
505
+ </td>
506
+ );
498
507
  };
499
508
 
500
509
  /** 时间选择器数据源 */
@@ -523,8 +532,6 @@ export class CustomDaysView extends React.Component<CustomDaysViewProps> {
523
532
  const inputs: Array<React.ReactNode> = [];
524
533
  const timeConstraints = this.timeConstraints;
525
534
 
526
- inputs.push(this.showTime());
527
-
528
535
  timeFormat.split(':').forEach((format, i) => {
529
536
  const type = /h/i.test(format)
530
537
  ? 'hours'
@@ -623,7 +630,12 @@ export class CustomDaysView extends React.Component<CustomDaysViewProps> {
623
630
  }
624
631
  });
625
632
  inputs.length && inputs.pop();
626
- return <div>{inputs}</div>;
633
+ return (
634
+ <div className={cx('CalendarTimesWrapper')}>
635
+ {this.showTime()}
636
+ <div className={cx('CalendarInputsWrapper')}>{inputs}</div>
637
+ </div>
638
+ );
627
639
  };
628
640
 
629
641
  renderFooter = () => {
@@ -184,6 +184,7 @@ register('de-DE', {
184
184
  'saveFailed': 'Fehler beim Speichern',
185
185
  'saveSuccess': 'Erfolgreich gespeichert',
186
186
  'search': 'Suchen',
187
+ 'searchHistory': 'Suchverlauf',
187
188
  'searchResult': 'Suchergebnis',
188
189
  'Checkboxes.selectAll': 'Alle auswählen/abwählen',
189
190
  'Select.checkAll': 'Alle markieren',
@@ -186,6 +186,7 @@ register('en-US', {
186
186
  'saveFailed': 'Save failed',
187
187
  'saveSuccess': 'Saved successfully',
188
188
  'search': 'Search',
189
+ 'searchHistory': 'Search History',
189
190
  'searchResult': 'Search result',
190
191
  'Checkboxes.selectAll': 'Select/Deselect All',
191
192
  'Select.checkAll': 'Check all',
@@ -193,6 +193,7 @@ register('zh-CN', {
193
193
  'saveFailed': '保存失败',
194
194
  'saveSuccess': '保存成功',
195
195
  'search': '搜索',
196
+ 'searchHistory': '搜索历史',
196
197
  'searchResult': '搜索结果',
197
198
  'stop': '停止',
198
199
  'Checkboxes.selectAll': '全选/不选',
@@ -410,6 +410,9 @@ export default class CRUD extends React.Component<CRUDProps, any> {
410
410
 
411
411
  timer: ReturnType<typeof setTimeout>;
412
412
  mounted: boolean;
413
+
414
+ target: React.RefObject<HTMLDivElement> = React.createRef();
415
+
413
416
  constructor(props: CRUDProps) {
414
417
  super(props);
415
418
 
@@ -434,6 +437,7 @@ export default class CRUD extends React.Component<CRUDProps, any> {
434
437
  this.renderHeaderToolbar = this.renderHeaderToolbar.bind(this);
435
438
  this.renderFooterToolbar = this.renderFooterToolbar.bind(this);
436
439
  this.clearSelection = this.clearSelection.bind(this);
440
+ this.getTarget = this.getTarget.bind(this);
437
441
 
438
442
  const {
439
443
  location,
@@ -1755,6 +1759,7 @@ export default class CRUD extends React.Component<CRUDProps, any> {
1755
1759
  classPrefix={ns}
1756
1760
  searchable={false}
1757
1761
  placeholder={__('Select.placeholder')}
1762
+ popOverContainer={this.getTarget}
1758
1763
  options={perPages}
1759
1764
  value={store.perPage + ''}
1760
1765
  onChange={(value: any) => this.handleChangePage(1, value.value)}
@@ -1764,6 +1769,10 @@ export default class CRUD extends React.Component<CRUDProps, any> {
1764
1769
  );
1765
1770
  }
1766
1771
 
1772
+ getTarget() {
1773
+ return this.target.current?.ownerDocument.body;
1774
+ }
1775
+
1767
1776
  renderLoadMore() {
1768
1777
  const {store, classPrefix: ns, classnames: cx, translate: __} = this.props;
1769
1778
  const {page, lastPage} = store;
@@ -2075,6 +2084,7 @@ export default class CRUD extends React.Component<CRUDProps, any> {
2075
2084
  className={cx('Crud', className, {
2076
2085
  'is-loading': store.loading
2077
2086
  })}
2087
+ ref={this.target}
2078
2088
  >
2079
2089
  {filter && (!store.filterTogggable || store.filterVisible)
2080
2090
  ? render(