@coreui/react-pro 4.2.0-beta.0 → 4.2.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 (35) hide show
  1. package/README.md +1 -1
  2. package/dist/components/calendar/CCalendar.d.ts +27 -10
  3. package/dist/components/calendar/CCalendar.utils.d.ts +2 -1
  4. package/dist/components/daterangepicker/CDateRangePicker.d.ts +26 -11
  5. package/dist/components/picker/CPicker.d.ts +50 -9
  6. package/dist/components/timepicker/CTimePicker.d.ts +9 -13
  7. package/dist/components/timepicker/CTimePicker.utils.d.ts +13 -0
  8. package/dist/index.es.js +243 -206
  9. package/dist/index.es.js.map +1 -1
  10. package/dist/index.js +243 -206
  11. package/dist/index.js.map +1 -1
  12. package/dist/utils/calendar.d.ts +21 -0
  13. package/dist/utils/time.d.ts +17 -0
  14. package/package.json +3 -2
  15. package/src/components/accordion/__tests__/__snapshots__/CAccordionButton.spec.tsx.snap +2 -0
  16. package/src/components/accordion/__tests__/__snapshots__/CAccordionHeader.spec.tsx.snap +2 -0
  17. package/src/components/calendar/CCalendar.tsx +104 -58
  18. package/src/components/calendar/__tests__/CCalendar.spec.tsx +9 -0
  19. package/src/components/calendar/__tests__/__snapshots__/CCalendar.spec.tsx.snap +573 -0
  20. package/src/components/datepicker/CDatePicker.tsx +1 -0
  21. package/src/components/datepicker/__tests__/CDatePicker.spec.tsx +9 -0
  22. package/src/components/datepicker/__tests__/__snapshots__/CDatePicker.spec.tsx.snap +617 -0
  23. package/src/components/daterangepicker/CDateRangePicker.tsx +152 -91
  24. package/src/components/daterangepicker/__tests__/CDateRangePicker.spec.tsx +9 -0
  25. package/src/components/daterangepicker/__tests__/__snapshots__/CDateRangePicker.spec.tsx.snap +1201 -0
  26. package/src/components/dropdown/CDropdownMenu.tsx +5 -3
  27. package/src/components/picker/CPicker.tsx +99 -34
  28. package/src/components/picker/__tests__/CPicker.spec.tsx +9 -0
  29. package/src/components/picker/__tests__/__snapshots__/CPicker.spec.tsx.snap +23 -0
  30. package/src/components/timepicker/CTimePicker.tsx +66 -87
  31. package/src/components/timepicker/CTimePickerRollCol.tsx +7 -1
  32. package/src/components/timepicker/__tests__/CTimePicker.spec.tsx +9 -0
  33. package/src/{components/calendar/CCalendar.utils.ts → utils/calendar.ts} +11 -1
  34. package/src/utils/time.ts +58 -0
  35. package/src/components/timepicker/CTimePicker.utils.ts +0 -27
@@ -3,14 +3,17 @@ import PropTypes from 'prop-types'
3
3
  import classNames from 'classnames'
4
4
  import { isMobile } from 'react-device-detect'
5
5
 
6
- import { CCalendar, CCalendarProps } from '../calendar/CCalendar'
7
- import { CPicker, CPickerProps } from './../picker/CPicker'
8
- import { CTimePicker } from './../timepicker/CTimePicker'
9
- import { convertToLocalDate } from '../calendar/CCalendar.utils'
10
6
  import { CButton } from '../button/CButton'
7
+ import { CCalendar, CCalendarProps } from '../calendar/CCalendar'
11
8
  import { CFormInput } from '../form/CFormInput'
12
9
  import { CInputGroup } from '../form/CInputGroup'
13
10
  import { CInputGroupText } from '../form/CInputGroupText'
11
+ import { CPicker, CPickerProps } from '../picker/CPicker'
12
+ import { CTimePicker } from '../timepicker/CTimePicker'
13
+
14
+ import { isValidDate } from '../../utils/calendar'
15
+
16
+ import { Colors } from '../Types'
14
17
 
15
18
  export interface CDateRangePickerProps
16
19
  extends Omit<CPickerProps, 'autoClose' | 'component' | 'dark' | 'placeholder' | 'variant'>,
@@ -20,21 +23,17 @@ export interface CDateRangePickerProps
20
23
  */
21
24
  calendars?: number
22
25
  /**
23
- * Enables selection cleaner element.
24
- */
25
- cleaner?: boolean
26
- /**
27
- * Cleaner icon.
26
+ * A string of all className you want applied to the component.
28
27
  */
29
- cleanerIcon?: ReactNode | boolean
28
+ className?: string
30
29
  /**
31
- * Default input icon.
30
+ * Toggle visibility or set the content of the cleaner button.
32
31
  */
33
- defaultIcon?: ReactNode | boolean
32
+ cleaner?: boolean
34
33
  /**
35
- * Default icon between date input fields.
34
+ * Toggle visibility or set the content of the input indicator.
36
35
  */
37
- infixIcon?: ReactNode | boolean
36
+ indicator?: ReactNode | boolean
38
37
  /**
39
38
  * Toggle the readonly state for the component.
40
39
  */
@@ -51,6 +50,24 @@ export interface CDateRangePickerProps
51
50
  * Predefined date ranges the user can select from.
52
51
  */
53
52
  ranges?: object
53
+ /**
54
+ * Sets the color context of the cancel button to one of CoreUI’s themed colors.
55
+ *
56
+ * @type 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | string
57
+ */
58
+ rangesButtonsColor?: Colors
59
+ /**
60
+ * Size the ranges button small or large.
61
+ */
62
+ rangesButtonsSize?: 'sm' | 'lg'
63
+ /**
64
+ * Set the ranges button variant to an outlined button or a ghost button.
65
+ */
66
+ rangesButtonsVariant?: 'outline' | 'ghost'
67
+ /**
68
+ * Default icon or character character that separates two dates.
69
+ */
70
+ separator?: ReactNode | boolean
54
71
  /**
55
72
  * Size the component small or large.
56
73
  */
@@ -67,17 +84,18 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
67
84
  calendars = 2,
68
85
  className,
69
86
  cleaner = true,
70
- cleanerIcon,
71
87
  calendarDate,
88
+ indicator = true,
72
89
  disabled,
73
90
  disabledDates,
74
91
  endDate,
75
- defaultIcon,
76
- infixIcon,
92
+ firstDayOfWeek,
93
+ footer,
77
94
  inputReadOnly,
78
- locale = typeof navigator === 'undefined' ? 'en-US' : navigator.language,
95
+ locale = 'default',
79
96
  maxDate,
80
97
  minDate,
98
+ navigation,
81
99
  onEndDateChange,
82
100
  onHide,
83
101
  onStartDateChange,
@@ -85,6 +103,10 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
85
103
  placeholder = ['Start date', 'End date'],
86
104
  range = true,
87
105
  ranges,
106
+ rangesButtonsColor = 'secondary',
107
+ rangesButtonsSize,
108
+ rangesButtonsVariant = 'ghost',
109
+ separator = true,
88
110
  size,
89
111
  startDate,
90
112
  timepicker,
@@ -94,17 +116,25 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
94
116
  },
95
117
  ref,
96
118
  ) => {
119
+ const [_visible, setVisible] = useState(visible)
120
+
97
121
  const inputStartRef = useRef<HTMLInputElement>(null)
98
122
  const inputEndRef = useRef<HTMLInputElement>(null)
99
- const [_visible, setVisible] = useState(visible)
100
- const [_startDate, setStartDate] = useState<Date | null>(startDate ? new Date(startDate) : null)
101
- const [_endDate, setEndDate] = useState<Date | null>(endDate ? new Date(endDate) : null)
102
- const [inputHoverValue, setInputHoverValue] = useState<Date | null>(null)
103
- const [inputToHoverValue, setInputToHoverValue] = useState<Date | null>(null)
104
- const [selectEndDate, setSelectEndDate] = useState(false)
123
+ const [inputStartHoverValue, setInputStartHoverValue] = useState<Date | null>(null)
124
+ const [inputEndHoverValue, setInputEndHoverValue] = useState<Date | null>(null)
125
+
105
126
  const [_calendarDate, setCalendarDate] = useState<Date>(
106
127
  calendarDate ? new Date(calendarDate) : new Date(),
107
128
  )
129
+ const [_startDate, setStartDate] = useState<Date | null>(startDate ? new Date(startDate) : null)
130
+ const [_endDate, setEndDate] = useState<Date | null>(endDate ? new Date(endDate) : null)
131
+ const [initialStartDate, setInitialStartDate] = useState<Date | null>(
132
+ startDate ? new Date(startDate) : null,
133
+ )
134
+ const [initialEndDate, setInitialEndDate] = useState<Date | null>(
135
+ endDate ? new Date(endDate) : null,
136
+ )
137
+ const [selectEndDate, setSelectEndDate] = useState(false)
108
138
 
109
139
  useEffect(() => {
110
140
  startDate && setCalendarDate(new Date(startDate))
@@ -115,41 +145,43 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
115
145
  }, [endDate])
116
146
 
117
147
  useEffect(() => {
118
- _visible && onShow && onShow()
119
- !_visible && onHide && onHide()
120
- }, [_visible])
148
+ if (inputStartHoverValue) {
149
+ setInputValue(inputStartRef.current, inputStartHoverValue, timepicker)
150
+ return
151
+ }
152
+
153
+ setInputValue(inputStartRef.current, _startDate, timepicker)
154
+ }, [inputStartHoverValue, _startDate])
121
155
 
122
156
  useEffect(() => {
123
- if (inputStartRef.current) {
124
- if (inputHoverValue) {
125
- inputStartRef.current.value = convertToLocalDate(inputHoverValue, locale)
126
- return
127
- }
128
- if (_startDate) {
129
- inputStartRef.current.value = timepicker
130
- ? _startDate.toLocaleString(locale)
131
- : _startDate.toLocaleDateString(locale)
132
- return
133
- }
134
- inputStartRef.current.value = ''
157
+ if (inputEndHoverValue) {
158
+ setInputValue(inputEndRef.current, inputEndHoverValue, timepicker)
159
+ return
135
160
  }
136
- }, [inputHoverValue, _startDate])
137
161
 
138
- useEffect(() => {
139
- if (inputEndRef.current) {
140
- if (inputToHoverValue) {
141
- inputEndRef.current.value = convertToLocalDate(inputToHoverValue, locale)
142
- return
143
- }
144
- if (_endDate) {
145
- inputEndRef.current.value = timepicker
146
- ? _endDate.toLocaleString(locale)
147
- : _endDate.toLocaleDateString(locale)
148
- return
149
- }
150
- inputEndRef.current.value = ''
162
+ setInputValue(inputEndRef.current, _endDate, timepicker)
163
+ }, [inputEndHoverValue, _endDate])
164
+
165
+ const setInputValue = (
166
+ el: HTMLInputElement | null,
167
+ date: Date | null,
168
+ timepicker?: boolean,
169
+ ) => {
170
+ if (!el) {
171
+ return
151
172
  }
152
- }, [inputToHoverValue, _endDate])
173
+
174
+ if (date) {
175
+ el.value = timepicker ? date.toLocaleString(locale) : date.toLocaleDateString(locale)
176
+ return
177
+ }
178
+
179
+ el.value = ''
180
+ }
181
+
182
+ const handleCalendarCellHover = (date: Date | null) => {
183
+ selectEndDate ? setInputEndHoverValue(date) : setInputStartHoverValue(date)
184
+ }
153
185
 
154
186
  const handleCalendarDateChange = (date: Date, difference?: number) => {
155
187
  difference
@@ -161,30 +193,26 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
161
193
  setStartDate(date)
162
194
  range && setSelectEndDate(true)
163
195
  onStartDateChange && onStartDateChange(date)
164
- setInputHoverValue(null)
196
+ setInputStartHoverValue(null)
165
197
  }
166
198
 
167
199
  const handleEndDateChange = (date: Date | null) => {
168
200
  setEndDate(date)
169
201
  setSelectEndDate(false)
170
202
  onEndDateChange && onEndDateChange(date)
171
- setInputToHoverValue(null)
203
+ setInputEndHoverValue(null)
172
204
 
173
- if (timepicker !== true) {
205
+ if (timepicker !== true && footer !== true) {
174
206
  _startDate !== null && setVisible(false)
175
207
  }
176
208
  }
177
209
 
178
- const handleCalendarCellHover = (date: Date | null) => {
179
- selectEndDate ? setInputToHoverValue(date) : setInputHoverValue(date)
180
- }
181
-
182
210
  const handleClear = (event: React.MouseEvent<HTMLElement>) => {
183
211
  event.stopPropagation()
184
- setStartDate(null)
185
- setEndDate(null)
186
- setInputHoverValue(null)
187
- setInputToHoverValue(null)
212
+ setStartDate(initialStartDate)
213
+ setEndDate(initialEndDate)
214
+ setInputStartHoverValue(null)
215
+ setInputEndHoverValue(null)
188
216
  }
189
217
 
190
218
  const _className = classNames('date-picker', className)
@@ -193,43 +221,55 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
193
221
  <CInputGroup className="picker-input-group" size={size}>
194
222
  <CFormInput
195
223
  className={classNames({
196
- hover: inputHoverValue,
224
+ hover: inputStartHoverValue,
197
225
  })}
198
226
  disabled={disabled}
199
227
  placeholder={Array.isArray(placeholder) ? placeholder[0] : placeholder}
200
228
  readOnly={inputReadOnly}
229
+ onChange={(event) => {
230
+ if (isValidDate(event.target.value)) {
231
+ setCalendarDate(new Date(event.target.value))
232
+ setStartDate(new Date(event.target.value))
233
+ }
234
+ }}
201
235
  onClick={() => setSelectEndDate(false)}
202
236
  ref={inputStartRef}
203
237
  />
204
- {range && infixIcon !== false && (
238
+ {range && separator !== false && (
205
239
  <CInputGroupText>
206
- {infixIcon ? (
207
- infixIcon
208
- ) : (
240
+ {typeof separator === 'boolean' ? (
209
241
  <span className="picker-input-group-icon date-picker-arrow-icon" />
242
+ ) : (
243
+ separator
210
244
  )}
211
245
  </CInputGroupText>
212
246
  )}
213
247
  {range && (
214
248
  <CFormInput
215
249
  className={classNames({
216
- hover: inputToHoverValue,
250
+ hover: inputEndHoverValue,
217
251
  })}
218
252
  disabled={disabled}
219
253
  placeholder={placeholder[1]}
220
254
  readOnly={inputReadOnly}
255
+ onChange={(event) => {
256
+ if (isValidDate(event.target.value)) {
257
+ setCalendarDate(new Date(event.target.value))
258
+ setEndDate(new Date(event.target.value))
259
+ }
260
+ }}
221
261
  onClick={() => setSelectEndDate(true)}
222
262
  ref={inputEndRef}
223
263
  />
224
264
  )}
225
- {(defaultIcon !== false || cleaner) && (
265
+ {(indicator || cleaner) && (
226
266
  <CInputGroupText>
227
- {defaultIcon !== false && (
267
+ {indicator && (
228
268
  <span className="picker-input-group-indicator">
229
- {defaultIcon ? (
230
- defaultIcon
231
- ) : (
269
+ {typeof indicator === 'boolean' ? (
232
270
  <span className="picker-input-group-icon date-picker-input-icon" />
271
+ ) : (
272
+ indicator
233
273
  )}
234
274
  </span>
235
275
  )}
@@ -239,10 +279,10 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
239
279
  role="button"
240
280
  onClick={(event) => handleClear(event)}
241
281
  >
242
- {cleanerIcon ? (
243
- cleanerIcon
244
- ) : (
282
+ {typeof cleaner === 'boolean' ? (
245
283
  <span className="picker-input-group-icon date-picker-cleaner-icon" />
284
+ ) : (
285
+ cleaner
246
286
  )}
247
287
  </span>
248
288
  )}
@@ -255,11 +295,21 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
255
295
  <CPicker
256
296
  className={_className}
257
297
  disabled={disabled}
258
- footer={timepicker}
298
+ footer={footer || timepicker}
259
299
  toggler={toggler ? toggler : InputGroup()}
260
- onCancelClick={() => {
261
- handleStartDateChange(startDate ? new Date(startDate) : null)
262
- handleEndDateChange(endDate ? new Date(endDate) : null)
300
+ onCancel={() => {
301
+ handleStartDateChange(initialStartDate)
302
+ handleEndDateChange(initialEndDate)
303
+ }}
304
+ onHide={() => {
305
+ setInputStartHoverValue(null)
306
+ setInputEndHoverValue(null)
307
+ onHide && onHide()
308
+ }}
309
+ onShow={() => {
310
+ setInitialStartDate(_startDate)
311
+ setInitialEndDate(_endDate)
312
+ onShow && onShow()
263
313
  }}
264
314
  visible={_visible}
265
315
  {...rest}
@@ -270,13 +320,14 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
270
320
  <div className="date-picker-ranges">
271
321
  {Object.keys(ranges).map((key: string, index: number) => (
272
322
  <CButton
273
- color="secondary"
323
+ color={rangesButtonsColor}
274
324
  key={index}
275
325
  onClick={() => {
276
326
  setStartDate(ranges[key][0])
277
327
  setEndDate(ranges[key][1])
278
328
  }}
279
- variant="ghost"
329
+ size={rangesButtonsSize}
330
+ variant={rangesButtonsVariant}
280
331
  >
281
332
  {key}
282
333
  </CButton>
@@ -292,9 +343,11 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
292
343
  }
293
344
  disabledDates={disabledDates}
294
345
  endDate={_endDate}
346
+ firstDayOfWeek={firstDayOfWeek}
295
347
  locale={locale}
296
348
  maxDate={maxDate}
297
349
  minDate={minDate}
350
+ navigation={navigation}
298
351
  range={range}
299
352
  selectEndDate={selectEndDate}
300
353
  startDate={_startDate}
@@ -316,10 +369,10 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
316
369
  : false
317
370
  }
318
371
  locale={locale}
319
- onChange={(_, __, date) =>
372
+ onTimeChange={(_, __, date) =>
320
373
  index === 0 ? handleStartDateChange(date) : handleEndDateChange(date)
321
374
  }
322
- value={index === 0 ? _startDate : _endDate}
375
+ time={index === 0 ? _startDate : _endDate}
323
376
  variant="select"
324
377
  />
325
378
  )}
@@ -329,16 +382,16 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
329
382
  container="inline"
330
383
  disabled={_startDate === null ? true : false}
331
384
  locale={locale}
332
- onChange={(_, __, date) => handleStartDateChange(date)}
333
- value={_startDate}
385
+ onTimeChange={(_, __, date) => handleStartDateChange(date)}
386
+ time={_startDate}
334
387
  variant="select"
335
388
  />
336
389
  <CTimePicker
337
390
  container="inline"
338
391
  disabled={_endDate === null ? true : false}
339
392
  locale={locale}
340
- onChange={(_, __, date) => handleEndDateChange(date)}
341
- value={_endDate}
393
+ onTimeChange={(_, __, date) => handleEndDateChange(date)}
394
+ time={_endDate}
342
395
  variant="select"
343
396
  />
344
397
  </>
@@ -358,9 +411,17 @@ CDateRangePicker.propTypes = {
358
411
  ...CCalendar.propTypes,
359
412
  ...CPicker.propTypes,
360
413
  calendars: PropTypes.number,
414
+ className: PropTypes.string,
415
+ cleaner: PropTypes.bool,
416
+ indicator: PropTypes.oneOfType([PropTypes.bool, PropTypes.node]),
361
417
  inputReadOnly: PropTypes.bool,
362
418
  placeholder: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.any)]),
363
419
  range: PropTypes.bool,
364
420
  ranges: PropTypes.object,
421
+ rangesButtonsColor: CButton.propTypes?.color,
422
+ rangesButtonsSize: CButton.propTypes?.size,
423
+ rangesButtonsVariant: CButton.propTypes?.variant,
424
+ separator: PropTypes.oneOfType([PropTypes.bool, PropTypes.node]),
425
+ size: PropTypes.oneOf(['sm', 'lg']),
365
426
  timepicker: PropTypes.bool,
366
427
  }
@@ -0,0 +1,9 @@
1
+ import * as React from 'react'
2
+ import { render } from '@testing-library/react'
3
+ import '@testing-library/jest-dom/extend-expect'
4
+ import { CDateRangePicker } from '../CDateRangePicker'
5
+
6
+ test('loads and displays CDateRangePicker component', async () => {
7
+ const { container } = render(<CDateRangePicker />)
8
+ expect(container).toMatchSnapshot()
9
+ })