@coreui/react-pro 4.1.4 → 4.2.0-rc.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 (162) hide show
  1. package/README.md +1 -1
  2. package/dist/components/Types.d.ts +1 -1
  3. package/dist/components/accordion/index.d.ts +7 -0
  4. package/dist/components/alert/index.d.ts +4 -0
  5. package/dist/components/avatar/index.d.ts +2 -0
  6. package/dist/components/backdrop/index.d.ts +2 -0
  7. package/dist/components/badge/index.d.ts +2 -0
  8. package/dist/components/breadcrumb/index.d.ts +3 -0
  9. package/dist/components/button/index.d.ts +2 -0
  10. package/dist/components/button-group/index.d.ts +3 -0
  11. package/dist/components/calendar/CCalendar.d.ts +113 -0
  12. package/dist/components/callout/index.d.ts +2 -0
  13. package/dist/components/card/index.d.ts +12 -0
  14. package/dist/components/carousel/index.d.ts +4 -0
  15. package/dist/components/close-button/index.d.ts +2 -0
  16. package/dist/components/collapse/index.d.ts +2 -0
  17. package/dist/components/datepicker/CDatePicker.d.ts +13 -0
  18. package/dist/components/datepicker/index.d.ts +2 -0
  19. package/dist/components/daterangepicker/CDateRangePicker.d.ts +65 -0
  20. package/dist/components/daterangepicker/index.d.ts +2 -0
  21. package/dist/components/dropdown/CDropdown.d.ts +10 -1
  22. package/dist/components/dropdown/CDropdownToggle.d.ts +4 -0
  23. package/dist/components/dropdown/index.d.ts +8 -0
  24. package/dist/components/footer/index.d.ts +2 -0
  25. package/dist/components/form/CForm.d.ts +2 -2
  26. package/dist/components/form/CFormCheck.d.ts +2 -1
  27. package/dist/components/form/CFormControlValidation.d.ts +46 -0
  28. package/dist/components/form/CFormControlWrapper.d.ts +31 -0
  29. package/dist/components/form/CFormInput.d.ts +2 -9
  30. package/dist/components/form/CFormRange.d.ts +7 -1
  31. package/dist/components/form/CFormSelect.d.ts +3 -10
  32. package/dist/components/form/CFormTextarea.d.ts +2 -9
  33. package/dist/components/form/index.d.ts +14 -0
  34. package/dist/components/grid/index.d.ts +4 -0
  35. package/dist/components/header/index.d.ts +7 -0
  36. package/dist/components/image/index.d.ts +2 -0
  37. package/dist/components/index.d.ts +41 -0
  38. package/dist/components/link/index.d.ts +2 -0
  39. package/dist/components/list-group/index.d.ts +3 -0
  40. package/dist/components/loading-button/index.d.ts +2 -0
  41. package/dist/components/modal/CModal.d.ts +3 -0
  42. package/dist/components/modal/index.d.ts +8 -0
  43. package/dist/components/multi-select/index.d.ts +2 -0
  44. package/dist/components/nav/index.d.ts +7 -0
  45. package/dist/components/navbar/index.d.ts +6 -0
  46. package/dist/components/offcanvas/index.d.ts +5 -0
  47. package/dist/components/pagination/index.d.ts +4 -0
  48. package/dist/components/picker/CPicker.d.ts +78 -0
  49. package/dist/components/placeholder/index.d.ts +2 -0
  50. package/dist/components/popover/CPopover.d.ts +2 -2
  51. package/dist/components/popover/index.d.ts +2 -0
  52. package/dist/components/progress/index.d.ts +3 -0
  53. package/dist/components/sidebar/index.d.ts +7 -0
  54. package/dist/components/smart-table/index.d.ts +2 -0
  55. package/dist/components/spinner/index.d.ts +2 -0
  56. package/dist/components/table/index.d.ts +9 -0
  57. package/dist/components/tabs/index.d.ts +3 -0
  58. package/dist/components/timepicker/CTimePicker.d.ts +45 -0
  59. package/dist/components/timepicker/CTimePickerRollCol.d.ts +11 -0
  60. package/dist/components/timepicker/index.d.ts +2 -0
  61. package/dist/components/toast/index.d.ts +6 -0
  62. package/dist/components/tooltip/CTooltip.d.ts +2 -2
  63. package/dist/components/tooltip/index.d.ts +2 -0
  64. package/dist/index.d.ts +0 -125
  65. package/dist/index.es.js +3268 -1339
  66. package/dist/index.es.js.map +1 -1
  67. package/dist/index.js +3513 -1582
  68. package/dist/index.js.map +1 -1
  69. package/dist/utils/calendar.d.ts +23 -0
  70. package/dist/utils/hooks/useStateWithCallback.d.ts +2 -1
  71. package/dist/utils/time.d.ts +21 -0
  72. package/package.json +12 -11
  73. package/src/components/Types.tsx +2 -2
  74. package/src/components/accordion/CAccordionButton.tsx +2 -1
  75. package/src/components/accordion/__tests__/__snapshots__/CAccordionButton.spec.tsx.snap +2 -0
  76. package/src/components/accordion/__tests__/__snapshots__/CAccordionHeader.spec.tsx.snap +2 -0
  77. package/src/components/accordion/index.ts +15 -0
  78. package/src/components/alert/CAlert.tsx +14 -3
  79. package/src/components/alert/index.ts +5 -0
  80. package/src/components/avatar/index.ts +3 -0
  81. package/src/components/backdrop/CBackdrop.tsx +10 -3
  82. package/src/components/backdrop/index.ts +3 -0
  83. package/src/components/badge/index.ts +3 -0
  84. package/src/components/breadcrumb/index.ts +4 -0
  85. package/src/components/button/index.ts +3 -0
  86. package/src/components/button-group/index.ts +4 -0
  87. package/src/components/calendar/CCalendar.tsx +559 -0
  88. package/src/components/calendar/__tests__/CCalendar.spec.tsx +9 -0
  89. package/src/components/calendar/__tests__/__snapshots__/CCalendar.spec.tsx.snap +573 -0
  90. package/src/components/callout/index.ts +3 -0
  91. package/src/components/card/index.ts +25 -0
  92. package/src/components/carousel/index.ts +5 -0
  93. package/src/components/close-button/index.ts +3 -0
  94. package/src/components/collapse/CCollapse.tsx +1 -0
  95. package/src/components/collapse/index.ts +3 -0
  96. package/src/components/datepicker/CDatePicker.tsx +50 -0
  97. package/src/components/datepicker/__tests__/CDatePicker.spec.tsx +9 -0
  98. package/src/components/datepicker/__tests__/__snapshots__/CDatePicker.spec.tsx.snap +617 -0
  99. package/src/components/datepicker/index.ts +3 -0
  100. package/src/components/daterangepicker/CDateRangePicker.tsx +432 -0
  101. package/src/components/daterangepicker/__tests__/CDateRangePicker.spec.tsx +9 -0
  102. package/src/components/daterangepicker/__tests__/__snapshots__/CDateRangePicker.spec.tsx.snap +1201 -0
  103. package/src/components/daterangepicker/index.ts +3 -0
  104. package/src/components/dropdown/CDropdown.tsx +19 -24
  105. package/src/components/dropdown/CDropdownItem.tsx +1 -1
  106. package/src/components/dropdown/CDropdownMenu.tsx +55 -3
  107. package/src/components/dropdown/CDropdownToggle.tsx +28 -5
  108. package/src/components/dropdown/index.ts +17 -0
  109. package/src/components/footer/index.ts +3 -0
  110. package/src/components/form/CForm.tsx +2 -2
  111. package/src/components/form/CFormCheck.tsx +32 -7
  112. package/src/components/form/CFormControlValidation.tsx +97 -0
  113. package/src/components/form/CFormControlWrapper.tsx +85 -0
  114. package/src/components/form/CFormInput.tsx +47 -18
  115. package/src/components/form/CFormRange.tsx +18 -4
  116. package/src/components/form/CFormSelect.tsx +60 -32
  117. package/src/components/form/CFormTextarea.tsx +45 -17
  118. package/src/components/form/index.ts +29 -0
  119. package/src/components/grid/index.ts +5 -0
  120. package/src/components/header/index.ts +8 -0
  121. package/src/components/image/index.ts +3 -0
  122. package/src/components/index.ts +41 -0
  123. package/src/components/link/index.ts +3 -0
  124. package/src/components/list-group/index.ts +4 -0
  125. package/src/components/loading-button/index.ts +3 -0
  126. package/src/components/modal/CModal.tsx +3 -2
  127. package/src/components/modal/index.ts +9 -0
  128. package/src/components/multi-select/CMultiSelect.tsx +45 -38
  129. package/src/components/multi-select/index.ts +3 -0
  130. package/src/components/nav/CNavGroup.tsx +1 -0
  131. package/src/components/nav/index.ts +8 -0
  132. package/src/components/navbar/index.ts +7 -0
  133. package/src/components/offcanvas/COffcanvas.tsx +1 -0
  134. package/src/components/offcanvas/index.ts +6 -0
  135. package/src/components/pagination/index.ts +5 -0
  136. package/src/components/picker/CPicker.tsx +207 -0
  137. package/src/components/picker/__tests__/CPicker.spec.tsx +9 -0
  138. package/src/components/picker/__tests__/__snapshots__/CPicker.spec.tsx.snap +23 -0
  139. package/src/components/placeholder/index.ts +3 -0
  140. package/src/components/popover/CPopover.tsx +78 -70
  141. package/src/components/popover/index.ts +3 -0
  142. package/src/components/progress/index.ts +4 -0
  143. package/src/components/sidebar/index.ts +8 -0
  144. package/src/components/smart-table/index.ts +3 -0
  145. package/src/components/spinner/index.ts +3 -0
  146. package/src/components/table/index.ts +19 -0
  147. package/src/components/tabs/CTabPane.tsx +7 -3
  148. package/src/components/tabs/index.ts +4 -0
  149. package/src/components/timepicker/CTimePicker.tsx +313 -0
  150. package/src/components/timepicker/CTimePickerRollCol.tsx +63 -0
  151. package/src/components/timepicker/__tests__/CTimePicker.spec.tsx +9 -0
  152. package/src/components/timepicker/index.ts +3 -0
  153. package/src/components/toast/CToast.tsx +6 -1
  154. package/src/components/toast/index.ts +7 -0
  155. package/src/components/tooltip/CTooltip.tsx +68 -60
  156. package/src/components/tooltip/index.ts +3 -0
  157. package/src/index.ts +0 -252
  158. package/src/utils/calendar.ts +270 -0
  159. package/src/utils/hooks/useStateWithCallback.ts +6 -3
  160. package/src/utils/time.ts +84 -0
  161. package/dist/components/dropdown/CDropdownToggleCustom.d.ts +0 -15
  162. package/src/components/dropdown/CDropdownToggleCustom.tsx +0 -81
@@ -0,0 +1,313 @@
1
+ /* eslint-disable react/prop-types */
2
+ import React, { forwardRef, ReactNode, useEffect, useRef, useState } from 'react'
3
+ import PropTypes from 'prop-types'
4
+ import classNames from 'classnames'
5
+
6
+ import { CFormInput } from '../form/CFormInput'
7
+ import { CFormSelect } from '../form/CFormSelect'
8
+ import { CInputGroup } from '../form/CInputGroup'
9
+ import { CInputGroupText } from '../form/CInputGroupText'
10
+
11
+ import { CTimePickerRollCol } from './CTimePickerRollCol'
12
+ import { CPicker, CPickerProps } from './../picker/CPicker'
13
+ import {
14
+ convert12hTo24h,
15
+ convertTimeToDate,
16
+ getAmPm,
17
+ getListOfHours,
18
+ getListOfMinutes,
19
+ getListOfSeconds,
20
+ getSelectedHour,
21
+ getSelectedMinutes,
22
+ getSelectedSeconds,
23
+ isAmPm,
24
+ isValidTime,
25
+ } from '../../utils/time'
26
+
27
+ export interface CTimePickerProps
28
+ extends Omit<
29
+ CPickerProps,
30
+ 'autoClose' | 'component' | 'dark' | 'placeholder' | 'variant' | 'onChange'
31
+ > {
32
+ /**
33
+ * A string of all className you want applied to the component.
34
+ */
35
+ className?: string
36
+ /**
37
+ * Toggle visibility or set the content of the cleaner button.
38
+ */
39
+ cleaner?: ReactNode | boolean
40
+ /**
41
+ * Toggle visibility or set the content of the input indicator.
42
+ */
43
+ indicator?: ReactNode | boolean
44
+ /**
45
+ * Toggle the readonly state for the component.
46
+ */
47
+ inputReadOnly?: boolean
48
+ /**
49
+ * Sets the default locale for components. If not set, it is inherited from the browser.
50
+ */
51
+ locale?: string
52
+ /**
53
+ * Callback fired when the time changed.
54
+ */
55
+ onTimeChange?: (timeString: string, localeTimeString: string, date: Date) => void
56
+ /**
57
+ * Specifies a short hint that is visible in the input.
58
+ */
59
+ placeholder?: string
60
+ /**
61
+ * Size the component small or large.
62
+ */
63
+ size?: 'sm' | 'lg'
64
+ /**
65
+ * Initial selected time.
66
+ */
67
+ time?: Date | string | null
68
+ /**
69
+ * Set the time picker variant to a roll or select.
70
+ */
71
+ variant?: 'roll' | 'select'
72
+ }
73
+
74
+ export const CTimePicker = forwardRef<HTMLDivElement | HTMLLIElement, CTimePickerProps>(
75
+ (
76
+ {
77
+ className,
78
+ cleaner = true,
79
+ container = 'dropdown',
80
+ disabled,
81
+ footer = true,
82
+ indicator = true,
83
+ inputReadOnly,
84
+ locale = 'default',
85
+ onTimeChange,
86
+ onHide,
87
+ onShow,
88
+ placeholder = 'Select time',
89
+ size,
90
+ time,
91
+ variant = 'roll',
92
+ ...rest
93
+ },
94
+ ref,
95
+ ) => {
96
+ const inputRef = useRef<HTMLInputElement>(null)
97
+ const [date, setDate] = useState<Date | null>(convertTimeToDate(time))
98
+ const [initialDate, setInitialDate] = useState<Date | null>(null)
99
+ const [_ampm, setAmPm] = useState<'am' | 'pm'>(date ? getAmPm(new Date(date), locale) : 'am')
100
+
101
+ useEffect(() => {
102
+ setDate(convertTimeToDate(time))
103
+ }, [time])
104
+
105
+ useEffect(() => {
106
+ if (inputRef.current) {
107
+ inputRef.current.value = date ? date.toLocaleTimeString(locale) : ''
108
+ }
109
+
110
+ date && setAmPm(getAmPm(new Date(date), locale))
111
+ }, [date])
112
+
113
+ const handleClear = (event: React.MouseEvent<HTMLElement>) => {
114
+ event.stopPropagation()
115
+ setDate(null)
116
+ }
117
+
118
+ const handleTimeChange = (set: 'hours' | 'minutes' | 'seconds' | 'toggle', value: string) => {
119
+ const _date = date || new Date('1970-01-01')
120
+
121
+ if (set === 'toggle') {
122
+ if (value === 'am') {
123
+ _date.setHours(_date.getHours() - 12)
124
+ }
125
+ if (value === 'pm') {
126
+ _date.setHours(_date.getHours() + 12)
127
+ }
128
+ }
129
+
130
+ if (set === 'hours') {
131
+ if (isAmPm(locale)) {
132
+ _date.setHours(convert12hTo24h(_ampm, parseInt(value)))
133
+ } else {
134
+ _date.setHours(parseInt(value))
135
+ }
136
+ }
137
+
138
+ if (set === 'minutes') {
139
+ _date.setMinutes(parseInt(value))
140
+ }
141
+
142
+ if (set === 'seconds') {
143
+ _date.setSeconds(parseInt(value))
144
+ }
145
+
146
+ setDate(new Date(_date))
147
+ onTimeChange && onTimeChange(_date.toTimeString(), _date.toLocaleTimeString(), _date)
148
+ }
149
+
150
+ const InputGroup = () => (
151
+ <CInputGroup className="picker-input-group" size={size}>
152
+ <CFormInput
153
+ disabled={disabled}
154
+ onChange={(event) =>
155
+ isValidTime(event.target.value) && setDate(convertTimeToDate(event.target.value))
156
+ }
157
+ placeholder={placeholder}
158
+ readOnly={inputReadOnly}
159
+ ref={inputRef}
160
+ />
161
+ {(indicator || cleaner) && (
162
+ <CInputGroupText>
163
+ {indicator && (
164
+ <span className="picker-input-group-indicator">
165
+ {typeof indicator === 'boolean' ? (
166
+ <span className="picker-input-group-icon time-picker-input-icon" />
167
+ ) : (
168
+ indicator
169
+ )}
170
+ </span>
171
+ )}
172
+ {cleaner && date && (
173
+ <span
174
+ className="picker-input-group-cleaner"
175
+ role="button"
176
+ onClick={(event) => handleClear(event)}
177
+ >
178
+ {typeof cleaner === 'boolean' ? (
179
+ <span className="picker-input-group-icon time-picker-cleaner-icon" />
180
+ ) : (
181
+ cleaner
182
+ )}
183
+ </span>
184
+ )}
185
+ </CInputGroupText>
186
+ )}
187
+ </CInputGroup>
188
+ )
189
+
190
+ const TimePickerSelect = () => {
191
+ return (
192
+ <>
193
+ <span className="time-picker-inline-icon" />
194
+ <CFormSelect
195
+ disabled={disabled}
196
+ options={getListOfHours(locale).map((option) => {
197
+ return {
198
+ value: option.value.toString(),
199
+ label: option.label,
200
+ }
201
+ })}
202
+ onChange={(event: React.ChangeEvent<HTMLSelectElement>) =>
203
+ handleTimeChange('hours', event.target.value)
204
+ }
205
+ value={getSelectedHour(date, locale)}
206
+ />
207
+ <>:</>
208
+ <CFormSelect
209
+ disabled={disabled}
210
+ // @ts-expect-error the getListOfMinutes function returns corect type
211
+ options={getListOfMinutes(locale, true)}
212
+ onChange={(event: React.ChangeEvent<HTMLSelectElement>) =>
213
+ handleTimeChange('minutes', event.target.value)
214
+ }
215
+ value={getSelectedMinutes(date)}
216
+ />
217
+ <>:</>
218
+ <CFormSelect
219
+ disabled={disabled}
220
+ // @ts-expect-error the getListOfSeconds function returns corect type
221
+ options={getListOfSeconds(locale, true)}
222
+ onChange={(event: React.ChangeEvent<HTMLSelectElement>) =>
223
+ handleTimeChange('seconds', event.target.value)
224
+ }
225
+ value={getSelectedSeconds(date)}
226
+ />
227
+ {isAmPm(locale) && (
228
+ <CFormSelect
229
+ disabled={disabled}
230
+ options={[
231
+ { value: 'am', label: 'AM' },
232
+ { value: 'pm', label: 'PM' },
233
+ ]}
234
+ onChange={(event: React.ChangeEvent<HTMLSelectElement>) =>
235
+ handleTimeChange('toggle', event.target.value)
236
+ }
237
+ value={_ampm}
238
+ />
239
+ )}
240
+ </>
241
+ )
242
+ }
243
+
244
+ const TimePickerRoll = () => (
245
+ <>
246
+ <CTimePickerRollCol
247
+ elements={getListOfHours(locale)}
248
+ onClick={(index: number) => handleTimeChange('hours', index.toString())}
249
+ selected={getSelectedHour(date, locale)}
250
+ />
251
+ <CTimePickerRollCol
252
+ elements={getListOfMinutes(locale)}
253
+ onClick={(index: number) => handleTimeChange('minutes', index.toString())}
254
+ selected={getSelectedMinutes(date)}
255
+ />
256
+ <CTimePickerRollCol
257
+ elements={getListOfSeconds(locale)}
258
+ onClick={(index: number) => handleTimeChange('seconds', index.toString())}
259
+ selected={getSelectedSeconds(date)}
260
+ />
261
+ {isAmPm(locale) && (
262
+ <CTimePickerRollCol
263
+ elements={[
264
+ { value: 'am', label: 'AM' },
265
+ { value: 'pm', label: 'PM' },
266
+ ]}
267
+ onClick={(value: string) => handleTimeChange('toggle', value)}
268
+ selected={_ampm}
269
+ />
270
+ )}
271
+ </>
272
+ )
273
+
274
+ const _className = classNames('time-picker', className)
275
+
276
+ return (
277
+ <CPicker
278
+ className={_className}
279
+ container={container}
280
+ disabled={disabled}
281
+ footer={footer}
282
+ onCancel={() => initialDate && setDate(new Date(initialDate))}
283
+ onHide={() => onHide && onHide()}
284
+ onShow={() => {
285
+ date && setInitialDate(new Date(date))
286
+ onShow && onShow()
287
+ }}
288
+ toggler={InputGroup()}
289
+ {...rest}
290
+ ref={ref}
291
+ >
292
+ <div
293
+ className={classNames('time-picker-body', {
294
+ ['time-picker-roll']: variant === 'roll',
295
+ })}
296
+ >
297
+ {variant === 'select' ? <TimePickerSelect /> : TimePickerRoll()}
298
+ </div>
299
+ </CPicker>
300
+ )
301
+ },
302
+ )
303
+
304
+ CTimePicker.propTypes = {
305
+ ...CPicker.propTypes,
306
+ className: PropTypes.string,
307
+ locale: PropTypes.string,
308
+ onTimeChange: PropTypes.func,
309
+ time: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),
310
+ variant: PropTypes.oneOf(['roll', 'select']),
311
+ }
312
+
313
+ CTimePicker.displayName = 'CTimePicker'
@@ -0,0 +1,63 @@
1
+ import React, { forwardRef, useEffect, useRef } from 'react'
2
+ import PropTypes from 'prop-types'
3
+ import classNames from 'classnames'
4
+
5
+ import { useForkedRef } from '../../utils/hooks'
6
+
7
+ export interface Element {
8
+ value: number | string
9
+ label: number | string
10
+ }
11
+
12
+ export interface CTimePickerRollColProps {
13
+ elements: Element[]
14
+ onClick?: (value: number | string) => void
15
+ selected?: number | string | null
16
+ }
17
+
18
+ export const CTimePickerRollCol = forwardRef<HTMLDivElement, CTimePickerRollColProps>(
19
+ ({ elements, onClick, selected }, ref) => {
20
+ const init = useRef(true)
21
+ const colRef = useRef<HTMLDivElement>(null)
22
+ const forkedRef = useForkedRef(ref, colRef)
23
+
24
+ useEffect(() => {
25
+ const nodeEl = colRef.current?.querySelector('.selected')
26
+ if (nodeEl && nodeEl instanceof HTMLElement) {
27
+ colRef.current?.scrollTo({
28
+ top: nodeEl.offsetTop,
29
+ behavior: init.current ? 'auto' : 'smooth',
30
+ })
31
+ }
32
+
33
+ init.current = false
34
+ }, [selected])
35
+
36
+ return (
37
+ <div className="time-picker-roll-col" ref={forkedRef}>
38
+ {elements.map((element, index) => {
39
+ return (
40
+ <div
41
+ className={classNames('time-picker-roll-cell', {
42
+ selected: element.value === selected,
43
+ })}
44
+ key={index}
45
+ onClick={() => onClick && onClick(element.value)}
46
+ role="button"
47
+ >
48
+ {element.label}
49
+ </div>
50
+ )
51
+ })}
52
+ </div>
53
+ )
54
+ },
55
+ )
56
+
57
+ CTimePickerRollCol.propTypes = {
58
+ elements: PropTypes.array.isRequired,
59
+ onClick: PropTypes.func,
60
+ selected: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
61
+ }
62
+
63
+ CTimePickerRollCol.displayName = 'CTimePickerRollCol'
@@ -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 { CTimePicker } from '../CTimePicker'
5
+
6
+ test('loads and displays CTimePicker component', async () => {
7
+ const { container } = render(<CTimePicker />)
8
+ expect(container).toMatchSnapshot()
9
+ })
@@ -0,0 +1,3 @@
1
+ import { CTimePicker } from './CTimePicker'
2
+
3
+ export { CTimePicker }
@@ -12,6 +12,8 @@ import classNames from 'classnames'
12
12
 
13
13
  import { Colors, colorPropType } from '../Types'
14
14
 
15
+ import { useForkedRef } from '../../utils/hooks'
16
+
15
17
  export interface CToastProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
16
18
  /**
17
19
  * Apply a CSS fade transition to the toast.
@@ -82,6 +84,8 @@ export const CToast = forwardRef<HTMLDivElement, CToastProps>(
82
84
  },
83
85
  ref,
84
86
  ) => {
87
+ const toastRef = useRef()
88
+ const forkedRef = useForkedRef(ref, toastRef)
85
89
  const [_visible, setVisible] = useState(false)
86
90
  const timeout = useRef<number>()
87
91
 
@@ -133,6 +137,7 @@ export const CToast = forwardRef<HTMLDivElement, CToastProps>(
133
137
  return (
134
138
  <Transition
135
139
  in={_visible}
140
+ nodeRef={toastRef}
136
141
  onEnter={() => onShow && onShow(index ? index : null)}
137
142
  onExited={() => onClose && onClose(index ? index : null)}
138
143
  timeout={250}
@@ -151,7 +156,7 @@ export const CToast = forwardRef<HTMLDivElement, CToastProps>(
151
156
  onMouseLeave={() => _autohide}
152
157
  {...rest}
153
158
  key={key}
154
- ref={ref}
159
+ ref={forkedRef}
155
160
  >
156
161
  {children}
157
162
  </div>
@@ -0,0 +1,7 @@
1
+ import { CToast } from './CToast'
2
+ import { CToastBody } from './CToastBody'
3
+ import { CToastClose } from './CToastClose'
4
+ import { CToastHeader } from './CToastHeader'
5
+ import { CToaster } from './CToaster'
6
+
7
+ export { CToast, CToastBody, CToastClose, CToastHeader, CToaster }
@@ -1,4 +1,4 @@
1
- import React, { FC, ReactElement, ReactNode, useState } from 'react'
1
+ import React, { FC, ReactNode, useRef, useState } from 'react'
2
2
  import { createPortal } from 'react-dom'
3
3
  import PropTypes from 'prop-types'
4
4
  import classNames from 'classnames'
@@ -9,7 +9,7 @@ import { Transition } from 'react-transition-group'
9
9
  import { Triggers, triggerPropType } from '../Types'
10
10
 
11
11
  export interface CTooltipProps {
12
- children: ReactElement
12
+ children: any
13
13
  /**
14
14
  * Content node for your component.
15
15
  */
@@ -48,6 +48,7 @@ export const CTooltip: FC<CTooltipProps> = ({
48
48
  visible,
49
49
  ...rest
50
50
  }) => {
51
+ const tooltipRef = useRef()
51
52
  const [_visible, setVisible] = useState(visible)
52
53
 
53
54
  const getTransitionClass = (state: string) => {
@@ -62,64 +63,71 @@ export const CTooltip: FC<CTooltipProps> = ({
62
63
 
63
64
  return (
64
65
  <Manager>
65
- <Reference>
66
- {({ ref }) =>
67
- React.cloneElement(children, {
68
- ref: ref,
69
- ...((trigger === 'click' || trigger.includes('click')) && {
70
- onClick: () => setVisible(!_visible),
71
- }),
72
- ...((trigger === 'focus' || trigger.includes('focus')) && {
73
- onFocus: () => setVisible(true),
74
- onBlur: () => setVisible(false),
75
- }),
76
- ...((trigger === 'hover' || trigger.includes('hover')) && {
77
- onMouseEnter: () => setVisible(true),
78
- onMouseLeave: () => setVisible(false),
79
- }),
80
- })
81
- }
82
- </Reference>
83
- {typeof window !== 'undefined' &&
84
- createPortal(
85
- <Transition
86
- in={_visible}
87
- mountOnEnter
88
- onEnter={onShow}
89
- onExit={onHide}
90
- timeout={{
91
- enter: 0,
92
- exit: 200,
93
- }}
94
- unmountOnExit
95
- >
96
- {(state) => {
97
- const transitionClass = getTransitionClass(state)
98
- return (
99
- <Popper placement={placement}>
100
- {({ arrowProps, style, ref }) => (
101
- <div
102
- className={classNames(
103
- `tooltip bs-tooltip-${
104
- placement === 'left' ? 'start' : placement === 'right' ? 'end' : placement
105
- }`,
106
- transitionClass,
107
- )}
108
- ref={ref}
109
- role="tooltip"
110
- style={style}
111
- {...rest}
112
- >
113
- <div className="tooltip-arrow" {...arrowProps}></div>
114
- <div className="tooltip-inner">{content}</div>
115
- </div>
116
- )}
117
- </Popper>
118
- )
119
- }}
120
- </Transition>,
121
- document.body,
122
- )}
66
+ <>
67
+ <Reference>
68
+ {({ ref }) =>
69
+ React.cloneElement(children, {
70
+ ref: ref,
71
+ ...((trigger === 'click' || trigger.includes('click')) && {
72
+ onClick: () => setVisible(!_visible),
73
+ }),
74
+ ...((trigger === 'focus' || trigger.includes('focus')) && {
75
+ onFocus: () => setVisible(true),
76
+ onBlur: () => setVisible(false),
77
+ }),
78
+ ...((trigger === 'hover' || trigger.includes('hover')) && {
79
+ onMouseEnter: () => setVisible(true),
80
+ onMouseLeave: () => setVisible(false),
81
+ }),
82
+ })
83
+ }
84
+ </Reference>
85
+ {typeof window !== 'undefined' &&
86
+ createPortal(
87
+ <Transition
88
+ in={_visible}
89
+ mountOnEnter
90
+ nodeRef={tooltipRef}
91
+ onEnter={onShow}
92
+ onExit={onHide}
93
+ timeout={{
94
+ enter: 0,
95
+ exit: 200,
96
+ }}
97
+ unmountOnExit
98
+ >
99
+ {(state) => {
100
+ const transitionClass = getTransitionClass(state)
101
+ return (
102
+ <Popper placement={placement}>
103
+ {({ arrowProps, style, ref }) => (
104
+ <div
105
+ className={classNames(
106
+ `tooltip bs-tooltip-${
107
+ placement === 'left'
108
+ ? 'start'
109
+ : placement === 'right'
110
+ ? 'end'
111
+ : placement
112
+ }`,
113
+ transitionClass,
114
+ )}
115
+ ref={ref}
116
+ role="tooltip"
117
+ style={style}
118
+ {...rest}
119
+ >
120
+ <div className="tooltip-arrow" {...arrowProps}></div>
121
+ <div className="tooltip-inner">{content}</div>
122
+ </div>
123
+ )}
124
+ </Popper>
125
+ )
126
+ }}
127
+ </Transition>,
128
+ document.body,
129
+ )}
130
+ </>
123
131
  </Manager>
124
132
  )
125
133
  }
@@ -0,0 +1,3 @@
1
+ import { CTooltip } from './CTooltip'
2
+
3
+ export { CTooltip }