@coreui/react-pro 4.11.3 → 4.12.0-alpha.0

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 (67) hide show
  1. package/README.md +1 -1
  2. package/dist/components/date-range-picker/CDateRangePicker copy.d.ts +114 -0
  3. package/dist/components/date-range-picker/CDateRangePicker.d.ts +49 -1
  4. package/dist/components/multi-select/CMultiSelect.d.ts +34 -3
  5. package/dist/components/multi-select/CMultiSelectNativeSelect.d.ts +4 -5
  6. package/dist/components/multi-select/CMultiSelectOptions.d.ts +4 -2
  7. package/dist/components/multi-select/CMultiSelectSelection.d.ts +1 -0
  8. package/dist/components/multi-select/types.d.ts +7 -3
  9. package/dist/components/multi-select/utils.d.ts +5 -5
  10. package/dist/components/multi-select-new/CMultiSelect.d.ts +133 -0
  11. package/dist/components/multi-select-new/CMultiSelectNativeSelect.d.ts +7 -0
  12. package/dist/components/multi-select-new/CMultiSelectNew.d.ts +121 -0
  13. package/dist/components/multi-select-new/CMultiSelectOptions.d.ts +16 -0
  14. package/dist/components/multi-select-new/CMultiSelectSelection.d.ts +11 -0
  15. package/dist/components/multi-select-new/index.d.ts +2 -0
  16. package/dist/components/multi-select-new/types.d.ts +15 -0
  17. package/dist/components/multi-select-new/utils.d.ts +11 -0
  18. package/dist/components/picker/CPicker copy.d.ts +82 -0
  19. package/dist/components/picker/CPicker.d.ts +14 -56
  20. package/dist/components/picker copy/CPicker.d.ts +82 -0
  21. package/dist/components/popover/CPopover.d.ts +1 -1
  22. package/dist/components/time-picker/CTimePicker.d.ts +41 -1
  23. package/dist/components/tooltip/CTooltip.d.ts +3 -3
  24. package/dist/index.es.js +2197 -2074
  25. package/dist/index.es.js.map +1 -1
  26. package/dist/index.js +2196 -2073
  27. package/dist/index.js.map +1 -1
  28. package/dist/utils/index.d.ts +2 -1
  29. package/dist/utils/isRTL.d.ts +2 -0
  30. package/package.json +7 -7
  31. package/src/components/calendar/__tests__/__snapshots__/CCalendar.spec.tsx.snap +601 -555
  32. package/src/components/date-picker/__tests__/__snapshots__/CDatePicker.spec.tsx.snap +599 -561
  33. package/src/components/date-range-picker/CDateRangePicker.tsx +198 -97
  34. package/src/components/date-range-picker/__tests__/__snapshots__/CDateRangePicker.spec.tsx.snap +1197 -1121
  35. package/src/components/dropdown/CDropdownMenu.tsx +5 -4
  36. package/src/components/dropdown/__tests__/__snapshots__/CDropdown.spec.tsx.snap +1 -1
  37. package/src/components/element-cover/CElementCover.tsx +1 -0
  38. package/src/components/multi-select/CMultiSelect.tsx +200 -79
  39. package/src/components/multi-select/CMultiSelectNativeSelect.tsx +34 -24
  40. package/src/components/multi-select/CMultiSelectOptions.tsx +25 -23
  41. package/src/components/multi-select/CMultiSelectSelection.tsx +36 -7
  42. package/src/components/multi-select/__tests__/CMultiSelect.spec.tsx +25 -14
  43. package/src/components/multi-select/__tests__/CMultiSelectNativeSelect.spec.tsx +1 -1
  44. package/src/components/multi-select/__tests__/CMultiSelectOptions.spec.tsx +4 -4
  45. package/src/components/multi-select/__tests__/CMultiSelectSelection.spec.tsx +0 -1
  46. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelect.spec.tsx.snap +136 -30
  47. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectNativeSelect.spec.tsx.snap +2 -0
  48. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectOptions.spec.tsx.snap +3 -1
  49. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectSelection.spec.tsx.snap +2 -2
  50. package/src/components/multi-select/types.ts +9 -4
  51. package/src/components/multi-select/utils.ts +56 -39
  52. package/src/components/picker/CPicker.tsx +113 -138
  53. package/src/components/popover/CPopover.tsx +62 -26
  54. package/src/components/smart-table/__tests__/CSmartTable.spec.tsx +1 -1
  55. package/src/components/smart-table/__tests__/__snapshots__/CSmartTable.spec.tsx.snap +580 -0
  56. package/src/components/time-picker/CTimePicker.tsx +182 -82
  57. package/src/components/time-picker/__tests__/__snapshots__/CTimePicker.spec.tsx.snap +1078 -0
  58. package/src/components/tooltip/CTooltip.tsx +66 -31
  59. package/src/components/virtual-scroller/CVirtualScroller.tsx +0 -1
  60. package/src/utils/index.ts +2 -1
  61. package/src/utils/isRTL.ts +13 -0
  62. package/src/components/multi-select/__tests__/CMultiSelectCleaner.spec.tsx +0 -15
  63. package/src/components/multi-select/__tests__/CMultiSelectSearchInput.spec.tsx +0 -17
  64. package/src/components/multi-select/__tests__/CMultiSelectSelectAllButton.spec.tsx +0 -21
  65. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectCleaner.spec.tsx.snap +0 -19
  66. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectSearchInput.spec.tsx.snap +0 -20
  67. package/src/components/multi-select/__tests__/__snapshots__/CMultiSelectSelectAllButton.spec.tsx.snap +0 -24
@@ -7,22 +7,46 @@ import { isMobile } from 'react-device-detect'
7
7
 
8
8
  import { CButton } from '../button'
9
9
  import { CCalendar, CCalendarProps } from '../calendar/CCalendar'
10
- import { CFormInput, CInputGroup, CInputGroupText } from '../form'
11
10
  import { CFormControlWrapper, CFormControlWrapperProps } from '../form/CFormControlWrapper'
12
11
  import { CPicker, CPickerProps } from '../picker/CPicker'
13
12
  import { CTimePicker } from '../time-picker/CTimePicker'
14
13
 
14
+ import { Colors } from '../../types'
15
15
  import { getLocalDateFromString } from './utils'
16
16
 
17
- import { Colors } from '../../types'
18
17
  export interface CDateRangePickerProps
19
18
  extends Omit<CFormControlWrapperProps, 'floatingLabel'>,
20
- Omit<CPickerProps, 'autoClose' | 'component' | 'dark' | 'placeholder' | 'variant'>,
19
+ Omit<CPickerProps, 'placeholder'>,
21
20
  Omit<CCalendarProps, 'onCalendarCellHover' | 'onCalendarDateChange'> {
22
21
  /**
23
22
  * The number of calendars that render on desktop devices.
24
23
  */
25
24
  calendars?: number
25
+ /**
26
+ * Toggle visibility or set the content of cancel button.
27
+ *
28
+ * @default 'Cancel'
29
+ */
30
+ cancelButton?: boolean | ReactNode
31
+ /**
32
+ * Sets the color context of the cancel button to one of CoreUI’s themed colors.
33
+ *
34
+ * @type 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | string
35
+ * @default 'primary'
36
+ */
37
+ cancelButtonColor?: Colors
38
+ /**
39
+ * Size the cancel button small or large.
40
+ *
41
+ * @default 'sm'
42
+ */
43
+ cancelButtonSize?: 'sm' | 'lg'
44
+ /**
45
+ * Set the cancel button variant to an outlined button or a ghost button.
46
+ *
47
+ * @default 'ghost'
48
+ */
49
+ cancelButtonVariant?: 'outline' | 'ghost'
26
50
  /**
27
51
  * A string of all className you want applied to the component.
28
52
  */
@@ -37,6 +61,29 @@ export interface CDateRangePickerProps
37
61
  * Toggle visibility or set the content of the cleaner button.
38
62
  */
39
63
  cleaner?: boolean
64
+ /**
65
+ * Toggle visibility or set the content of confirm button.
66
+ *
67
+ * @default 'OK'
68
+ */
69
+ confirmButton?: boolean | ReactNode
70
+ /**
71
+ * Sets the color context of the confirm button to one of CoreUI’s themed colors.
72
+ *
73
+ * @type 'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'dark' | 'light' | string
74
+ * @default 'primary'
75
+ */
76
+ confirmButtonColor?: Colors
77
+ /**
78
+ * Size the confirm button small or large.
79
+ *
80
+ * @default 'sm'
81
+ */
82
+ confirmButtonSize?: 'sm' | 'lg'
83
+ /**
84
+ * Set the confirm button variant to an outlined button or a ghost button.
85
+ */
86
+ confirmButtonVariant?: 'outline' | 'ghost'
40
87
  /**
41
88
  * Set date format.
42
89
  * We use date-fns to format dates. Visit https://date-fns.org/v2.28.0/docs/format to check accepted patterns.
@@ -86,7 +133,7 @@ export interface CDateRangePickerProps
86
133
  rangesButtonsVariant?: 'outline' | 'ghost'
87
134
  /**
88
135
  * When present, it specifies that date must be filled out before submitting the form.
89
- *
136
+ *
90
137
  * @since 4.10.0
91
138
  */
92
139
  required?: boolean
@@ -131,10 +178,18 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
131
178
  (
132
179
  {
133
180
  calendars = 2,
181
+ calendarDate,
182
+ cancelButton = 'Cancel',
183
+ cancelButtonColor = 'primary',
184
+ cancelButtonSize = 'sm',
185
+ cancelButtonVariant = 'ghost',
134
186
  className,
135
187
  cleaner = true,
136
- calendarDate,
137
188
  closeOnSelect = true,
189
+ confirmButton = 'OK',
190
+ confirmButtonColor = 'primary',
191
+ confirmButtonSize = 'sm',
192
+ confirmButtonVariant,
138
193
  indicator = true,
139
194
  dayFormat,
140
195
  disabled,
@@ -186,28 +241,34 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
186
241
  },
187
242
  ref,
188
243
  ) => {
189
- const [_visible, setVisible] = useState(visible)
190
-
191
- const inputStartRef = useRef<HTMLInputElement>(null)
192
244
  const inputEndRef = useRef<HTMLInputElement>(null)
193
- const [inputStartHoverValue, setInputStartHoverValue] = useState<Date | null>(null)
194
- const [inputEndHoverValue, setInputEndHoverValue] = useState<Date | null>(null)
245
+ const inputStartRef = useRef<HTMLInputElement>(null)
246
+ const formRef = useRef<HTMLFormElement>()
195
247
 
196
248
  const [_calendarDate, setCalendarDate] = useState<Date>(
197
249
  calendarDate ? new Date(calendarDate) : new Date(),
198
250
  )
199
- const [_startDate, setStartDate] = useState<Date | null>(startDate ? new Date(startDate) : null)
200
251
  const [_endDate, setEndDate] = useState<Date | null>(endDate ? new Date(endDate) : null)
252
+ const [_maxDate, setMaxDate] = useState<Date | null>(maxDate ? new Date(maxDate) : null)
253
+ const [_minDate, setMinDate] = useState<Date | null>(minDate ? new Date(minDate) : null)
254
+ const [_startDate, setStartDate] = useState<Date | null>(startDate ? new Date(startDate) : null)
255
+ const [_visible, setVisible] = useState(visible)
256
+
201
257
  const [initialStartDate, setInitialStartDate] = useState<Date | null>(
202
258
  startDate ? new Date(startDate) : null,
203
259
  )
204
260
  const [initialEndDate, setInitialEndDate] = useState<Date | null>(
205
261
  endDate ? new Date(endDate) : null,
206
262
  )
207
- const [_maxDate, setMaxDate] = useState<Date | null>(maxDate ? new Date(maxDate) : null)
208
- const [_minDate, setMinDate] = useState<Date | null>(minDate ? new Date(minDate) : null)
263
+ const [inputStartHoverValue, setInputStartHoverValue] = useState<Date | null>(null)
264
+ const [inputEndHoverValue, setInputEndHoverValue] = useState<Date | null>(null)
265
+ const [isValid, setIsValid] = useState(valid || (invalid && false))
209
266
  const [selectEndDate, setSelectEndDate] = useState(false)
210
267
 
268
+ useEffect(() => {
269
+ setIsValid(valid || (invalid && false))
270
+ }, [valid, invalid])
271
+
211
272
  useEffect(() => {
212
273
  if (startDate) {
213
274
  setStartDate(new Date(startDate))
@@ -248,6 +309,22 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
248
309
  setInputValue(inputEndRef.current, _endDate)
249
310
  }, [inputEndHoverValue, _endDate])
250
311
 
312
+ useEffect(() => {
313
+ if (inputStartRef.current && inputStartRef.current.form) {
314
+ formRef.current = inputStartRef.current.form
315
+ }
316
+ }, [inputStartRef])
317
+
318
+ useEffect(() => {
319
+ if (formRef.current) {
320
+ formRef.current.addEventListener('submit', (event) => {
321
+ setTimeout(() => handleFormValidation(event.target as HTMLFormElement))
322
+ })
323
+
324
+ handleFormValidation(formRef.current)
325
+ }
326
+ }, [formRef, _startDate, _endDate])
327
+
251
328
  const formatDate = (date: Date) => {
252
329
  return format
253
330
  ? dateFormat(date, format)
@@ -279,18 +356,10 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
279
356
  : setCalendarDate(date)
280
357
  }
281
358
 
282
- const handleStartDateChange = (date: Date | null) => {
283
- setStartDate(date)
284
- setInputStartHoverValue(null)
285
- onStartDateChange && onStartDateChange(date, date ? formatDate(date) : undefined)
286
-
287
- if (timepicker || footer) {
288
- return
289
- }
290
-
291
- if (closeOnSelect && !range) {
292
- setVisible(false)
293
- }
359
+ const handleClear = (event: React.MouseEvent<HTMLElement>) => {
360
+ event.stopPropagation()
361
+ setStartDate(null)
362
+ setEndDate(null)
294
363
  }
295
364
 
296
365
  const handleEndDateChange = (date: Date | null) => {
@@ -307,20 +376,40 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
307
376
  }
308
377
  }
309
378
 
310
- const handleClear = (event: React.MouseEvent<HTMLElement>) => {
311
- event.stopPropagation()
312
- setStartDate(null)
313
- setEndDate(null)
379
+ const handleFormValidation = (form: HTMLFormElement) => {
380
+ if (!form.classList.contains('was-validated')) {
381
+ return
382
+ }
383
+
384
+ if ((range && _startDate && _endDate) || (!range && _startDate)) {
385
+ return setIsValid(true)
386
+ }
387
+
388
+ setIsValid(false)
389
+ }
390
+
391
+ const handleStartDateChange = (date: Date | null) => {
392
+ setStartDate(date)
393
+ setInputStartHoverValue(null)
394
+ onStartDateChange && onStartDateChange(date, date ? formatDate(date) : undefined)
395
+
396
+ if (timepicker || footer) {
397
+ return
398
+ }
399
+
400
+ if (closeOnSelect && !range) {
401
+ setVisible(false)
402
+ }
314
403
  }
315
404
 
316
405
  const InputGroup = () => (
317
- <CInputGroup className="picker-input-group" size={size}>
318
- <CFormInput
406
+ <div className="date-picker-input-group">
407
+ <input
319
408
  autoComplete="off"
320
- className={classNames({
409
+ className={classNames('date-picker-input', {
321
410
  hover: inputStartHoverValue,
322
411
  })}
323
- delay={true}
412
+ // delay={true}
324
413
  disabled={disabled}
325
414
  {...(id && { name: range ? `${id}-start-date` : `${id}-date` })}
326
415
  placeholder={Array.isArray(placeholder) ? placeholder[0] : placeholder}
@@ -336,22 +425,14 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
336
425
  onClick={() => setSelectEndDate(false)}
337
426
  ref={inputStartRef}
338
427
  />
339
- {range && separator !== false && (
340
- <CInputGroupText>
341
- {typeof separator === 'boolean' ? (
342
- <span className="picker-input-group-icon date-picker-arrow-icon" />
343
- ) : (
344
- separator
345
- )}
346
- </CInputGroupText>
347
- )}
428
+ {range && separator !== false && <div className="date-picker-separator" />}
348
429
  {range && (
349
- <CFormInput
430
+ <input
350
431
  autoComplete="off"
351
- className={classNames({
432
+ className={classNames('date-picker-input', {
352
433
  hover: inputEndHoverValue,
353
434
  })}
354
- delay={true}
435
+ // delay={true}
355
436
  disabled={disabled}
356
437
  {...(id && { name: `${id}-end-date` })}
357
438
  placeholder={placeholder[1]}
@@ -368,33 +449,19 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
368
449
  ref={inputEndRef}
369
450
  />
370
451
  )}
371
- {(indicator || cleaner) && (
372
- <CInputGroupText>
373
- {indicator && (
374
- <span className="picker-input-group-indicator">
375
- {typeof indicator === 'boolean' ? (
376
- <span className="picker-input-group-icon date-picker-input-icon" />
377
- ) : (
378
- indicator
379
- )}
380
- </span>
381
- )}
382
- {cleaner && _startDate && (
383
- <span
384
- className="picker-input-group-cleaner"
385
- role="button"
386
- onClick={(event) => handleClear(event)}
387
- >
388
- {typeof cleaner === 'boolean' ? (
389
- <span className="picker-input-group-icon date-picker-cleaner-icon" />
390
- ) : (
391
- cleaner
392
- )}
393
- </span>
394
- )}
395
- </CInputGroupText>
396
- )}
397
- </CInputGroup>
452
+ {indicator &&
453
+ (typeof indicator === 'boolean' ? <div className="date-picker-indicator" /> : indicator)}
454
+ {cleaner &&
455
+ (_startDate || _endDate) &&
456
+ (typeof cleaner === 'boolean' ? (
457
+ <div className="date-picker-cleaner" onClick={(event) => handleClear(event)} />
458
+ ) : (
459
+ React.isValidElement(cleaner) &&
460
+ React.cloneElement(cleaner as React.ReactElement<any>, {
461
+ onClick: (event: React.MouseEvent<HTMLElement>) => handleClear(event),
462
+ })
463
+ ))}
464
+ </div>
398
465
  )
399
466
 
400
467
  return (
@@ -404,48 +471,74 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
404
471
  feedbackInvalid={feedbackInvalid}
405
472
  feedbackValid={feedbackValid}
406
473
  id={id}
407
- invalid={invalid}
474
+ invalid={isValid === false ? true : false}
408
475
  label={label}
409
476
  text={text}
410
477
  tooltipFeedback={tooltipFeedback}
411
- valid={valid}
478
+ valid={isValid}
412
479
  >
413
480
  <CPicker
414
481
  className={classNames(
415
482
  'date-picker',
416
483
  {
417
- 'is-invalid': invalid,
418
- 'is-valid': valid,
484
+ [`date-picker-${size}`]: size,
485
+ disabled: disabled,
486
+ 'is-invalid': isValid === false ? true : false,
487
+ 'is-valid': isValid,
419
488
  },
420
489
  className,
421
490
  )}
422
491
  disabled={disabled}
492
+ dropdownClassNames="date-picker-dropdown"
423
493
  footer={footer || timepicker}
424
494
  footerContent={
425
- todayButton && (
426
- <CButton
427
- className="me-auto"
428
- color={todayButtonColor}
429
- size={todayButtonSize}
430
- variant={todayButtonVariant}
431
- onClick={() => {
432
- const date = new Date()
433
- handleStartDateChange(date)
434
- handleEndDateChange(date)
435
- setCalendarDate(date)
436
- }}
437
- >
438
- {todayButton}
439
- </CButton>
440
- )
495
+ <div className="date-picker-footer">
496
+ {todayButton && (
497
+ <CButton
498
+ className="me-auto"
499
+ color={todayButtonColor}
500
+ size={todayButtonSize}
501
+ variant={todayButtonVariant}
502
+ onClick={() => {
503
+ const date = new Date()
504
+ handleStartDateChange(date)
505
+ handleEndDateChange(date)
506
+ setCalendarDate(date)
507
+ }}
508
+ >
509
+ {todayButton}
510
+ </CButton>
511
+ )}
512
+ {cancelButton && (
513
+ <CButton
514
+ color={cancelButtonColor}
515
+ size={cancelButtonSize}
516
+ variant={cancelButtonVariant}
517
+ onClick={() => {
518
+ handleStartDateChange(initialStartDate)
519
+ handleEndDateChange(initialEndDate)
520
+ setVisible(false)
521
+ }}
522
+ >
523
+ {cancelButton}
524
+ </CButton>
525
+ )}
526
+ {confirmButton && (
527
+ <CButton
528
+ color={confirmButtonColor}
529
+ size={confirmButtonSize}
530
+ variant={confirmButtonVariant}
531
+ onClick={() => {
532
+ setVisible(false)
533
+ }}
534
+ >
535
+ {confirmButton}
536
+ </CButton>
537
+ )}
538
+ </div>
441
539
  }
442
540
  id={id}
443
541
  toggler={toggler ?? InputGroup()}
444
- onCancel={() => {
445
- handleStartDateChange(initialStartDate)
446
- handleEndDateChange(initialEndDate)
447
- setVisible(false)
448
- }}
449
542
  onHide={() => {
450
543
  setVisible(false)
451
544
  onHide && onHide()
@@ -565,10 +658,18 @@ CDateRangePicker.propTypes = {
565
658
  ...CCalendar.propTypes,
566
659
  ...CFormControlWrapper.propTypes,
567
660
  ...CPicker.propTypes,
661
+ cancelButton: PropTypes.oneOfType([PropTypes.bool, PropTypes.node]),
662
+ cancelButtonColor: CButton.propTypes?.color,
663
+ cancelButtonSize: CButton.propTypes?.size,
664
+ cancelButtonVariant: CButton.propTypes?.variant,
568
665
  calendars: PropTypes.number,
569
666
  className: PropTypes.string,
570
667
  cleaner: PropTypes.bool,
571
668
  closeOnSelect: PropTypes.bool,
669
+ confirmButton: PropTypes.oneOfType([PropTypes.bool, PropTypes.node]),
670
+ confirmButtonColor: CButton.propTypes?.color,
671
+ confirmButtonSize: CButton.propTypes?.size,
672
+ confirmButtonVariant: CButton.propTypes?.variant,
572
673
  id: PropTypes.string,
573
674
  indicator: PropTypes.oneOfType([PropTypes.bool, PropTypes.node]),
574
675
  inputReadOnly: PropTypes.bool,