@coreui/react-pro 5.0.0-alpha.0 → 5.0.0-alpha.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 (53) hide show
  1. package/README.md +1 -1
  2. package/dist/components/calendar/CCalendar.d.ts +25 -7
  3. package/dist/components/calendar/utils.d.ts +12 -3
  4. package/dist/components/close-button/CCloseButton.d.ts +6 -0
  5. package/dist/components/modal/CModal.d.ts +6 -0
  6. package/dist/components/multi-select/types.d.ts +2 -2
  7. package/dist/components/multi-select/utils.d.ts +2 -2
  8. package/dist/components/nav/CNav.d.ts +1 -1
  9. package/dist/components/navbar/CNavbar.d.ts +1 -1
  10. package/dist/components/offcanvas/COffcanvas.d.ts +4 -0
  11. package/dist/components/smart-table/CSmartTableBody.d.ts +2 -1
  12. package/dist/components/smart-table/CSmartTableInterface.d.ts +1 -3
  13. package/dist/components/smart-table/types.d.ts +2 -2
  14. package/dist/components/smart-table/utils.d.ts +3 -1
  15. package/dist/index.es.js +1388 -1097
  16. package/dist/index.es.js.map +1 -1
  17. package/dist/index.js +1388 -1097
  18. package/dist/index.js.map +1 -1
  19. package/dist/utils/executeAfterTransition.d.ts +2 -0
  20. package/dist/utils/getTransitionDurationFromElement.d.ts +2 -0
  21. package/dist/utils/index.d.ts +3 -1
  22. package/package.json +2 -2
  23. package/src/components/calendar/CCalendar.tsx +396 -193
  24. package/src/components/calendar/utils.ts +91 -4
  25. package/src/components/carousel/CCarousel.tsx +9 -5
  26. package/src/components/close-button/CCloseButton.tsx +9 -1
  27. package/src/components/date-range-picker/CDateRangePicker.tsx +49 -45
  28. package/src/components/dropdown/CDropdownMenu.tsx +1 -1
  29. package/src/components/modal/CModal.tsx +25 -9
  30. package/src/components/multi-select/CMultiSelect.tsx +3 -3
  31. package/src/components/multi-select/CMultiSelectNativeSelect.tsx +1 -1
  32. package/src/components/multi-select/CMultiSelectOptions.tsx +1 -1
  33. package/src/components/multi-select/CMultiSelectSelection.tsx +3 -3
  34. package/src/components/multi-select/types.ts +2 -2
  35. package/src/components/multi-select/utils.ts +5 -5
  36. package/src/components/nav/CNav.tsx +2 -2
  37. package/src/components/nav/CNavGroup.tsx +9 -2
  38. package/src/components/navbar/CNavbar.tsx +2 -2
  39. package/src/components/offcanvas/COffcanvas.tsx +8 -1
  40. package/src/components/popover/CPopover.tsx +2 -2
  41. package/src/components/sidebar/CSidebar.tsx +1 -1
  42. package/src/components/smart-table/CSmartTable.tsx +2 -1
  43. package/src/components/smart-table/CSmartTableBody.tsx +11 -5
  44. package/src/components/smart-table/CSmartTableInterface.tsx +1 -3
  45. package/src/components/smart-table/types.ts +2 -2
  46. package/src/components/smart-table/utils.ts +40 -5
  47. package/src/components/time-picker/CTimePicker.tsx +2 -2
  48. package/src/components/time-picker/utils.ts +5 -1
  49. package/src/components/tooltip/CTooltip.tsx +2 -2
  50. package/src/hooks/usePopper.ts +10 -2
  51. package/src/utils/executeAfterTransition.ts +46 -0
  52. package/src/utils/getTransitionDurationFromElement.ts +24 -0
  53. package/src/utils/index.ts +10 -1
@@ -1,3 +1,31 @@
1
+ export const convertIsoWeekToDate = (isoWeek: string) => {
2
+ const [year, week] = isoWeek.split(/w/i)
3
+ // Get date for 4th of January for year
4
+ const date = new Date(Number(year), 0, 4)
5
+ // Get previous Monday, add 7 days for each week after first
6
+ date.setDate(date.getDate() - (date.getDay() || 7) + 1 + (Number(week) - 1) * 7)
7
+ return date
8
+ }
9
+
10
+ export const convertToDateObject = (
11
+ date: Date | string | null,
12
+ selectionType?: 'day' | 'week' | 'month' | 'year',
13
+ ) => {
14
+ // if (date === null) {
15
+ // return null
16
+ // }
17
+
18
+ if (date instanceof Date) {
19
+ return date
20
+ }
21
+
22
+ if (selectionType === 'week') {
23
+ return convertIsoWeekToDate(date as string)
24
+ }
25
+
26
+ return new Date(Date.parse(date))
27
+ }
28
+
1
29
  export const convertToLocalDate = (d: Date, locale: string, options = {}) =>
2
30
  d.toLocaleDateString(locale, options)
3
31
 
@@ -11,10 +39,50 @@ export const createGroupsInArray = <T>(arr: T[], numberOfGroups: number): T[][]
11
39
  .map((_, i) => arr.slice(i * perGroup, (i + 1) * perGroup))
12
40
  }
13
41
 
42
+ export const getCalendarDate = (calendarDate: Date, order: number, view: 'days' | 'months' | 'years') => {
43
+ if (order !== 0 && view === 'days') {
44
+ return new Date(Date.UTC(calendarDate.getFullYear(), calendarDate.getMonth() + order, 1))
45
+ }
46
+
47
+ if (order !== 0 && view === 'months') {
48
+ return new Date(Date.UTC(calendarDate.getFullYear() + order, calendarDate.getMonth(), 1))
49
+ }
50
+
51
+ if (order !== 0 && view === 'years') {
52
+ return new Date(Date.UTC(calendarDate.getFullYear() + (12 * order), calendarDate.getMonth(), 1))
53
+ }
54
+
55
+ return calendarDate
56
+ }
57
+
14
58
  export const getCurrentYear = () => new Date().getFullYear()
15
59
 
16
60
  export const getCurrentMonth = () => new Date().getMonth()
17
61
 
62
+ export const getDateBySelectionType = (
63
+ date: Date | null,
64
+ selectionType: 'day' | 'week' | 'month' | 'year',
65
+ ) => {
66
+ if (date === null) {
67
+ return null
68
+ }
69
+
70
+ if (selectionType === 'week') {
71
+ return `${date.getFullYear()}W${getWeekNumber(date)}`
72
+ }
73
+
74
+ if (selectionType === 'month') {
75
+ const monthNumber = `0${date.getMonth() + 1}`.slice(-2)
76
+ return `${date.getFullYear()}-${monthNumber}`
77
+ }
78
+
79
+ if (selectionType === 'year') {
80
+ return `${date.getFullYear()}`
81
+ }
82
+
83
+ return date
84
+ }
85
+
18
86
  export const getMonthName = (month: number, locale: string) => {
19
87
  const d = new Date()
20
88
  d.setDate(1)
@@ -77,6 +145,7 @@ const getMonthDays = (year: number, month: number) => {
77
145
  month: 'current',
78
146
  })
79
147
  }
148
+
80
149
  return dates
81
150
  }
82
151
 
@@ -94,22 +163,40 @@ const getTrailingDays = (
94
163
  month: 'next',
95
164
  })
96
165
  }
166
+
97
167
  return dates
98
168
  }
99
169
 
170
+ export const getDayNumber = (date: Date) =>
171
+ Math.ceil((Number(date) - Number(new Date(date.getFullYear(), 0, 0))) / 1000 / 60 / 60 / 24)
172
+
173
+ export const getWeekNumber = (date: Date) => {
174
+ const week1 = new Date(date.getFullYear(), 0, 4)
175
+ return (
176
+ 1 +
177
+ Math.round(((date.getTime() - week1.getTime()) / 86400000 - 3 + ((week1.getDay() + 6) % 7)) / 7)
178
+ )
179
+ }
180
+
100
181
  export const getMonthDetails = (year: number, month: number, firstDayOfWeek: number) => {
101
182
  const daysPrevMonth = getLeadingDays(year, month, firstDayOfWeek)
102
183
  const daysThisMonth = getMonthDays(year, month)
103
184
  const daysNextMonth = getTrailingDays(year, month, daysPrevMonth, daysThisMonth)
104
185
  const days = [...daysPrevMonth, ...daysThisMonth, ...daysNextMonth]
105
-
106
- const weeks: { date: Date; month: string }[][] = []
186
+ const weeks: { weekNumber?: number; days: { date: Date; month: string }[] }[] = []
107
187
 
108
188
  days.forEach((day, index) => {
109
189
  if (index % 7 === 0 || weeks.length === 0) {
110
- weeks.push([])
190
+ weeks.push({
191
+ days: [],
192
+ })
111
193
  }
112
- weeks[weeks.length - 1].push(day)
194
+
195
+ if ((index + 1) % 7 === 0) {
196
+ weeks[weeks.length - 1].weekNumber = getWeekNumber(day.date)
197
+ }
198
+
199
+ weeks[weeks.length - 1].days.push(day)
113
200
  })
114
201
 
115
202
  return weeks
@@ -226,11 +226,11 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
226
226
  className={classNames(
227
227
  'carousel slide',
228
228
  {
229
- 'carousel-dark': dark,
230
229
  'carousel-fade': transition === 'crossfade',
231
230
  },
232
231
  className,
233
232
  )}
233
+ {...(dark && { 'data-coreui-theme': 'dark' })}
234
234
  onMouseEnter={_pause}
235
235
  onMouseLeave={cycle}
236
236
  {...(touch && { onTouchStart: handleTouchStart, onTouchMove: handleTouchMove })}
@@ -244,20 +244,24 @@ export const CCarousel = forwardRef<HTMLDivElement, CCarouselProps>(
244
244
  }}
245
245
  >
246
246
  {indicators && (
247
- <ol className="carousel-indicators">
247
+ <div className="carousel-indicators">
248
248
  {Array.from({ length: itemsNumber }, (_, i) => i).map((index) => {
249
249
  return (
250
- <li
250
+ <button
251
251
  key={`indicator${index}`}
252
252
  onClick={() => {
253
253
  !animating && handleIndicatorClick(index)
254
254
  }}
255
- className={active === index ? 'active' : ''}
255
+ className={classNames({
256
+ active: active === index
257
+ })}
256
258
  data-coreui-target=""
259
+ {...(active === index && { 'aria-current': true })}
260
+ aria-label={`Slide ${index + 1}`}
257
261
  />
258
262
  )
259
263
  })}
260
- </ol>
264
+ </div>
261
265
  )}
262
266
  <div className="carousel-inner">
263
267
  {Children.map(children, (child, index) => {
@@ -7,18 +7,24 @@ export interface CCloseButtonProps extends HTMLAttributes<HTMLButtonElement> {
7
7
  * A string of all className you want applied to the base component.
8
8
  */
9
9
  className?: string
10
+ /**
11
+ * Invert the default color.
12
+ */
13
+ dark?: boolean
10
14
  /**
11
15
  * Toggle the disabled state for the component.
12
16
  */
13
17
  disabled?: boolean
14
18
  /**
15
19
  * Change the default color to white.
20
+ *
21
+ * @deprecated 5.0.0
16
22
  */
17
23
  white?: boolean
18
24
  }
19
25
 
20
26
  export const CCloseButton = forwardRef<HTMLButtonElement, CCloseButtonProps>(
21
- ({ className, disabled, white, ...rest }, ref) => {
27
+ ({ className, dark, disabled, white, ...rest }, ref) => {
22
28
  return (
23
29
  <button
24
30
  type="button"
@@ -33,6 +39,7 @@ export const CCloseButton = forwardRef<HTMLButtonElement, CCloseButtonProps>(
33
39
  )}
34
40
  aria-label="Close"
35
41
  disabled={disabled}
42
+ {...(dark && { 'data-coreui-theme': 'dark' })}
36
43
  {...rest}
37
44
  ref={ref}
38
45
  />
@@ -42,6 +49,7 @@ export const CCloseButton = forwardRef<HTMLButtonElement, CCloseButtonProps>(
42
49
 
43
50
  CCloseButton.propTypes = {
44
51
  className: PropTypes.string,
52
+ dark: PropTypes.bool,
45
53
  disabled: PropTypes.bool,
46
54
  white: PropTypes.bool,
47
55
  }
@@ -223,7 +223,9 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
223
223
  required,
224
224
  separator = true,
225
225
  selectAdjacementDays,
226
+ selectionType = 'day',
226
227
  showAdjacementDays,
228
+ showWeekNumber,
227
229
  size,
228
230
  startDate,
229
231
  text,
@@ -245,50 +247,46 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
245
247
  const inputStartRef = useRef<HTMLInputElement>(null)
246
248
  const formRef = useRef<HTMLFormElement>()
247
249
 
248
- const [_calendarDate, setCalendarDate] = useState<Date>(
249
- calendarDate ? new Date(calendarDate) : new Date(),
250
- )
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)
250
+ const [_calendarDate, setCalendarDate] = useState<Date | string | null>(calendarDate ?? null)
251
+ const [_endDate, setEndDate] = useState<Date | string | null>(endDate ?? null)
252
+ const [_maxDate, setMaxDate] = useState<Date | string | null>(maxDate ?? null)
253
+ const [_minDate, setMinDate] = useState<Date | string | null>(minDate ?? null)
254
+ const [_startDate, setStartDate] = useState<Date | string | null>(startDate ?? null)
255
255
  const [_visible, setVisible] = useState(visible)
256
256
 
257
- const [initialStartDate, setInitialStartDate] = useState<Date | null>(
258
- startDate ? new Date(startDate) : null,
259
- )
260
- const [initialEndDate, setInitialEndDate] = useState<Date | null>(
261
- endDate ? new Date(endDate) : null,
257
+ const [initialStartDate, setInitialStartDate] = useState<Date | string | null>(
258
+ startDate ?? null,
262
259
  )
263
- const [inputStartHoverValue, setInputStartHoverValue] = useState<Date | null>(null)
264
- const [inputEndHoverValue, setInputEndHoverValue] = useState<Date | null>(null)
265
- const [isValid, setIsValid] = useState(valid || (invalid && false))
260
+ const [initialEndDate, setInitialEndDate] = useState<Date | string | null>(endDate ?? null)
261
+ const [inputStartHoverValue, setInputStartHoverValue] = useState<Date | string | null>(null)
262
+ const [inputEndHoverValue, setInputEndHoverValue] = useState<Date | string | null>(null)
263
+ const [isValid, setIsValid] = useState(valid ?? (invalid === true ? false : undefined))
266
264
  const [selectEndDate, setSelectEndDate] = useState(false)
267
265
 
268
266
  useEffect(() => {
269
- setIsValid(valid || (invalid && false))
267
+ setIsValid(valid ?? (invalid === true ? false : undefined))
270
268
  }, [valid, invalid])
271
269
 
272
270
  useEffect(() => {
273
271
  if (startDate) {
274
- setStartDate(new Date(startDate))
275
- setCalendarDate(new Date(startDate))
272
+ setStartDate(startDate)
273
+ setCalendarDate(startDate)
276
274
  }
277
275
  }, [startDate])
278
276
 
279
277
  useEffect(() => {
280
278
  if (endDate) {
281
- setEndDate(new Date(endDate))
282
- setCalendarDate(new Date(endDate))
279
+ setEndDate(endDate)
280
+ setCalendarDate(endDate)
283
281
  }
284
282
  }, [endDate])
285
283
 
286
284
  useEffect(() => {
287
- maxDate && setMaxDate(new Date(maxDate))
285
+ maxDate && setMaxDate(maxDate)
288
286
  }, [maxDate])
289
287
 
290
288
  useEffect(() => {
291
- minDate && setMinDate(new Date(minDate))
289
+ minDate && setMinDate(minDate)
292
290
  }, [minDate])
293
291
 
294
292
  useEffect(() => {
@@ -325,15 +323,21 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
325
323
  }
326
324
  }, [formRef, _startDate, _endDate])
327
325
 
328
- const formatDate = (date: Date) => {
329
- return format
330
- ? dateFormat(date, format)
331
- : timepicker
332
- ? date.toLocaleString(locale)
333
- : date.toLocaleDateString(locale)
326
+ const formatDate = (date: Date | string) => {
327
+ if (selectionType !== 'day') {
328
+ return date
329
+ }
330
+
331
+ const _date = new Date(date)
332
+
333
+ return format ?
334
+ dateFormat(_date, format) :
335
+ timepicker ?
336
+ _date.toLocaleString(locale) :
337
+ _date.toLocaleDateString(locale)
334
338
  }
335
339
 
336
- const setInputValue = (el: HTMLInputElement | null, date: Date | null) => {
340
+ const setInputValue = (el: HTMLInputElement | null, date: Date | string | null) => {
337
341
  if (!el) {
338
342
  return
339
343
  }
@@ -346,23 +350,17 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
346
350
  el.value = ''
347
351
  }
348
352
 
349
- const handleDayHover = (date: Date | null) => {
353
+ const handleDateHover = (date: Date | string | null) => {
350
354
  selectEndDate ? setInputEndHoverValue(date) : setInputStartHoverValue(date)
351
355
  }
352
356
 
353
- const handleCalendarDateChange = (date: Date, difference?: number) => {
354
- difference
355
- ? setCalendarDate(new Date(date.getFullYear(), date.getMonth() - difference, 1))
356
- : setCalendarDate(date)
357
- }
358
-
359
357
  const handleClear = (event: React.MouseEvent<HTMLElement>) => {
360
358
  event.stopPropagation()
361
359
  setStartDate(null)
362
360
  setEndDate(null)
363
361
  }
364
362
 
365
- const handleEndDateChange = (date: Date | null) => {
363
+ const handleEndDateChange = (date: Date | string | null) => {
366
364
  setEndDate(date)
367
365
  setInputEndHoverValue(null)
368
366
  onEndDateChange && onEndDateChange(date, date ? formatDate(date) : undefined)
@@ -388,7 +386,7 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
388
386
  setIsValid(false)
389
387
  }
390
388
 
391
- const handleStartDateChange = (date: Date | null) => {
389
+ const handleStartDateChange = (date: Date | string | null) => {
392
390
  setStartDate(date)
393
391
  setInputStartHoverValue(null)
394
392
  onStartDateChange && onStartDateChange(date, date ? formatDate(date) : undefined)
@@ -409,7 +407,7 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
409
407
  className={classNames('date-picker-input', {
410
408
  hover: inputStartHoverValue,
411
409
  })}
412
- // delay={true}
410
+ // delay={true} TODO
413
411
  disabled={disabled}
414
412
  {...(id && { name: range ? `${id}-start-date` : `${id}-date` })}
415
413
  placeholder={Array.isArray(placeholder) ? placeholder[0] : placeholder}
@@ -432,7 +430,7 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
432
430
  className={classNames('date-picker-input', {
433
431
  hover: inputEndHoverValue,
434
432
  })}
435
- // delay={true}
433
+ // delay={true} TODO
436
434
  disabled={disabled}
437
435
  {...(id && { name: `${id}-end-date` })}
438
436
  placeholder={placeholder[1]}
@@ -588,10 +586,12 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
588
586
  range={range}
589
587
  selectAdjacementDays={selectAdjacementDays}
590
588
  selectEndDate={selectEndDate}
589
+ selectionType={selectionType}
591
590
  showAdjacementDays={showAdjacementDays}
591
+ showWeekNumber={showWeekNumber}
592
592
  startDate={_startDate}
593
- onDayHover={(date) => handleDayHover(date)}
594
- onCalendarDateChange={(date) => handleCalendarDateChange(date)}
593
+ onDateHover={(date) => handleDateHover(date)}
594
+ onCalendarDateChange={(date) => setCalendarDate(date)}
595
595
  onStartDateChange={(date) => handleStartDateChange(date)}
596
596
  onEndDateChange={(date) => handleEndDateChange(date)}
597
597
  onSelectEndChange={(value) => setSelectEndDate(value)}
@@ -606,7 +606,7 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
606
606
  disabled={_startDate === null ? true : false}
607
607
  locale={locale}
608
608
  onTimeChange={(_, __, date) => date && handleStartDateChange(date)}
609
- time={_startDate}
609
+ time={_startDate && new Date(_startDate)}
610
610
  variant="select"
611
611
  />
612
612
  <CTimePicker
@@ -614,7 +614,7 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
614
614
  disabled={_endDate === null ? true : false}
615
615
  locale={locale}
616
616
  onTimeChange={(_, __, date) => date && handleEndDateChange(date)}
617
- time={_endDate}
617
+ time={_endDate && new Date(_endDate)}
618
618
  variant="select"
619
619
  />
620
620
  </>
@@ -638,7 +638,11 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
638
638
  ? date && handleStartDateChange(date)
639
639
  : date && handleEndDateChange(date)
640
640
  }
641
- time={index === 0 ? _startDate : _endDate}
641
+ time={
642
+ index === 0
643
+ ? _startDate && new Date(_startDate)
644
+ : _endDate && new Date(_endDate)
645
+ }
642
646
  variant="select"
643
647
  />
644
648
  ))
@@ -46,7 +46,6 @@ export const CDropdownMenu = forwardRef<HTMLDivElement | HTMLUListElement, CDrop
46
46
  className={classNames(
47
47
  'dropdown-menu',
48
48
  {
49
- 'dropdown-menu-dark': dark,
50
49
  show: visible,
51
50
  },
52
51
  alignment && alignmentClassNames(alignment),
@@ -56,6 +55,7 @@ export const CDropdownMenu = forwardRef<HTMLDivElement | HTMLUListElement, CDrop
56
55
  role="menu"
57
56
  aria-hidden={!visible}
58
57
  {...(!popper && { 'data-coreui-popper': 'static' })}
58
+ {...(dark && { 'data-coreui-theme': 'dark' })}
59
59
  {...rest}
60
60
  >
61
61
  {Component === 'ul'
@@ -11,7 +11,7 @@ import PropTypes from 'prop-types'
11
11
  import classNames from 'classnames'
12
12
  import { Transition } from 'react-transition-group'
13
13
 
14
- import { CBackdrop } from '../backdrop/CBackdrop'
14
+ import { CBackdrop } from '../backdrop'
15
15
  import { CConditionalPortal } from '../conditional-portal'
16
16
  import { CModalContent } from './CModalContent'
17
17
  import { CModalDialog } from './CModalDialog'
@@ -35,6 +35,12 @@ export interface CModalProps extends HTMLAttributes<HTMLDivElement> {
35
35
  * @ignore
36
36
  */
37
37
  duration?: number
38
+ /**
39
+ * Puts the focus on the modal when shown.
40
+ *
41
+ * @since v4.10.0
42
+ */
43
+ focus?: boolean
38
44
  /**
39
45
  * Set modal to covers the entire user viewport.
40
46
  */
@@ -96,6 +102,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
96
102
  backdrop = true,
97
103
  className,
98
104
  duration = 150,
105
+ focus = true,
99
106
  fullscreen,
100
107
  keyboard = true,
101
108
  onClose,
@@ -111,6 +118,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
111
118
  },
112
119
  ref,
113
120
  ) => {
121
+ const activeElementRef = useRef<HTMLElement | null>(null)
114
122
  const modalRef = useRef<HTMLDivElement>(null)
115
123
  const modalContentRef = useRef<HTMLDivElement>(null)
116
124
  const forkedRef = useForkedRef(ref, modalRef)
@@ -128,11 +136,16 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
128
136
  }, [visible])
129
137
 
130
138
  useEffect(() => {
131
- document.addEventListener('click', handleClickOutside)
132
- document.addEventListener('keydown', handleKeyDown)
139
+ if (_visible) {
140
+ activeElementRef.current = document.activeElement as HTMLElement | null
141
+ document.addEventListener('mouseup', handleClickOutside)
142
+ document.addEventListener('keydown', handleKeyDown)
143
+ } else {
144
+ activeElementRef.current?.focus()
145
+ }
133
146
 
134
147
  return () => {
135
- document.removeEventListener('click', handleClickOutside)
148
+ document.removeEventListener('mouseup', handleClickOutside)
136
149
  document.removeEventListener('keydown', handleKeyDown)
137
150
  }
138
151
  }, [_visible])
@@ -143,6 +156,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
143
156
  }
144
157
 
145
158
  setVisible(false)
159
+
146
160
  return onClose && onClose()
147
161
  }
148
162
 
@@ -163,7 +177,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
163
177
 
164
178
  setTimeout(
165
179
  () => {
166
- modalRef.current?.focus()
180
+ focus && modalRef.current?.focus()
167
181
  },
168
182
  transition ? duration : 0,
169
183
  )
@@ -225,10 +239,13 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
225
239
  className,
226
240
  )}
227
241
  tabIndex={-1}
228
- role="dialog"
242
+ {...(_visible
243
+ ? { 'aria-modal': true, role: 'dialog' }
244
+ : { 'aria-hidden': 'true' })}
229
245
  style={{
230
246
  ...(state !== 'exited' && { display: 'block' }),
231
247
  }}
248
+ {...rest}
232
249
  ref={forkedRef}
233
250
  >
234
251
  <CModalDialog
@@ -237,9 +254,7 @@ export const CModal = forwardRef<HTMLDivElement, CModalProps>(
237
254
  scrollable={scrollable}
238
255
  size={size}
239
256
  >
240
- <CModalContent {...rest} ref={modalContentRef}>
241
- {children}
242
- </CModalContent>
257
+ <CModalContent ref={modalContentRef}>{children}</CModalContent>
243
258
  </CModalDialog>
244
259
  </div>
245
260
  </CModalContext.Provider>
@@ -262,6 +277,7 @@ CModal.propTypes = {
262
277
  children: PropTypes.node,
263
278
  className: PropTypes.string,
264
279
  duration: PropTypes.number,
280
+ focus: PropTypes.bool,
265
281
  fullscreen: PropTypes.oneOfType([
266
282
  PropTypes.bool,
267
283
  PropTypes.oneOf<'sm' | 'md' | 'lg' | 'xl' | 'xxl'>(['sm', 'md', 'lg', 'xl', 'xxl']),
@@ -243,7 +243,7 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
243
243
  if (
244
244
  allowCreateOptions &&
245
245
  filteredOptions.some(
246
- (option) => option.text && option.text.toLowerCase() === searchValue.toLowerCase(),
246
+ (option) => option.label && option.label.toLowerCase() === searchValue.toLowerCase(),
247
247
  )
248
248
  ) {
249
249
  return false
@@ -354,7 +354,7 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
354
354
  setSelected([
355
355
  ...selected,
356
356
  filteredOptions.find(
357
- (option) => String(option.text).toLowerCase() === searchValue.toLowerCase(),
357
+ (option) => String(option.label).toLowerCase() === searchValue.toLowerCase(),
358
358
  ) as Option,
359
359
  ])
360
360
  }
@@ -491,7 +491,7 @@ export const CMultiSelect = forwardRef<HTMLDivElement, CMultiSelectProps>(
491
491
  placeholder: `${selected.length} ${selectionTypeCounterText}`,
492
492
  })}
493
493
  {...(selected.length > 0 &&
494
- !multiple && { placeholder: selected.map((option) => option.text)[0] })}
494
+ !multiple && { placeholder: selected.map((option) => option.label)[0] })}
495
495
  {...(multiple &&
496
496
  selected.length > 0 &&
497
497
  selectionType !== 'counter' && { size: searchValue.length + 2 })}
@@ -18,7 +18,7 @@ const createNativeOptions = (options: Option[]) =>
18
18
  </optgroup>
19
19
  ) : (
20
20
  <option value={option.value} key={index} disabled={option.disabled}>
21
- {option.text}
21
+ {option.label}
22
22
  </option>
23
23
  ),
24
24
  )
@@ -77,7 +77,7 @@ export const CMultiSelectOptions = forwardRef<HTMLDivElement, CMultiSelectOption
77
77
  onKeyDown={(event) => handleKeyDown(event, option as Option)}
78
78
  tabIndex={0}
79
79
  >
80
- {optionsTemplate ? optionsTemplate(option as Option) : option.text}
80
+ {optionsTemplate ? optionsTemplate(option as Option) : option.label}
81
81
  </div>
82
82
  ) : (
83
83
  <div className="form-multi-select-optgroup-label" key={index}>
@@ -48,7 +48,7 @@ export const CMultiSelectSelection = forwardRef<HTMLSpanElement, CMultiSelectSel
48
48
  if (selectionType === 'tags') {
49
49
  return (
50
50
  <span className="form-multi-select-tag" key={index}>
51
- {option.text}
51
+ {option.label}
52
52
  {!option.disabled && (
53
53
  <button
54
54
  className="form-multi-select-tag-delete"
@@ -65,11 +65,11 @@ export const CMultiSelectSelection = forwardRef<HTMLSpanElement, CMultiSelectSel
65
65
  selectionType === 'text' &&
66
66
  selected.map((option, index) => (
67
67
  <span key={index}>
68
- {option.text}
68
+ {option.label}
69
69
  {index === selected.length - 1 ? '' : ','}&nbsp;
70
70
  </span>
71
71
  ))}
72
- {!multiple && !search && selected.map((option) => option.text)[0]}
72
+ {!multiple && !search && selected.map((option) => option.label)[0]}
73
73
  {children}
74
74
  </span>
75
75
  )
@@ -2,7 +2,7 @@ export type Option = {
2
2
  custom?: boolean
3
3
  disabled?: boolean
4
4
  selected?: boolean
5
- text: string // TODO: change to label in v5
5
+ label: string
6
6
  value: number | string
7
7
  [key: string]: number | string | any
8
8
  }
@@ -15,7 +15,7 @@ export type OptionsGroup = {
15
15
 
16
16
  export type SelectedOption = {
17
17
  disabled?: boolean
18
- text: string
18
+ label: string
19
19
  value: number | string
20
20
  [key: string]: number | string | any
21
21
  }
@@ -1,7 +1,7 @@
1
1
  import type { Option, OptionsGroup, SelectedOption } from './types'
2
2
 
3
- export const createOption = (text: string, options: (Option | OptionsGroup)[]) => {
4
- const value = text.toLowerCase().replace(/\s/g, '-')
3
+ export const createOption = (label: string, options: (Option | OptionsGroup)[]) => {
4
+ const value = label.toLowerCase().replace(/\s/g, '-')
5
5
  let uniqueValue = value
6
6
  let i = 1
7
7
 
@@ -13,7 +13,7 @@ export const createOption = (text: string, options: (Option | OptionsGroup)[]) =
13
13
  return [
14
14
  {
15
15
  value: uniqueValue,
16
- text,
16
+ label,
17
17
  custom: true,
18
18
  },
19
19
  ]
@@ -28,10 +28,10 @@ export const filterOptionsList = (search: string, _options: (Option | OptionsGro
28
28
  option.options &&
29
29
  option.options.filter(
30
30
  (option: Option) =>
31
- option.text && option.text.toLowerCase().includes(search.toLowerCase()),
31
+ option.lable && option.label.toLowerCase().includes(search.toLowerCase()),
32
32
  )
33
33
  if (
34
- (option.text && option.text.toLowerCase().includes(search.toLowerCase())) ||
34
+ (option.lable && option.label.toLowerCase().includes(search.toLowerCase())) ||
35
35
  (options && options.length > 0)
36
36
  ) {
37
37
  optionsList.push(Object.assign({}, option, options && options.length > 0 && { options }))