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