@coreui/react-pro 4.1.2 → 4.2.0-beta.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/calendar/CCalendar.d.ts +89 -0
- package/dist/components/calendar/CCalendar.utils.d.ts +20 -0
- package/dist/components/datepicker/CDatePicker.d.ts +13 -0
- package/dist/components/daterangepicker/CDateRangePicker.d.ts +50 -0
- package/dist/components/dropdown/CDropdown.d.ts +10 -1
- package/dist/components/dropdown/CDropdownToggle.d.ts +4 -0
- package/dist/components/dropdown/CDropdownToggleCustom.d.ts +15 -0
- package/dist/components/modal/CModal.d.ts +1 -0
- package/dist/components/picker/CPicker.d.ts +37 -0
- package/dist/components/smart-table/CSmartTableInterface.d.ts +0 -9
- package/dist/components/timepicker/CTimePicker.d.ts +49 -0
- package/dist/components/timepicker/CTimePicker.utils.d.ts +4 -0
- package/dist/components/timepicker/CTimePickerRollCol.d.ts +11 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.es.js +2976 -1148
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +4691 -2859
- package/dist/index.js.map +1 -1
- package/package.json +10 -8
- package/src/components/accordion/CAccordionButton.tsx +2 -1
- package/src/components/calendar/CCalendar.tsx +482 -0
- package/src/components/calendar/CCalendar.utils.ts +183 -0
- package/src/components/datepicker/CDatePicker.tsx +49 -0
- package/src/components/daterangepicker/CDateRangePicker.tsx +366 -0
- package/src/components/dropdown/CDropdown.tsx +19 -24
- package/src/components/dropdown/CDropdownMenu.tsx +55 -3
- package/src/components/dropdown/CDropdownToggle.tsx +28 -5
- package/src/components/modal/CModal.tsx +42 -19
- package/src/components/modal/__tests__/CModal.spec.tsx +1 -1
- package/src/components/modal/__tests__/__snapshots__/CModal.spec.tsx.snap +2 -10
- package/src/components/picker/CPicker.tsx +142 -0
- package/src/components/smart-table/CSmartTable.tsx +44 -96
- package/src/components/smart-table/CSmartTableCleaner.tsx +3 -16
- package/src/components/smart-table/CSmartTableInterface.tsx +0 -9
- package/src/components/timepicker/CTimePicker.tsx +341 -0
- package/src/components/timepicker/CTimePicker.utils.ts +27 -0
- package/src/components/timepicker/CTimePickerRollCol.tsx +57 -0
- package/src/index.ts +8 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import PropTypes from 'prop-types'
|
|
2
2
|
import React, { forwardRef, HTMLAttributes, ReactNode } from 'react'
|
|
3
3
|
|
|
4
|
+
import { cilFilterX } from '@coreui/icons-pro'
|
|
5
|
+
|
|
4
6
|
import CIcon from '@coreui/icons-react'
|
|
5
7
|
|
|
6
8
|
interface CSmartTableCleanerProps extends HTMLAttributes<HTMLButtonElement> {
|
|
@@ -9,22 +11,7 @@ interface CSmartTableCleanerProps extends HTMLAttributes<HTMLButtonElement> {
|
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
export const CSmartTableCleaner = forwardRef<HTMLButtonElement, CSmartTableCleanerProps>(
|
|
12
|
-
(
|
|
13
|
-
{
|
|
14
|
-
content = (
|
|
15
|
-
<CIcon
|
|
16
|
-
width={18}
|
|
17
|
-
icon={[
|
|
18
|
-
'512 512',
|
|
19
|
-
'<polygon fill="var(--ci-primary-color, currentColor)" points="40 16 40 53.828 109.024 136 150.815 136 76.896 48 459.51 48 304 242.388 304 401.373 241.373 464 240 464 240 368 208 368 208 496 254.627 496 336 414.627 336 253.612 496 53.612 496 16 40 16" class="ci-primary"></polygon><polygon fill="var(--ci-primary-color, currentColor)" points="166.403 248.225 226.864 187.763 204.237 165.135 143.775 225.597 83.313 165.135 60.687 187.763 121.148 248.225 60.687 308.687 83.313 331.314 143.775 270.852 204.237 331.314 226.864 308.687 166.403 248.225" class="ci-primary"></polygon>',
|
|
20
|
-
]}
|
|
21
|
-
/>
|
|
22
|
-
),
|
|
23
|
-
isFiltered,
|
|
24
|
-
...rest
|
|
25
|
-
},
|
|
26
|
-
ref,
|
|
27
|
-
) => {
|
|
14
|
+
({ content = <CIcon width={18} icon={cilFilterX} />, isFiltered, ...rest }, ref) => {
|
|
28
15
|
return (
|
|
29
16
|
<button
|
|
30
17
|
type="button"
|
|
@@ -59,8 +59,6 @@ export interface SorterValue {
|
|
|
59
59
|
export interface TableFilter {
|
|
60
60
|
lazy?: boolean
|
|
61
61
|
external?: boolean
|
|
62
|
-
label?: string
|
|
63
|
-
placeholder?: string
|
|
64
62
|
}
|
|
65
63
|
|
|
66
64
|
export interface NoItemsView {
|
|
@@ -75,14 +73,9 @@ export interface CSmartTableProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
75
73
|
* @default 1
|
|
76
74
|
*/
|
|
77
75
|
activePage?: number
|
|
78
|
-
/**
|
|
79
|
-
* A string of all className you want applied to the base component.
|
|
80
|
-
*/
|
|
81
|
-
className?: string
|
|
82
76
|
/**
|
|
83
77
|
* When set, displays table cleaner above table, next to the table filter (or in place of table filter if `tableFilter` prop is not set)
|
|
84
78
|
* Cleaner resets `tableFilterValue`, `columnFilterValue`, `sorterValue`. If clean is possible it is clickable (`tabIndex="0"` `role="button"`, `color="danger"`), otherwise it is not clickable and transparent. Cleaner can be customized through the `cleaner` slot.
|
|
85
|
-
*
|
|
86
79
|
*/
|
|
87
80
|
cleaner?: boolean
|
|
88
81
|
/**
|
|
@@ -276,8 +269,6 @@ export interface CSmartTableProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
276
269
|
* When set, displays table filter above table, allowing filtering by specific column.
|
|
277
270
|
*
|
|
278
271
|
* Column filter can be customized, by passing prop as object with additional options as keys. Available options:
|
|
279
|
-
* - placeholder (String) - Sets custom table filter placeholder.
|
|
280
|
-
* - label (String) - Sets custom table filter label.
|
|
281
272
|
* - external (Boolean) - Disables automatic filtering inside component.
|
|
282
273
|
* - lazy (Boolean) - Set to true to trigger filter updates only on change event.
|
|
283
274
|
*/
|
|
@@ -0,0 +1,341 @@
|
|
|
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 { convert12hTo24h, convert24hTo12h, getAmPm, isAmPm } from './CTimePicker.utils'
|
|
14
|
+
|
|
15
|
+
export interface CTimePickerProps
|
|
16
|
+
extends Omit<
|
|
17
|
+
CPickerProps,
|
|
18
|
+
'autoClose' | 'component' | 'dark' | 'placeholder' | 'variant' | 'onChange'
|
|
19
|
+
> {
|
|
20
|
+
/**
|
|
21
|
+
* A string of all className you want applied to the component.
|
|
22
|
+
*/
|
|
23
|
+
className?: string
|
|
24
|
+
/**
|
|
25
|
+
* Enables selection cleaner element.
|
|
26
|
+
*/
|
|
27
|
+
cleaner?: boolean
|
|
28
|
+
/**
|
|
29
|
+
* Cleaner icon.
|
|
30
|
+
*/
|
|
31
|
+
cleanerIcon?: ReactNode | boolean
|
|
32
|
+
/**
|
|
33
|
+
* Default input icon.
|
|
34
|
+
*/
|
|
35
|
+
defaultIcon?: ReactNode | boolean
|
|
36
|
+
/**
|
|
37
|
+
* Toggle the readonly state for the component.
|
|
38
|
+
*/
|
|
39
|
+
inputReadOnly?: boolean
|
|
40
|
+
/**
|
|
41
|
+
* Sets the default locale for components. If not set, it is inherited from the navigator.language.
|
|
42
|
+
*/
|
|
43
|
+
locale?: string
|
|
44
|
+
/**
|
|
45
|
+
* Callback fired when the user hovers over the calendar cell.
|
|
46
|
+
*/
|
|
47
|
+
onChange?: (timeString: string, localeTimeString: string, date: Date) => void
|
|
48
|
+
/**
|
|
49
|
+
* Specifies a short hint that is visible in the input.
|
|
50
|
+
*/
|
|
51
|
+
placeholder?: string
|
|
52
|
+
/**
|
|
53
|
+
* Size the component small or large.
|
|
54
|
+
*/
|
|
55
|
+
size?: 'sm' | 'lg'
|
|
56
|
+
/**
|
|
57
|
+
* Default value of the component
|
|
58
|
+
*/
|
|
59
|
+
value?: Date | string | null
|
|
60
|
+
/**
|
|
61
|
+
* Set the time picker variant to a roll or select.
|
|
62
|
+
*/
|
|
63
|
+
variant?: 'roll' | 'select'
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export const CTimePicker = forwardRef<HTMLDivElement | HTMLLIElement, CTimePickerProps>(
|
|
67
|
+
(
|
|
68
|
+
{
|
|
69
|
+
className,
|
|
70
|
+
cleaner = true,
|
|
71
|
+
cleanerIcon,
|
|
72
|
+
container = 'dropdown',
|
|
73
|
+
defaultIcon,
|
|
74
|
+
disabled,
|
|
75
|
+
footer = true,
|
|
76
|
+
inputReadOnly,
|
|
77
|
+
locale = typeof navigator === 'undefined' ? 'en-US' : navigator.language,
|
|
78
|
+
onChange,
|
|
79
|
+
placeholder = 'Select time',
|
|
80
|
+
size,
|
|
81
|
+
value,
|
|
82
|
+
variant = 'roll',
|
|
83
|
+
...rest
|
|
84
|
+
},
|
|
85
|
+
ref,
|
|
86
|
+
) => {
|
|
87
|
+
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
|
+
)
|
|
91
|
+
const [_ampm, setAmPm] = useState<'am' | 'pm'>(date ? getAmPm(new Date(date), locale) : 'am')
|
|
92
|
+
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
setDate(
|
|
95
|
+
value ? (value instanceof Date ? new Date(value) : new Date(`1970-01-01 ${value}`)) : null,
|
|
96
|
+
)
|
|
97
|
+
}, [value])
|
|
98
|
+
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
if (inputRef.current) {
|
|
101
|
+
inputRef.current.value = date ? date.toLocaleTimeString(locale) : ''
|
|
102
|
+
}
|
|
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
|
+
|
|
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
|
|
130
|
+
|
|
131
|
+
const handleClear = (event: React.MouseEvent<HTMLElement>) => {
|
|
132
|
+
event.stopPropagation()
|
|
133
|
+
setDate(null)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const handleTimeChange = (set: 'hours' | 'minutes' | 'seconds' | 'toggle', value: string) => {
|
|
137
|
+
const _date = date || new Date('1970-01-01')
|
|
138
|
+
|
|
139
|
+
if (set === 'toggle') {
|
|
140
|
+
if (value === 'am') {
|
|
141
|
+
setAmPm('am')
|
|
142
|
+
_date.setHours(_date.getHours() - 12)
|
|
143
|
+
}
|
|
144
|
+
if (value === 'pm') {
|
|
145
|
+
setAmPm('pm')
|
|
146
|
+
_date.setHours(_date.getHours() + 12)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (set === 'hours') {
|
|
151
|
+
if (isAmPm(locale)) {
|
|
152
|
+
_date.setHours(convert12hTo24h(_ampm, parseInt(value)))
|
|
153
|
+
} else {
|
|
154
|
+
_date.setHours(parseInt(value))
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (set === 'minutes') {
|
|
159
|
+
_date.setMinutes(parseInt(value))
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (set === 'seconds') {
|
|
163
|
+
_date.setSeconds(parseInt(value))
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
setDate(new Date(_date))
|
|
167
|
+
onChange && onChange(_date.toTimeString(), _date.toLocaleTimeString(), _date)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const InputGroup = () => (
|
|
171
|
+
<CInputGroup className="picker-input-group" size={size}>
|
|
172
|
+
<CFormInput
|
|
173
|
+
disabled={disabled}
|
|
174
|
+
placeholder={placeholder}
|
|
175
|
+
readOnly={inputReadOnly}
|
|
176
|
+
ref={inputRef}
|
|
177
|
+
/>
|
|
178
|
+
{(defaultIcon !== false || cleaner) && (
|
|
179
|
+
<CInputGroupText>
|
|
180
|
+
{defaultIcon !== false && (
|
|
181
|
+
<span className="picker-input-group-indicator">
|
|
182
|
+
{defaultIcon ? (
|
|
183
|
+
defaultIcon
|
|
184
|
+
) : (
|
|
185
|
+
<span className="picker-input-group-icon time-picker-input-icon" />
|
|
186
|
+
)}
|
|
187
|
+
</span>
|
|
188
|
+
)}
|
|
189
|
+
{cleaner && date && (
|
|
190
|
+
<span
|
|
191
|
+
className="picker-input-group-cleaner"
|
|
192
|
+
role="button"
|
|
193
|
+
onClick={(event) => handleClear(event)}
|
|
194
|
+
>
|
|
195
|
+
{cleanerIcon ? (
|
|
196
|
+
cleanerIcon
|
|
197
|
+
) : (
|
|
198
|
+
<span className="picker-input-group-icon time-picker-cleaner-icon" />
|
|
199
|
+
)}
|
|
200
|
+
</span>
|
|
201
|
+
)}
|
|
202
|
+
</CInputGroupText>
|
|
203
|
+
)}
|
|
204
|
+
</CInputGroup>
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
const TimePickerSelect = () => {
|
|
208
|
+
return (
|
|
209
|
+
<>
|
|
210
|
+
<span className="time-picker-inline-icon" />
|
|
211
|
+
<CFormSelect
|
|
212
|
+
disabled={disabled}
|
|
213
|
+
options={getHours(locale).map((option) => {
|
|
214
|
+
return {
|
|
215
|
+
value: option.value.toString(),
|
|
216
|
+
label: option.label,
|
|
217
|
+
}
|
|
218
|
+
})}
|
|
219
|
+
onChange={(event: React.ChangeEvent<HTMLSelectElement>) =>
|
|
220
|
+
handleTimeChange('hours', event.target.value)
|
|
221
|
+
}
|
|
222
|
+
value={selectedHour ? selectedHour : '0'}
|
|
223
|
+
/>
|
|
224
|
+
<span className="px-1">:</span>
|
|
225
|
+
<CFormSelect
|
|
226
|
+
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
|
+
})}
|
|
233
|
+
onChange={(event: React.ChangeEvent<HTMLSelectElement>) =>
|
|
234
|
+
handleTimeChange('minutes', event.target.value)
|
|
235
|
+
}
|
|
236
|
+
value={selectedMinutes ? selectedMinutes : '0'}
|
|
237
|
+
/>
|
|
238
|
+
<span className="px-1">:</span>
|
|
239
|
+
<CFormSelect
|
|
240
|
+
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
|
+
})}
|
|
247
|
+
onChange={(event: React.ChangeEvent<HTMLSelectElement>) =>
|
|
248
|
+
handleTimeChange('seconds', event.target.value)
|
|
249
|
+
}
|
|
250
|
+
value={selectedSeconds ? selectedSeconds : '0'}
|
|
251
|
+
/>
|
|
252
|
+
{isAmPm(locale) && (
|
|
253
|
+
<CFormSelect
|
|
254
|
+
disabled={disabled}
|
|
255
|
+
options={[
|
|
256
|
+
{ value: 'am', label: 'AM' },
|
|
257
|
+
{ value: 'pm', label: 'PM' },
|
|
258
|
+
]}
|
|
259
|
+
onChange={(event: React.ChangeEvent<HTMLSelectElement>) =>
|
|
260
|
+
handleTimeChange('toggle', event.target.value)
|
|
261
|
+
}
|
|
262
|
+
value={_ampm}
|
|
263
|
+
/>
|
|
264
|
+
)}
|
|
265
|
+
</>
|
|
266
|
+
)
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const TimePickerRoll = () => (
|
|
270
|
+
<>
|
|
271
|
+
<CTimePickerRollCol
|
|
272
|
+
elements={getHours(locale)}
|
|
273
|
+
onClick={(index: number) => handleTimeChange('hours', index.toString())}
|
|
274
|
+
selected={selectedHour}
|
|
275
|
+
/>
|
|
276
|
+
<CTimePickerRollCol
|
|
277
|
+
elements={getMinutesOrSeconds(locale)}
|
|
278
|
+
selected={selectedMinutes}
|
|
279
|
+
onClick={(index: number) => handleTimeChange('minutes', index.toString())}
|
|
280
|
+
/>
|
|
281
|
+
<CTimePickerRollCol
|
|
282
|
+
elements={getMinutesOrSeconds(locale)}
|
|
283
|
+
selected={selectedSeconds}
|
|
284
|
+
onClick={(index: number) => handleTimeChange('seconds', index.toString())}
|
|
285
|
+
/>
|
|
286
|
+
{isAmPm(locale) && (
|
|
287
|
+
<CTimePickerRollCol
|
|
288
|
+
elements={[
|
|
289
|
+
{ value: 'am', label: 'AM' },
|
|
290
|
+
{ value: 'pm', label: 'PM' },
|
|
291
|
+
]}
|
|
292
|
+
selected={_ampm}
|
|
293
|
+
onClick={(value: string) => handleTimeChange('toggle', value)}
|
|
294
|
+
/>
|
|
295
|
+
)}
|
|
296
|
+
</>
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
const _className = classNames('time-picker', className)
|
|
300
|
+
|
|
301
|
+
return (
|
|
302
|
+
<CPicker
|
|
303
|
+
className={_className}
|
|
304
|
+
container={container}
|
|
305
|
+
disabled={disabled}
|
|
306
|
+
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
|
+
)
|
|
315
|
+
}}
|
|
316
|
+
toggler={InputGroup()}
|
|
317
|
+
{...rest}
|
|
318
|
+
ref={ref}
|
|
319
|
+
>
|
|
320
|
+
<div
|
|
321
|
+
className={classNames('time-picker-body', {
|
|
322
|
+
['time-picker-roll']: variant === 'roll',
|
|
323
|
+
})}
|
|
324
|
+
>
|
|
325
|
+
{variant === 'select' ? <TimePickerSelect /> : TimePickerRoll()}
|
|
326
|
+
</div>
|
|
327
|
+
</CPicker>
|
|
328
|
+
)
|
|
329
|
+
},
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
CTimePicker.propTypes = {
|
|
333
|
+
...CPicker.propTypes,
|
|
334
|
+
className: PropTypes.string,
|
|
335
|
+
locale: PropTypes.string,
|
|
336
|
+
onChange: PropTypes.func,
|
|
337
|
+
value: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),
|
|
338
|
+
variant: PropTypes.oneOf(['roll', 'select']),
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
CTimePicker.displayName = 'CTimePicker'
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export const convert12hTo24h = (abbr: 'am' | 'pm', hour: number) => {
|
|
2
|
+
if (abbr === 'am' && hour === 12) {
|
|
3
|
+
return 0
|
|
4
|
+
}
|
|
5
|
+
if (abbr === 'am') {
|
|
6
|
+
return hour
|
|
7
|
+
}
|
|
8
|
+
if (abbr === 'pm' && hour === 12) {
|
|
9
|
+
return 12
|
|
10
|
+
}
|
|
11
|
+
return hour + 12
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const convert24hTo12h = (hour: number) => hour % 12 || 12
|
|
15
|
+
|
|
16
|
+
export const getAmPm = (date: Date, locale: string) => {
|
|
17
|
+
if (date.toLocaleTimeString(locale).includes('AM')) {
|
|
18
|
+
return 'am'
|
|
19
|
+
}
|
|
20
|
+
if (date.toLocaleTimeString(locale).includes('PM')) {
|
|
21
|
+
return 'pm'
|
|
22
|
+
}
|
|
23
|
+
return date.getHours() >= 12 ? 'pm' : 'am'
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const isAmPm = (locale: string) =>
|
|
27
|
+
['am', 'AM', 'pm', 'PM'].some((el) => new Date().toLocaleString(locale).includes(el))
|
|
@@ -0,0 +1,57 @@
|
|
|
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 colRef = useRef<HTMLDivElement>(null)
|
|
21
|
+
const forkedRef = useForkedRef(ref, colRef)
|
|
22
|
+
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
const nodeEl = colRef.current?.querySelector('.selected')
|
|
25
|
+
if (nodeEl && nodeEl instanceof HTMLElement) {
|
|
26
|
+
colRef.current?.scrollTo({ top: nodeEl.offsetTop, behavior: 'smooth' })
|
|
27
|
+
}
|
|
28
|
+
}, [selected])
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div className="time-picker-roll-col" ref={forkedRef}>
|
|
32
|
+
{elements.map((element, index) => {
|
|
33
|
+
return (
|
|
34
|
+
<div
|
|
35
|
+
className={classNames('time-picker-roll-cell', {
|
|
36
|
+
selected: element.value === selected,
|
|
37
|
+
})}
|
|
38
|
+
key={index}
|
|
39
|
+
onClick={() => onClick && onClick(element.value)}
|
|
40
|
+
role="button"
|
|
41
|
+
>
|
|
42
|
+
{element.label}
|
|
43
|
+
</div>
|
|
44
|
+
)
|
|
45
|
+
})}
|
|
46
|
+
</div>
|
|
47
|
+
)
|
|
48
|
+
},
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
CTimePickerRollCol.propTypes = {
|
|
52
|
+
elements: PropTypes.array.isRequired,
|
|
53
|
+
onClick: PropTypes.func,
|
|
54
|
+
selected: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
CTimePickerRollCol.displayName = 'CTimePickerRollCol'
|
package/src/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { CBreadcrumbItem } from './components/breadcrumb/CBreadcrumbItem'
|
|
|
15
15
|
import { CButton } from './components/button/CButton'
|
|
16
16
|
import { CButtonGroup } from './components/button-group/CButtonGroup'
|
|
17
17
|
import { CButtonToolbar } from './components/button-group/CButtonToolbar'
|
|
18
|
+
import { CCalendar } from './components/calendar/CCalendar'
|
|
18
19
|
import { CCallout } from './components/callout/CCallout'
|
|
19
20
|
import { CCard } from './components/card/CCard'
|
|
20
21
|
import { CCardBody } from './components/card/CCardBody'
|
|
@@ -32,6 +33,8 @@ import { CCarouselCaption } from './components/carousel/CCarouselCaption'
|
|
|
32
33
|
import { CCarouselItem } from './components/carousel/CCarouselItem'
|
|
33
34
|
import { CCollapse } from './components/collapse/CCollapse'
|
|
34
35
|
import { CCloseButton } from './components/close-button/CCloseButton'
|
|
36
|
+
import { CDatePicker } from './components/datepicker/CDatePicker'
|
|
37
|
+
import { CDateRangePicker } from './components/daterangepicker/CDateRangePicker'
|
|
35
38
|
import { CDropdown } from './components/dropdown/CDropdown'
|
|
36
39
|
import { CDropdownDivider } from './components/dropdown/CDropdownDivider'
|
|
37
40
|
import { CDropdownHeader } from './components/dropdown/CDropdownHeader'
|
|
@@ -115,6 +118,7 @@ import { CTableHeaderCell } from './components/table/CTableHeaderCell'
|
|
|
115
118
|
import { CTableRow } from './components/table/CTableRow'
|
|
116
119
|
import { CTabContent } from './components/tabs/CTabContent'
|
|
117
120
|
import { CTabPane } from './components/tabs/CTabPane'
|
|
121
|
+
import { CTimePicker } from './components/timepicker/CTimePicker'
|
|
118
122
|
import { CToast } from './components/toast/CToast'
|
|
119
123
|
import { CToastBody } from './components/toast/CToastBody'
|
|
120
124
|
import { CToastClose } from './components/toast/CToastClose'
|
|
@@ -140,6 +144,7 @@ export {
|
|
|
140
144
|
CButton,
|
|
141
145
|
CButtonGroup,
|
|
142
146
|
CButtonToolbar,
|
|
147
|
+
CCalendar,
|
|
143
148
|
CCallout,
|
|
144
149
|
CCard,
|
|
145
150
|
CCardBody,
|
|
@@ -156,6 +161,8 @@ export {
|
|
|
156
161
|
CCarouselItem,
|
|
157
162
|
CCloseButton,
|
|
158
163
|
CCollapse,
|
|
164
|
+
CDatePicker,
|
|
165
|
+
CDateRangePicker,
|
|
159
166
|
CDropdown,
|
|
160
167
|
CDropdownDivider,
|
|
161
168
|
CDropdownHeader,
|
|
@@ -240,6 +247,7 @@ export {
|
|
|
240
247
|
CTableRow,
|
|
241
248
|
CTabContent,
|
|
242
249
|
CTabPane,
|
|
250
|
+
CTimePicker,
|
|
243
251
|
CToast,
|
|
244
252
|
CToastBody,
|
|
245
253
|
CToastClose,
|