@coreui/react-pro 4.13.1 → 4.14.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.
- package/README.md +1 -1
- package/dist/components/date-range-picker/CDateRangePicker.d.ts +18 -0
- package/dist/components/popover/CPopover.d.ts +2 -2
- package/dist/components/tooltip/CTooltip.d.ts +2 -2
- package/dist/hooks/index.d.ts +3 -1
- package/dist/hooks/useDebouncedCallback.d.ts +1 -0
- package/dist/hooks/useIsVisible.d.ts +2 -0
- package/dist/index.es.js +97 -61
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +97 -59
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/date-range-picker/CDateRangePicker.tsx +45 -21
- package/src/components/popover/CPopover.tsx +126 -117
- package/src/components/time-picker/CTimePicker.tsx +34 -34
- package/src/components/time-picker/CTimePickerRollCol.tsx +7 -4
- package/src/components/tooltip/CTooltip.tsx +131 -114
- package/src/hooks/index.ts +3 -1
- package/src/hooks/useDebouncedCallback.ts +18 -0
- package/src/hooks/useIsVisible.ts +14 -0
package/package.json
CHANGED
|
@@ -11,6 +11,7 @@ import { CFormControlWrapper, CFormControlWrapperProps } from '../form/CFormCont
|
|
|
11
11
|
import { CPicker, CPickerProps } from '../picker/CPicker'
|
|
12
12
|
import { CTimePicker } from '../time-picker/CTimePicker'
|
|
13
13
|
|
|
14
|
+
import { useDebouncedCallback } from '../../hooks'
|
|
14
15
|
import { Colors } from '../../types'
|
|
15
16
|
import { getLocalDateFromString } from './utils'
|
|
16
17
|
|
|
@@ -101,6 +102,24 @@ export interface CDateRangePickerProps
|
|
|
101
102
|
* Toggle visibility or set the content of the input indicator.
|
|
102
103
|
*/
|
|
103
104
|
indicator?: ReactNode | boolean
|
|
105
|
+
/**
|
|
106
|
+
* Custom function to format the selected date into a string according to a custom format.
|
|
107
|
+
*
|
|
108
|
+
* @since v4.14.0
|
|
109
|
+
*/
|
|
110
|
+
inputDateFormat?: (date: Date) => string
|
|
111
|
+
/**
|
|
112
|
+
* Custom function to parse the input value into a valid Date object.
|
|
113
|
+
*
|
|
114
|
+
* @since v4.14.0
|
|
115
|
+
*/
|
|
116
|
+
inputDateParse?: (date: string | Date) => Date
|
|
117
|
+
/**
|
|
118
|
+
* Defines the delay (in milliseconds) for the input field's onChange event.
|
|
119
|
+
*
|
|
120
|
+
* @since v4.14.0
|
|
121
|
+
*/
|
|
122
|
+
inputOnChangeDelay?: number
|
|
104
123
|
/**
|
|
105
124
|
* Toggle the readonly state for the component.
|
|
106
125
|
*/
|
|
@@ -190,7 +209,6 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
|
|
|
190
209
|
confirmButtonColor = 'primary',
|
|
191
210
|
confirmButtonSize = 'sm',
|
|
192
211
|
confirmButtonVariant,
|
|
193
|
-
indicator = true,
|
|
194
212
|
dayFormat,
|
|
195
213
|
disabled,
|
|
196
214
|
disabledDates,
|
|
@@ -202,6 +220,10 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
|
|
|
202
220
|
format,
|
|
203
221
|
footer,
|
|
204
222
|
id,
|
|
223
|
+
indicator = true,
|
|
224
|
+
inputDateFormat,
|
|
225
|
+
inputDateParse,
|
|
226
|
+
inputOnChangeDelay = 750,
|
|
205
227
|
inputReadOnly,
|
|
206
228
|
invalid,
|
|
207
229
|
label,
|
|
@@ -270,17 +292,13 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
|
|
|
270
292
|
}, [valid, invalid])
|
|
271
293
|
|
|
272
294
|
useEffect(() => {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
setCalendarDate(new Date(startDate))
|
|
276
|
-
}
|
|
295
|
+
setStartDate(startDate ? new Date(startDate) : null)
|
|
296
|
+
setCalendarDate(startDate ? new Date(startDate) : new Date())
|
|
277
297
|
}, [startDate])
|
|
278
298
|
|
|
279
299
|
useEffect(() => {
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
setCalendarDate(new Date(endDate))
|
|
283
|
-
}
|
|
300
|
+
setEndDate(endDate ? new Date(endDate) : null)
|
|
301
|
+
setCalendarDate(endDate ? new Date(endDate) : new Date())
|
|
284
302
|
}, [endDate])
|
|
285
303
|
|
|
286
304
|
useEffect(() => {
|
|
@@ -326,7 +344,9 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
|
|
|
326
344
|
}, [formRef, _startDate, _endDate])
|
|
327
345
|
|
|
328
346
|
const formatDate = (date: Date) => {
|
|
329
|
-
return
|
|
347
|
+
return inputDateFormat
|
|
348
|
+
? inputDateFormat(date)
|
|
349
|
+
: format
|
|
330
350
|
? dateFormat(date, format)
|
|
331
351
|
: timepicker
|
|
332
352
|
? date.toLocaleString(locale)
|
|
@@ -402,6 +422,16 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
|
|
|
402
422
|
}
|
|
403
423
|
}
|
|
404
424
|
|
|
425
|
+
const handleOnChange = useDebouncedCallback((value: string, input: string) => {
|
|
426
|
+
const date = inputDateParse
|
|
427
|
+
? inputDateParse(value)
|
|
428
|
+
: getLocalDateFromString(value, locale, timepicker)
|
|
429
|
+
if (date instanceof Date && date.getTime()) {
|
|
430
|
+
setCalendarDate(date)
|
|
431
|
+
input === 'start' ? setStartDate(date) : setEndDate(date)
|
|
432
|
+
}
|
|
433
|
+
}, inputOnChangeDelay)
|
|
434
|
+
|
|
405
435
|
const InputGroup = () => (
|
|
406
436
|
<div
|
|
407
437
|
className={classNames('input-group', 'picker-input-group', {
|
|
@@ -419,11 +449,7 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
|
|
|
419
449
|
readOnly={inputReadOnly || typeof format === 'string'}
|
|
420
450
|
required={required}
|
|
421
451
|
onChange={(event) => {
|
|
422
|
-
|
|
423
|
-
if (date instanceof Date && date.getTime()) {
|
|
424
|
-
setCalendarDate(date)
|
|
425
|
-
setStartDate(date)
|
|
426
|
-
}
|
|
452
|
+
handleOnChange(event.target.value, 'start')
|
|
427
453
|
}}
|
|
428
454
|
onClick={() => setSelectEndDate(false)}
|
|
429
455
|
ref={inputStartRef}
|
|
@@ -439,18 +465,13 @@ export const CDateRangePicker = forwardRef<HTMLDivElement | HTMLLIElement, CDate
|
|
|
439
465
|
className={classNames('form-control date-picker-input', {
|
|
440
466
|
hover: inputEndHoverValue,
|
|
441
467
|
})}
|
|
442
|
-
|
|
443
468
|
disabled={disabled}
|
|
444
469
|
{...(id && { name: `${id}-end-date` })}
|
|
445
470
|
placeholder={placeholder[1]}
|
|
446
471
|
readOnly={inputReadOnly || typeof format === 'string'}
|
|
447
472
|
required={required}
|
|
448
473
|
onChange={(event) => {
|
|
449
|
-
|
|
450
|
-
if (date instanceof Date && date.getTime()) {
|
|
451
|
-
setCalendarDate(date)
|
|
452
|
-
setEndDate(date)
|
|
453
|
-
}
|
|
474
|
+
handleOnChange(event.target.value, 'end')
|
|
454
475
|
}}
|
|
455
476
|
onClick={() => setSelectEndDate(true)}
|
|
456
477
|
ref={inputEndRef}
|
|
@@ -692,6 +713,9 @@ CDateRangePicker.propTypes = {
|
|
|
692
713
|
confirmButtonVariant: CButton.propTypes?.variant,
|
|
693
714
|
id: PropTypes.string,
|
|
694
715
|
indicator: PropTypes.oneOfType([PropTypes.bool, PropTypes.node]),
|
|
716
|
+
inputDateFormat: PropTypes.func,
|
|
717
|
+
inputDateParse: PropTypes.func,
|
|
718
|
+
inputOnChangeDelay: PropTypes.number,
|
|
695
719
|
inputReadOnly: PropTypes.bool,
|
|
696
720
|
placeholder: PropTypes.oneOfType([
|
|
697
721
|
PropTypes.string,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { forwardRef, HTMLAttributes, ReactNode, useRef, useEffect, useState } from 'react'
|
|
2
2
|
import { createPortal } from 'react-dom'
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
import PropTypes from 'prop-types'
|
|
5
5
|
import { Transition } from 'react-transition-group'
|
|
6
6
|
|
|
7
|
-
import { usePopper } from '../../hooks'
|
|
7
|
+
import { useForkedRef, usePopper } from '../../hooks'
|
|
8
8
|
import { fallbackPlacementsPropType, triggerPropType } from '../../props'
|
|
9
9
|
import type { Placements, Triggers } from '../../types'
|
|
10
10
|
import { getRTLPlacement, getTransitionDurationFromElement } from '../../utils'
|
|
@@ -68,132 +68,141 @@ export interface CPopoverProps extends Omit<HTMLAttributes<HTMLDivElement>, 'tit
|
|
|
68
68
|
visible?: boolean
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
export const CPopover
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
71
|
+
export const CPopover = forwardRef<HTMLDivElement, CPopoverProps>(
|
|
72
|
+
(
|
|
73
|
+
{
|
|
74
|
+
children,
|
|
75
|
+
animation = true,
|
|
76
|
+
className,
|
|
77
|
+
content,
|
|
78
|
+
delay = 0,
|
|
79
|
+
fallbackPlacements = ['top', 'right', 'bottom', 'left'],
|
|
80
|
+
offset = [0, 8],
|
|
81
|
+
onHide,
|
|
82
|
+
onShow,
|
|
83
|
+
placement = 'top',
|
|
84
|
+
title,
|
|
85
|
+
trigger = 'click',
|
|
86
|
+
visible,
|
|
87
|
+
...rest
|
|
88
|
+
},
|
|
89
|
+
ref,
|
|
90
|
+
) => {
|
|
91
|
+
const popoverRef = useRef(null)
|
|
92
|
+
const togglerRef = useRef(null)
|
|
93
|
+
const forkedRef = useForkedRef(ref, popoverRef)
|
|
91
94
|
|
|
92
|
-
|
|
95
|
+
const { initPopper, destroyPopper } = usePopper()
|
|
96
|
+
const [_visible, setVisible] = useState(visible)
|
|
93
97
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
const _delay = typeof delay === 'number' ? { show: delay, hide: delay } : delay
|
|
99
|
+
|
|
100
|
+
const popperConfig = {
|
|
101
|
+
modifiers: [
|
|
102
|
+
{
|
|
103
|
+
name: 'arrow',
|
|
104
|
+
options: {
|
|
105
|
+
element: '.popover-arrow',
|
|
106
|
+
},
|
|
100
107
|
},
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
108
|
+
{
|
|
109
|
+
name: 'flip',
|
|
110
|
+
options: {
|
|
111
|
+
fallbackPlacements: fallbackPlacements,
|
|
112
|
+
},
|
|
106
113
|
},
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
114
|
+
{
|
|
115
|
+
name: 'offset',
|
|
116
|
+
options: {
|
|
117
|
+
offset: offset,
|
|
118
|
+
},
|
|
112
119
|
},
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
120
|
+
],
|
|
121
|
+
placement: getRTLPlacement(placement, togglerRef.current),
|
|
122
|
+
}
|
|
117
123
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
setVisible(visible)
|
|
126
|
+
}, [visible])
|
|
121
127
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
if (_visible && togglerRef.current && popoverRef.current) {
|
|
130
|
+
initPopper(togglerRef.current, popoverRef.current, popperConfig)
|
|
131
|
+
}
|
|
126
132
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
133
|
+
return () => {
|
|
134
|
+
destroyPopper()
|
|
135
|
+
}
|
|
136
|
+
}, [_visible])
|
|
131
137
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
138
|
+
const toggleVisible = (visible: boolean) => {
|
|
139
|
+
if (visible) {
|
|
140
|
+
setTimeout(() => setVisible(true), _delay.show)
|
|
141
|
+
return
|
|
142
|
+
}
|
|
137
143
|
|
|
138
|
-
|
|
139
|
-
|
|
144
|
+
setTimeout(() => setVisible(false), _delay.hide)
|
|
145
|
+
}
|
|
140
146
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
147
|
+
return (
|
|
148
|
+
<>
|
|
149
|
+
{React.cloneElement(children as React.ReactElement<any>, {
|
|
150
|
+
ref: togglerRef,
|
|
151
|
+
...((trigger === 'click' || trigger.includes('click')) && {
|
|
152
|
+
onClick: () => toggleVisible(!_visible),
|
|
153
|
+
}),
|
|
154
|
+
...((trigger === 'focus' || trigger.includes('focus')) && {
|
|
155
|
+
onFocus: () => toggleVisible(true),
|
|
156
|
+
onBlur: () => toggleVisible(false),
|
|
157
|
+
}),
|
|
158
|
+
...((trigger === 'hover' || trigger.includes('hover')) && {
|
|
159
|
+
onMouseEnter: () => toggleVisible(true),
|
|
160
|
+
onMouseLeave: () => toggleVisible(false),
|
|
161
|
+
}),
|
|
162
|
+
})}
|
|
163
|
+
{typeof window !== 'undefined' &&
|
|
164
|
+
createPortal(
|
|
165
|
+
<Transition
|
|
166
|
+
in={_visible}
|
|
167
|
+
mountOnEnter
|
|
168
|
+
nodeRef={popoverRef}
|
|
169
|
+
onEnter={onShow}
|
|
170
|
+
onExit={onHide}
|
|
171
|
+
timeout={{
|
|
172
|
+
enter: 0,
|
|
173
|
+
exit: popoverRef.current
|
|
174
|
+
? getTransitionDurationFromElement(popoverRef.current) + 50
|
|
175
|
+
: 200,
|
|
176
|
+
}}
|
|
177
|
+
unmountOnExit
|
|
178
|
+
>
|
|
179
|
+
{(state) => (
|
|
180
|
+
<div
|
|
181
|
+
className={classNames(
|
|
182
|
+
'popover',
|
|
183
|
+
'bs-popover-auto',
|
|
184
|
+
{
|
|
185
|
+
fade: animation,
|
|
186
|
+
show: state === 'entered',
|
|
187
|
+
},
|
|
188
|
+
className,
|
|
189
|
+
)}
|
|
190
|
+
ref={forkedRef}
|
|
191
|
+
role="tooltip"
|
|
192
|
+
{...rest}
|
|
193
|
+
>
|
|
194
|
+
<div className="popover-arrow"></div>
|
|
195
|
+
<div className="popover-header">{title}</div>
|
|
196
|
+
<div className="popover-body">{content}</div>
|
|
197
|
+
</div>
|
|
198
|
+
)}
|
|
199
|
+
</Transition>,
|
|
200
|
+
document.body,
|
|
201
|
+
)}
|
|
202
|
+
</>
|
|
203
|
+
)
|
|
204
|
+
},
|
|
205
|
+
)
|
|
197
206
|
|
|
198
207
|
CPopover.propTypes = {
|
|
199
208
|
animation: PropTypes.bool,
|
|
@@ -183,7 +183,7 @@ export const CTimePicker = forwardRef<HTMLDivElement | HTMLLIElement, CTimePicke
|
|
|
183
183
|
})
|
|
184
184
|
|
|
185
185
|
useEffect(() => {
|
|
186
|
-
setDate(convertTimeToDate(time))
|
|
186
|
+
setDate(time ? convertTimeToDate(time) : null)
|
|
187
187
|
}, [time])
|
|
188
188
|
|
|
189
189
|
useEffect(() => {
|
|
@@ -390,38 +390,6 @@ export const CTimePicker = forwardRef<HTMLDivElement | HTMLLIElement, CTimePicke
|
|
|
390
390
|
)
|
|
391
391
|
}
|
|
392
392
|
|
|
393
|
-
const TimePickerRoll = () => (
|
|
394
|
-
<>
|
|
395
|
-
<CTimePickerRollCol
|
|
396
|
-
elements={localizedTimePartials && localizedTimePartials.listOfHours}
|
|
397
|
-
onClick={(index: number) => handleTimeChange('hours', index.toString())}
|
|
398
|
-
selected={getSelectedHour(date, locale, ampm)}
|
|
399
|
-
/>
|
|
400
|
-
<CTimePickerRollCol
|
|
401
|
-
elements={localizedTimePartials && localizedTimePartials.listOfMinutes}
|
|
402
|
-
onClick={(index: number) => handleTimeChange('minutes', index.toString())}
|
|
403
|
-
selected={getSelectedMinutes(date)}
|
|
404
|
-
/>
|
|
405
|
-
{seconds && (
|
|
406
|
-
<CTimePickerRollCol
|
|
407
|
-
elements={localizedTimePartials && localizedTimePartials.listOfSeconds}
|
|
408
|
-
onClick={(index: number) => handleTimeChange('seconds', index.toString())}
|
|
409
|
-
selected={getSelectedSeconds(date)}
|
|
410
|
-
/>
|
|
411
|
-
)}
|
|
412
|
-
{localizedTimePartials && localizedTimePartials.hour12 && (
|
|
413
|
-
<CTimePickerRollCol
|
|
414
|
-
elements={[
|
|
415
|
-
{ value: 'am', label: 'AM' },
|
|
416
|
-
{ value: 'pm', label: 'PM' },
|
|
417
|
-
]}
|
|
418
|
-
onClick={(value: string) => handleTimeChange('toggle', value)}
|
|
419
|
-
selected={_ampm}
|
|
420
|
-
/>
|
|
421
|
-
)}
|
|
422
|
-
</>
|
|
423
|
-
)
|
|
424
|
-
|
|
425
393
|
return (
|
|
426
394
|
<CFormControlWrapper
|
|
427
395
|
describedby={rest['aria-describedby']}
|
|
@@ -499,7 +467,39 @@ export const CTimePicker = forwardRef<HTMLDivElement | HTMLLIElement, CTimePicke
|
|
|
499
467
|
['time-picker-roll']: variant === 'roll',
|
|
500
468
|
})}
|
|
501
469
|
>
|
|
502
|
-
{variant === 'select' ?
|
|
470
|
+
{variant === 'select' ? (
|
|
471
|
+
<TimePickerSelect />
|
|
472
|
+
) : (
|
|
473
|
+
<>
|
|
474
|
+
<CTimePickerRollCol
|
|
475
|
+
elements={localizedTimePartials && localizedTimePartials.listOfHours}
|
|
476
|
+
onClick={(index: number) => handleTimeChange('hours', index.toString())}
|
|
477
|
+
selected={getSelectedHour(date, locale, ampm)}
|
|
478
|
+
/>
|
|
479
|
+
<CTimePickerRollCol
|
|
480
|
+
elements={localizedTimePartials && localizedTimePartials.listOfMinutes}
|
|
481
|
+
onClick={(index: number) => handleTimeChange('minutes', index.toString())}
|
|
482
|
+
selected={getSelectedMinutes(date)}
|
|
483
|
+
/>
|
|
484
|
+
{seconds && (
|
|
485
|
+
<CTimePickerRollCol
|
|
486
|
+
elements={localizedTimePartials && localizedTimePartials.listOfSeconds}
|
|
487
|
+
onClick={(index: number) => handleTimeChange('seconds', index.toString())}
|
|
488
|
+
selected={getSelectedSeconds(date)}
|
|
489
|
+
/>
|
|
490
|
+
)}
|
|
491
|
+
{localizedTimePartials && localizedTimePartials.hour12 && (
|
|
492
|
+
<CTimePickerRollCol
|
|
493
|
+
elements={[
|
|
494
|
+
{ value: 'am', label: 'AM' },
|
|
495
|
+
{ value: 'pm', label: 'PM' },
|
|
496
|
+
]}
|
|
497
|
+
onClick={(value: string) => handleTimeChange('toggle', value)}
|
|
498
|
+
selected={_ampm}
|
|
499
|
+
/>
|
|
500
|
+
)}
|
|
501
|
+
</>
|
|
502
|
+
)}
|
|
503
503
|
</div>
|
|
504
504
|
</CPicker>
|
|
505
505
|
</CFormControlWrapper>
|
|
@@ -2,7 +2,7 @@ import React, { forwardRef, useEffect, useRef } from 'react'
|
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
|
|
5
|
-
import { useForkedRef } from '../../hooks'
|
|
5
|
+
import { useForkedRef, useIsVisible } from '../../hooks'
|
|
6
6
|
|
|
7
7
|
export interface Element {
|
|
8
8
|
value: number | string
|
|
@@ -20,18 +20,21 @@ export const CTimePickerRollCol = forwardRef<HTMLDivElement, CTimePickerRollColP
|
|
|
20
20
|
const init = useRef(true)
|
|
21
21
|
const colRef = useRef<HTMLDivElement>(null)
|
|
22
22
|
const forkedRef = useForkedRef(ref, colRef)
|
|
23
|
+
const isVisible = useIsVisible(colRef)
|
|
23
24
|
|
|
24
25
|
useEffect(() => {
|
|
25
26
|
const nodeEl = colRef.current?.querySelector('.selected')
|
|
26
|
-
if (nodeEl && nodeEl instanceof HTMLElement) {
|
|
27
|
+
if (isVisible && nodeEl && nodeEl instanceof HTMLElement) {
|
|
27
28
|
colRef.current?.scrollTo({
|
|
28
29
|
top: nodeEl.offsetTop,
|
|
29
30
|
behavior: init.current ? 'auto' : 'smooth',
|
|
30
31
|
})
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
if (isVisible) {
|
|
35
|
+
init.current = false
|
|
36
|
+
}
|
|
37
|
+
}, [isVisible, selected])
|
|
35
38
|
|
|
36
39
|
const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>, value: number | string) => {
|
|
37
40
|
if (event.code === 'Space' || event.key === 'Enter') {
|