@coreui/vue-pro 5.14.0 → 5.16.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/cjs/components/calendar/CCalendar.js +67 -65
- package/dist/cjs/components/calendar/CCalendar.js.map +1 -1
- package/dist/cjs/components/calendar/utils.d.ts +53 -2
- package/dist/cjs/components/calendar/utils.js +466 -43
- package/dist/cjs/components/calendar/utils.js.map +1 -1
- package/dist/cjs/components/date-range-picker/CDateRangePicker.js +86 -57
- package/dist/cjs/components/date-range-picker/CDateRangePicker.js.map +1 -1
- package/dist/cjs/components/date-range-picker/utils.d.ts +0 -9
- package/dist/cjs/components/date-range-picker/utils.js +0 -38
- package/dist/cjs/components/date-range-picker/utils.js.map +1 -1
- package/dist/cjs/components/dropdown/CDropdown.d.ts +32 -7
- package/dist/cjs/components/dropdown/CDropdown.js +67 -29
- package/dist/cjs/components/dropdown/CDropdown.js.map +1 -1
- package/dist/cjs/components/dropdown/CDropdownToggle.d.ts +19 -0
- package/dist/cjs/components/dropdown/CDropdownToggle.js +17 -2
- package/dist/cjs/components/dropdown/CDropdownToggle.js.map +1 -1
- package/dist/cjs/components/dropdown/utils.d.ts +2 -0
- package/dist/cjs/components/dropdown/utils.js +13 -0
- package/dist/cjs/components/dropdown/utils.js.map +1 -1
- package/dist/cjs/components/focus-trap/CFocusTrap.d.ts +108 -0
- package/dist/cjs/components/focus-trap/CFocusTrap.js +254 -0
- package/dist/cjs/components/focus-trap/CFocusTrap.js.map +1 -0
- package/dist/cjs/components/focus-trap/index.d.ts +6 -0
- package/dist/cjs/components/focus-trap/index.js +13 -0
- package/dist/cjs/components/focus-trap/index.js.map +1 -0
- package/dist/cjs/components/focus-trap/utils.d.ts +28 -0
- package/dist/cjs/components/focus-trap/utils.js +83 -0
- package/dist/cjs/components/focus-trap/utils.js.map +1 -0
- package/dist/cjs/components/index.d.ts +1 -0
- package/dist/cjs/components/index.js +70 -66
- package/dist/cjs/components/index.js.map +1 -1
- package/dist/cjs/components/modal/CModal.d.ts +2 -2
- package/dist/cjs/components/modal/CModal.js +19 -27
- package/dist/cjs/components/modal/CModal.js.map +1 -1
- package/dist/cjs/components/modal/CModalHeader.js +4 -2
- package/dist/cjs/components/modal/CModalHeader.js.map +1 -1
- package/dist/cjs/components/nav/CNavItem.d.ts +2 -2
- package/dist/cjs/components/offcanvas/COffcanvas.js +3 -2
- package/dist/cjs/components/offcanvas/COffcanvas.js.map +1 -1
- package/dist/cjs/components/picker/CPicker.js +3 -2
- package/dist/cjs/components/picker/CPicker.js.map +1 -1
- package/dist/cjs/components/time-picker/CTimePicker.d.ts +45 -1
- package/dist/cjs/components/time-picker/CTimePicker.js +64 -8
- package/dist/cjs/components/time-picker/CTimePicker.js.map +1 -1
- package/dist/cjs/components/time-picker/CTimePickerRollCol.d.ts +19 -7
- package/dist/cjs/components/time-picker/CTimePickerRollCol.js +80 -8
- package/dist/cjs/components/time-picker/CTimePickerRollCol.js.map +1 -1
- package/dist/cjs/components/time-picker/utils.d.ts +1 -1
- package/dist/cjs/composables/useDebouncedCallback.d.ts +1 -1
- package/dist/cjs/composables/useDebouncedCallback.js +1 -1
- package/dist/cjs/composables/useDebouncedCallback.js.map +1 -1
- package/dist/cjs/index.js +76 -72
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/components/calendar/CCalendar.js +67 -65
- package/dist/esm/components/calendar/CCalendar.js.map +1 -1
- package/dist/esm/components/calendar/utils.d.ts +53 -2
- package/dist/esm/components/calendar/utils.js +464 -44
- package/dist/esm/components/calendar/utils.js.map +1 -1
- package/dist/esm/components/date-range-picker/CDateRangePicker.js +86 -57
- package/dist/esm/components/date-range-picker/CDateRangePicker.js.map +1 -1
- package/dist/esm/components/date-range-picker/utils.d.ts +0 -9
- package/dist/esm/components/date-range-picker/utils.js +1 -38
- package/dist/esm/components/date-range-picker/utils.js.map +1 -1
- package/dist/esm/components/dropdown/CDropdown.d.ts +32 -7
- package/dist/esm/components/dropdown/CDropdown.js +69 -31
- package/dist/esm/components/dropdown/CDropdown.js.map +1 -1
- package/dist/esm/components/dropdown/CDropdownToggle.d.ts +19 -0
- package/dist/esm/components/dropdown/CDropdownToggle.js +17 -2
- package/dist/esm/components/dropdown/CDropdownToggle.js.map +1 -1
- package/dist/esm/components/dropdown/utils.d.ts +2 -0
- package/dist/esm/components/dropdown/utils.js +13 -1
- package/dist/esm/components/dropdown/utils.js.map +1 -1
- package/dist/esm/components/focus-trap/CFocusTrap.d.ts +108 -0
- package/dist/esm/components/focus-trap/CFocusTrap.js +252 -0
- package/dist/esm/components/focus-trap/CFocusTrap.js.map +1 -0
- package/dist/esm/components/focus-trap/index.d.ts +6 -0
- package/dist/esm/components/focus-trap/index.js +10 -0
- package/dist/esm/components/focus-trap/index.js.map +1 -0
- package/dist/esm/components/focus-trap/utils.d.ts +28 -0
- package/dist/esm/components/focus-trap/utils.js +78 -0
- package/dist/esm/components/focus-trap/utils.js.map +1 -0
- package/dist/esm/components/index.d.ts +1 -0
- package/dist/esm/components/index.js +2 -0
- package/dist/esm/components/index.js.map +1 -1
- package/dist/esm/components/modal/CModal.d.ts +2 -2
- package/dist/esm/components/modal/CModal.js +19 -27
- package/dist/esm/components/modal/CModal.js.map +1 -1
- package/dist/esm/components/modal/CModalHeader.js +4 -2
- package/dist/esm/components/modal/CModalHeader.js.map +1 -1
- package/dist/esm/components/nav/CNavItem.d.ts +2 -2
- package/dist/esm/components/offcanvas/COffcanvas.js +3 -2
- package/dist/esm/components/offcanvas/COffcanvas.js.map +1 -1
- package/dist/esm/components/picker/CPicker.js +3 -2
- package/dist/esm/components/picker/CPicker.js.map +1 -1
- package/dist/esm/components/time-picker/CTimePicker.d.ts +45 -1
- package/dist/esm/components/time-picker/CTimePicker.js +64 -8
- package/dist/esm/components/time-picker/CTimePicker.js.map +1 -1
- package/dist/esm/components/time-picker/CTimePickerRollCol.d.ts +19 -7
- package/dist/esm/components/time-picker/CTimePickerRollCol.js +80 -8
- package/dist/esm/components/time-picker/CTimePickerRollCol.js.map +1 -1
- package/dist/esm/components/time-picker/utils.d.ts +1 -1
- package/dist/esm/composables/useDebouncedCallback.d.ts +1 -1
- package/dist/esm/composables/useDebouncedCallback.js +1 -1
- package/dist/esm/composables/useDebouncedCallback.js.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/package.json +5 -5
- package/src/components/calendar/CCalendar.ts +61 -70
- package/src/components/calendar/utils.ts +595 -47
- package/src/components/date-range-picker/CDateRangePicker.ts +131 -82
- package/src/components/date-range-picker/utils.ts +0 -58
- package/src/components/dropdown/CDropdown.ts +119 -52
- package/src/components/dropdown/CDropdownToggle.ts +18 -3
- package/src/components/dropdown/utils.ts +21 -0
- package/src/components/focus-trap/CFocusTrap.ts +303 -0
- package/src/components/focus-trap/index.ts +10 -0
- package/src/components/focus-trap/utils.ts +90 -0
- package/src/components/index.ts +1 -0
- package/src/components/modal/CModal.ts +32 -37
- package/src/components/modal/CModalHeader.ts +5 -3
- package/src/components/nav/CNavItem.ts +1 -1
- package/src/components/offcanvas/COffcanvas.ts +40 -36
- package/src/components/picker/CPicker.ts +58 -52
- package/src/components/time-picker/CTimePicker.ts +80 -22
- package/src/components/time-picker/CTimePickerRollCol.ts +87 -9
- package/src/composables/useDebouncedCallback.ts +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { defineComponent, h, ref, RendererElement, Transition, watch, withDirectives } from 'vue'
|
|
2
2
|
|
|
3
3
|
import { CBackdrop } from '../backdrop'
|
|
4
|
+
import { CFocusTrap } from '../focus-trap'
|
|
4
5
|
|
|
5
6
|
import { vVisible } from '../../directives/v-c-visible'
|
|
6
7
|
import { executeAfterTransition } from '../../utils/transition'
|
|
@@ -103,7 +104,7 @@ const COffcanvas = defineComponent({
|
|
|
103
104
|
() => props.visible,
|
|
104
105
|
() => {
|
|
105
106
|
visible.value = props.visible
|
|
106
|
-
}
|
|
107
|
+
}
|
|
107
108
|
)
|
|
108
109
|
|
|
109
110
|
watch(visible, () => {
|
|
@@ -161,41 +162,44 @@ const COffcanvas = defineComponent({
|
|
|
161
162
|
}
|
|
162
163
|
|
|
163
164
|
return () => [
|
|
164
|
-
h(
|
|
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
|
-
|
|
197
|
-
|
|
198
|
-
|
|
165
|
+
h(CFocusTrap, { active: visible.value && Boolean(props.backdrop) }, () =>
|
|
166
|
+
h(
|
|
167
|
+
Transition,
|
|
168
|
+
{
|
|
169
|
+
appear: visible.value,
|
|
170
|
+
css: false,
|
|
171
|
+
onEnter: (el, done) => handleEnter(el, done),
|
|
172
|
+
onAfterEnter: () => handleAfterEnter(),
|
|
173
|
+
onLeave: (el, done) => handleLeave(el, done),
|
|
174
|
+
onAfterLeave: (el) => handleAfterLeave(el),
|
|
175
|
+
},
|
|
176
|
+
() =>
|
|
177
|
+
withDirectives(
|
|
178
|
+
h(
|
|
179
|
+
'div',
|
|
180
|
+
{
|
|
181
|
+
...attrs,
|
|
182
|
+
class: [
|
|
183
|
+
{
|
|
184
|
+
[`offcanvas${
|
|
185
|
+
typeof props.responsive === 'boolean' ? '' : '-' + props.responsive
|
|
186
|
+
}`]: props.responsive,
|
|
187
|
+
[`offcanvas-${props.placement}`]: props.placement,
|
|
188
|
+
},
|
|
189
|
+
attrs.class,
|
|
190
|
+
],
|
|
191
|
+
onKeydown: (event: KeyboardEvent) => handleKeyDown(event),
|
|
192
|
+
ref: offcanvasRef,
|
|
193
|
+
role: 'dialog',
|
|
194
|
+
tabindex: -1,
|
|
195
|
+
...(props.dark && { 'data-coreui-theme': 'dark' }),
|
|
196
|
+
},
|
|
197
|
+
slots.default && slots.default()
|
|
198
|
+
),
|
|
199
|
+
|
|
200
|
+
[[vVisible, props.visible]]
|
|
201
|
+
)
|
|
202
|
+
)
|
|
199
203
|
),
|
|
200
204
|
props.backdrop &&
|
|
201
205
|
h(CBackdrop, {
|
|
@@ -2,6 +2,7 @@ import { cloneVNode, defineComponent, h, PropType, ref, watch } from 'vue'
|
|
|
2
2
|
import { createPopper } from '@popperjs/core'
|
|
3
3
|
|
|
4
4
|
import { CConditionalTeleport } from '../conditional-teleport'
|
|
5
|
+
import { CFocusTrap } from '../focus-trap'
|
|
5
6
|
|
|
6
7
|
import { isRTL } from '../../utils'
|
|
7
8
|
|
|
@@ -63,7 +64,7 @@ const CPicker = defineComponent({
|
|
|
63
64
|
() => props.visible,
|
|
64
65
|
() => {
|
|
65
66
|
visible.value = props.visible
|
|
66
|
-
}
|
|
67
|
+
}
|
|
67
68
|
)
|
|
68
69
|
|
|
69
70
|
watch(visible, () => {
|
|
@@ -142,62 +143,67 @@ const CPicker = defineComponent({
|
|
|
142
143
|
default: {
|
|
143
144
|
return () =>
|
|
144
145
|
h(
|
|
145
|
-
|
|
146
|
-
{
|
|
147
|
-
|
|
148
|
-
attrs.class,
|
|
149
|
-
{
|
|
150
|
-
show: visible.value,
|
|
151
|
-
},
|
|
152
|
-
],
|
|
153
|
-
ref: pickerRef,
|
|
154
|
-
},
|
|
155
|
-
[
|
|
156
|
-
/**
|
|
157
|
-
* @slot Location for the toggler element.
|
|
158
|
-
*/
|
|
159
|
-
slots.toggler &&
|
|
160
|
-
slots.toggler().map((slot) =>
|
|
161
|
-
cloneVNode(slot, {
|
|
162
|
-
onClick: () => {
|
|
163
|
-
if (!props.disabled && !visible.value) {
|
|
164
|
-
visible.value = true
|
|
165
|
-
}
|
|
166
|
-
},
|
|
167
|
-
ref: (el) => {
|
|
168
|
-
togglerRef.value = el
|
|
169
|
-
},
|
|
170
|
-
}),
|
|
171
|
-
),
|
|
146
|
+
CFocusTrap,
|
|
147
|
+
{ active: visible.value, ...(props.teleport && { additionalContainer: dropdownRef }) },
|
|
148
|
+
() =>
|
|
172
149
|
h(
|
|
173
|
-
|
|
150
|
+
'div',
|
|
174
151
|
{
|
|
175
|
-
|
|
152
|
+
class: [
|
|
153
|
+
attrs.class,
|
|
154
|
+
{
|
|
155
|
+
show: visible.value,
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
ref: pickerRef,
|
|
176
159
|
},
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
160
|
+
[
|
|
161
|
+
/**
|
|
162
|
+
* @slot Location for the toggler element.
|
|
163
|
+
*/
|
|
164
|
+
slots.toggler &&
|
|
165
|
+
slots.toggler().map((slot) =>
|
|
166
|
+
cloneVNode(slot, {
|
|
167
|
+
onClick: () => {
|
|
168
|
+
if (!props.disabled && !visible.value) {
|
|
169
|
+
visible.value = true
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
ref: (el) => {
|
|
173
|
+
togglerRef.value = el
|
|
174
|
+
},
|
|
175
|
+
})
|
|
176
|
+
),
|
|
177
|
+
h(
|
|
178
|
+
CConditionalTeleport,
|
|
179
|
+
{
|
|
180
|
+
teleport: props.teleport,
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
default: () =>
|
|
184
|
+
h(
|
|
185
|
+
'div',
|
|
184
186
|
{
|
|
185
|
-
|
|
187
|
+
class: [
|
|
188
|
+
props.dropdownClassNames,
|
|
189
|
+
{
|
|
190
|
+
show: props.teleport && visible.value,
|
|
191
|
+
},
|
|
192
|
+
],
|
|
193
|
+
ref: dropdownRef,
|
|
186
194
|
},
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
),
|
|
200
|
-
],
|
|
195
|
+
[
|
|
196
|
+
slots.default && slots.default(),
|
|
197
|
+
/**
|
|
198
|
+
* @slot Location for the footer element.
|
|
199
|
+
*/
|
|
200
|
+
props.footer && slots.footer && slots.footer(),
|
|
201
|
+
]
|
|
202
|
+
),
|
|
203
|
+
}
|
|
204
|
+
),
|
|
205
|
+
]
|
|
206
|
+
)
|
|
201
207
|
)
|
|
202
208
|
}
|
|
203
209
|
}
|
|
@@ -25,6 +25,28 @@ import { Color } from '../props'
|
|
|
25
25
|
const CTimePicker = defineComponent({
|
|
26
26
|
name: 'CTimePicker',
|
|
27
27
|
props: {
|
|
28
|
+
/**
|
|
29
|
+
* Accessible label for the hours selection element.
|
|
30
|
+
*/
|
|
31
|
+
ariaSelectHoursLabel: String,
|
|
32
|
+
/**
|
|
33
|
+
* Accessible label for the AM/PM selection element.
|
|
34
|
+
*
|
|
35
|
+
* @since 5.16.0
|
|
36
|
+
*/
|
|
37
|
+
ariaSelectMeridiemLabel: String,
|
|
38
|
+
/**
|
|
39
|
+
* Accessible label for the minutes selection element.
|
|
40
|
+
*
|
|
41
|
+
* @since 5.16.0
|
|
42
|
+
*/
|
|
43
|
+
ariaSelectMinutesLabel: String,
|
|
44
|
+
/**
|
|
45
|
+
* Accessible label for the seconds selection element.
|
|
46
|
+
*
|
|
47
|
+
* @since 5.16.0
|
|
48
|
+
*/
|
|
49
|
+
ariaSelectSecondsLabel: String,
|
|
28
50
|
/**
|
|
29
51
|
* Set if the component should use the 12/24 hour format. If `true` forces the interface to a 12-hour format. If `false` forces the interface into a 24-hour format. If `auto` the current locale will determine the 12 or 24-hour interface by default locales.
|
|
30
52
|
*
|
|
@@ -339,9 +361,11 @@ const CTimePicker = defineComponent({
|
|
|
339
361
|
setup(props, { emit, attrs, slots }) {
|
|
340
362
|
const formRef = ref()
|
|
341
363
|
const inputRef = ref()
|
|
342
|
-
|
|
364
|
+
const columnRefs = ref<(HTMLElement | null)[]>([])
|
|
343
365
|
const date = ref<Date | null>(convertTimeToDate(props.time))
|
|
344
|
-
const ampm = ref<'am' | 'pm'
|
|
366
|
+
const ampm = ref<'am' | 'pm' | null>(
|
|
367
|
+
date.value ? getAmPm(new Date(date.value), props.locale) : null
|
|
368
|
+
)
|
|
345
369
|
const initialDate = ref<Date | null>(null)
|
|
346
370
|
const visible = ref(props.visible)
|
|
347
371
|
const localizedTimePartials = ref<LocalizedTimePartials>({
|
|
@@ -354,6 +378,10 @@ const CTimePicker = defineComponent({
|
|
|
354
378
|
props.valid ?? (props.invalid === true ? false : undefined)
|
|
355
379
|
)
|
|
356
380
|
|
|
381
|
+
const setColumnRef = (index: number, el: HTMLElement | null) => {
|
|
382
|
+
columnRefs.value[index] = el
|
|
383
|
+
}
|
|
384
|
+
|
|
357
385
|
watch(
|
|
358
386
|
() => props.time,
|
|
359
387
|
() => {
|
|
@@ -421,22 +449,32 @@ const CTimePicker = defineComponent({
|
|
|
421
449
|
isValid.value = false
|
|
422
450
|
}
|
|
423
451
|
|
|
424
|
-
const handleTimeChange = (set: 'hours' | 'minutes' | 'seconds' | '
|
|
452
|
+
const handleTimeChange = (set: 'hours' | 'minutes' | 'seconds' | 'meridiem', value: string) => {
|
|
425
453
|
const _date = date.value || new Date('1970-01-01')
|
|
426
454
|
|
|
427
|
-
if (set === '
|
|
455
|
+
if (set === 'meridiem') {
|
|
456
|
+
const currentHours = _date.getHours()
|
|
457
|
+
|
|
428
458
|
if (value === 'am') {
|
|
429
|
-
|
|
459
|
+
ampm.value = 'am'
|
|
460
|
+
// Convert PM hours (12-23) to AM hours (0-11)
|
|
461
|
+
if (currentHours >= 12) {
|
|
462
|
+
_date.setHours(currentHours - 12)
|
|
463
|
+
}
|
|
430
464
|
}
|
|
431
465
|
|
|
432
466
|
if (value === 'pm') {
|
|
433
|
-
|
|
467
|
+
ampm.value = 'pm'
|
|
468
|
+
// Convert AM hours (0-11) to PM hours (12-23)
|
|
469
|
+
if (currentHours < 12) {
|
|
470
|
+
_date.setHours(currentHours + 12)
|
|
471
|
+
}
|
|
434
472
|
}
|
|
435
473
|
}
|
|
436
474
|
|
|
437
475
|
if (set === 'hours') {
|
|
438
476
|
if (localizedTimePartials.value && localizedTimePartials.value.hour12) {
|
|
439
|
-
_date.setHours(convert12hTo24h(ampm.value, Number.parseInt(value)))
|
|
477
|
+
_date.setHours(convert12hTo24h(ampm.value ?? 'am', Number.parseInt(value)))
|
|
440
478
|
} else {
|
|
441
479
|
_date.setHours(Number.parseInt(value))
|
|
442
480
|
}
|
|
@@ -463,24 +501,23 @@ const CTimePicker = defineComponent({
|
|
|
463
501
|
disabled: props.disabled,
|
|
464
502
|
id: props.id,
|
|
465
503
|
name: props.name,
|
|
466
|
-
onInput: (event: Event) =>
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
date.value = _date
|
|
504
|
+
onInput: useDebouncedCallback((event: Event) => {
|
|
505
|
+
if (isValidTime((event.target as HTMLInputElement).value)) {
|
|
506
|
+
const _date = convertTimeToDate((event.target as HTMLInputElement).value)
|
|
507
|
+
date.value = _date
|
|
471
508
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
} else {
|
|
476
|
-
emit('change', null)
|
|
477
|
-
emit('update:time', null)
|
|
478
|
-
}
|
|
509
|
+
if (_date) {
|
|
510
|
+
emit('change', _date.toTimeString(), _date.toLocaleTimeString(props.locale), _date)
|
|
511
|
+
emit('update:time', _date.toLocaleTimeString(props.locale))
|
|
479
512
|
} else {
|
|
480
513
|
emit('change', null)
|
|
481
514
|
emit('update:time', null)
|
|
482
515
|
}
|
|
483
|
-
}
|
|
516
|
+
} else {
|
|
517
|
+
emit('change', null)
|
|
518
|
+
emit('update:time', null)
|
|
519
|
+
}
|
|
520
|
+
}, props.inputOnChangeDelay),
|
|
484
521
|
placeholder: props.placeholder,
|
|
485
522
|
readonly: props.inputReadOnly,
|
|
486
523
|
ref: inputRef,
|
|
@@ -528,6 +565,7 @@ const CTimePicker = defineComponent({
|
|
|
528
565
|
onChange: (event: Event) =>
|
|
529
566
|
handleTimeChange('hours', (event.target as HTMLSelectElement).value),
|
|
530
567
|
...(date.value && { value: getSelectedHour(date.value, props.locale) }),
|
|
568
|
+
'aria-label': props.ariaSelectHoursLabel,
|
|
531
569
|
},
|
|
532
570
|
localizedTimePartials.value &&
|
|
533
571
|
localizedTimePartials.value.listOfHours.map((option) =>
|
|
@@ -550,6 +588,7 @@ const CTimePicker = defineComponent({
|
|
|
550
588
|
onChange: (event: Event) =>
|
|
551
589
|
handleTimeChange('minutes', (event.target as HTMLSelectElement).value),
|
|
552
590
|
...(date.value && { value: getSelectedMinutes(date.value) }),
|
|
591
|
+
'aria-label': props.ariaSelectMinutesLabel,
|
|
553
592
|
},
|
|
554
593
|
localizedTimePartials.value &&
|
|
555
594
|
localizedTimePartials.value.listOfMinutes?.map((option) =>
|
|
@@ -572,6 +611,7 @@ const CTimePicker = defineComponent({
|
|
|
572
611
|
onChange: (event: Event) =>
|
|
573
612
|
handleTimeChange('seconds', (event.target as HTMLSelectElement).value),
|
|
574
613
|
...(date.value && { value: getSelectedSeconds(date.value) }),
|
|
614
|
+
'aria-label': props.ariaSelectSecondsLabel,
|
|
575
615
|
},
|
|
576
616
|
localizedTimePartials.value &&
|
|
577
617
|
localizedTimePartials.value.listOfSeconds?.map((option) =>
|
|
@@ -592,8 +632,9 @@ const CTimePicker = defineComponent({
|
|
|
592
632
|
class: 'time-picker-inline-select',
|
|
593
633
|
disabled: props.disabled,
|
|
594
634
|
onChange: (event: Event) =>
|
|
595
|
-
handleTimeChange('
|
|
635
|
+
handleTimeChange('meridiem', (event.target as HTMLSelectElement).value),
|
|
596
636
|
value: ampm.value,
|
|
637
|
+
'aria-label': props.ariaSelectMeridiemLabel,
|
|
597
638
|
},
|
|
598
639
|
[
|
|
599
640
|
h(
|
|
@@ -616,31 +657,47 @@ const CTimePicker = defineComponent({
|
|
|
616
657
|
|
|
617
658
|
const TimePickerRoll = () => [
|
|
618
659
|
h(CTimePickerRollCol, {
|
|
660
|
+
ariaLabel: props.ariaSelectHoursLabel,
|
|
661
|
+
columnIndex: 0,
|
|
662
|
+
columnRefs: columnRefs.value,
|
|
619
663
|
elements: localizedTimePartials.value && localizedTimePartials.value.listOfHours,
|
|
620
664
|
onClick: (index: number) => handleTimeChange('hours', index.toString()),
|
|
621
665
|
selected: getSelectedHour(date.value, props.locale, props.ampm),
|
|
666
|
+
setColumnRef,
|
|
622
667
|
}),
|
|
623
668
|
props.minutes &&
|
|
624
669
|
h(CTimePickerRollCol, {
|
|
670
|
+
ariaLabel: props.ariaSelectMinutesLabel,
|
|
671
|
+
columnIndex: 1,
|
|
672
|
+
columnRefs: columnRefs.value,
|
|
625
673
|
elements: localizedTimePartials.value && localizedTimePartials.value.listOfMinutes,
|
|
626
674
|
onClick: (index: number) => handleTimeChange('minutes', index.toString()),
|
|
627
675
|
selected: getSelectedMinutes(date.value),
|
|
676
|
+
setColumnRef,
|
|
628
677
|
}),
|
|
629
678
|
props.seconds &&
|
|
630
679
|
h(CTimePickerRollCol, {
|
|
680
|
+
ariaLabel: props.ariaSelectSecondsLabel,
|
|
681
|
+
columnIndex: props.minutes ? 2 : 1,
|
|
682
|
+
columnRefs: columnRefs.value,
|
|
631
683
|
elements: localizedTimePartials.value && localizedTimePartials.value.listOfSeconds,
|
|
632
684
|
onClick: (index: number) => handleTimeChange('seconds', index.toString()),
|
|
633
685
|
selected: getSelectedSeconds(date.value),
|
|
686
|
+
setColumnRef,
|
|
634
687
|
}),
|
|
635
688
|
localizedTimePartials.value &&
|
|
636
689
|
localizedTimePartials.value.hour12 &&
|
|
637
690
|
h(CTimePickerRollCol, {
|
|
691
|
+
ariaLabel: props.ariaSelectMeridiemLabel,
|
|
692
|
+
columnIndex: (props.minutes ? 1 : 0) + (props.seconds ? 1 : 0) + 1,
|
|
693
|
+
columnRefs: columnRefs.value,
|
|
638
694
|
elements: [
|
|
639
695
|
{ value: 'am', label: 'AM' },
|
|
640
696
|
{ value: 'pm', label: 'PM' },
|
|
641
697
|
],
|
|
642
|
-
onClick: (value: string) => handleTimeChange('
|
|
698
|
+
onClick: (value: string) => handleTimeChange('meridiem', value),
|
|
643
699
|
selected: ampm.value,
|
|
700
|
+
setColumnRef,
|
|
644
701
|
}),
|
|
645
702
|
]
|
|
646
703
|
|
|
@@ -712,6 +769,7 @@ const CTimePicker = defineComponent({
|
|
|
712
769
|
['time-picker-roll']: props.variant === 'roll',
|
|
713
770
|
},
|
|
714
771
|
],
|
|
772
|
+
...(props.variant !== 'select' && { role: 'group' }),
|
|
715
773
|
},
|
|
716
774
|
props.variant === 'select' ? TimePickerSelect() : TimePickerRoll()
|
|
717
775
|
),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { defineComponent, h, onUpdated, PropType, ref, watch } from 'vue'
|
|
2
2
|
|
|
3
3
|
import { useIsVisible } from '../../composables'
|
|
4
|
+
import { getNextActiveElement, isRTL } from '../../utils'
|
|
4
5
|
|
|
5
6
|
export interface Element {
|
|
6
7
|
value: number | string
|
|
@@ -10,13 +11,18 @@ export interface Element {
|
|
|
10
11
|
const CTimePickerRollCol = defineComponent({
|
|
11
12
|
name: 'CTimePickerRollCol',
|
|
12
13
|
props: {
|
|
14
|
+
ariaLabel: String,
|
|
15
|
+
columnIndex: Number,
|
|
16
|
+
columnRefs: {
|
|
17
|
+
type: Array as PropType<(HTMLElement | null)[]>,
|
|
18
|
+
default: () => [],
|
|
19
|
+
},
|
|
13
20
|
elements: {
|
|
14
21
|
type: Array as PropType<Element[]>,
|
|
15
22
|
required: true,
|
|
16
23
|
},
|
|
17
|
-
selected:
|
|
18
|
-
|
|
19
|
-
},
|
|
24
|
+
selected: [Number, String, null],
|
|
25
|
+
setColumnRef: Function as PropType<(index: number, el: HTMLElement | null) => void>,
|
|
20
26
|
},
|
|
21
27
|
emits: ['click'],
|
|
22
28
|
setup(props, { emit }) {
|
|
@@ -29,7 +35,7 @@ const CTimePickerRollCol = defineComponent({
|
|
|
29
35
|
if (isVisible.value && nodeEl && nodeEl instanceof HTMLElement) {
|
|
30
36
|
colRef.value?.scrollTo({
|
|
31
37
|
top: nodeEl.offsetTop,
|
|
32
|
-
behavior: init.value ? '
|
|
38
|
+
behavior: init.value ? 'instant' : 'smooth',
|
|
33
39
|
})
|
|
34
40
|
}
|
|
35
41
|
}
|
|
@@ -42,35 +48,107 @@ const CTimePickerRollCol = defineComponent({
|
|
|
42
48
|
}
|
|
43
49
|
})
|
|
44
50
|
|
|
51
|
+
watch(colRef, () => {
|
|
52
|
+
if (props.columnIndex !== undefined && props.setColumnRef) {
|
|
53
|
+
props.setColumnRef(props.columnIndex, colRef.value || null)
|
|
54
|
+
}
|
|
55
|
+
}, { immediate: true })
|
|
56
|
+
|
|
45
57
|
onUpdated(() => {
|
|
46
58
|
scrollToSelectedElement()
|
|
47
59
|
})
|
|
48
60
|
|
|
61
|
+
const moveFocusToNextColumn = () => {
|
|
62
|
+
if (!props.columnRefs || props.columnIndex === undefined) return
|
|
63
|
+
|
|
64
|
+
if (props.columnIndex < props.columnRefs.length - 1) {
|
|
65
|
+
const column = props.columnRefs[props.columnIndex + 1]
|
|
66
|
+
const focusableCell = column?.querySelector('.time-picker-roll-cell[tabindex="0"]') as HTMLElement
|
|
67
|
+
focusableCell?.focus()
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const moveFocusToPreviousColumn = () => {
|
|
72
|
+
if (!props.columnRefs || props.columnIndex === undefined) return
|
|
73
|
+
|
|
74
|
+
if (props.columnIndex > 0) {
|
|
75
|
+
const column = props.columnRefs[props.columnIndex - 1]
|
|
76
|
+
const focusableCell = column?.querySelector('.time-picker-roll-cell[tabindex="0"]') as HTMLElement
|
|
77
|
+
focusableCell?.focus()
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
49
81
|
const handleKeyDown = (event: KeyboardEvent, value: number | string) => {
|
|
50
82
|
if (event.code === 'Space' || event.key === 'Enter') {
|
|
51
83
|
event.preventDefault()
|
|
52
84
|
emit('click', value)
|
|
85
|
+
moveFocusToNextColumn()
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (colRef.value && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
|
|
90
|
+
event.preventDefault()
|
|
91
|
+
const target = event.target as HTMLElement
|
|
92
|
+
const items = [...colRef.value.querySelectorAll('.time-picker-roll-cell')] as HTMLElement[]
|
|
93
|
+
|
|
94
|
+
getNextActiveElement(items, target, event.key === 'ArrowDown', true).focus()
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (colRef.value && (event.key === 'Home' || event.key === 'End')) {
|
|
99
|
+
event.preventDefault()
|
|
100
|
+
const items = [...colRef.value.querySelectorAll('.time-picker-roll-cell')] as HTMLElement[]
|
|
101
|
+
const index = event.key === 'Home' ? 0 : items.length - 1
|
|
102
|
+
items[index]?.focus()
|
|
103
|
+
return
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (colRef.value && (event.key === 'ArrowLeft' || event.key === 'ArrowRight')) {
|
|
107
|
+
event.preventDefault()
|
|
108
|
+
const rtl = isRTL(colRef.value)
|
|
109
|
+
const shouldGoLeft =
|
|
110
|
+
(event.key === 'ArrowLeft' && !rtl) || (event.key === 'ArrowRight' && rtl)
|
|
111
|
+
if (shouldGoLeft) {
|
|
112
|
+
moveFocusToPreviousColumn()
|
|
113
|
+
} else {
|
|
114
|
+
moveFocusToNextColumn()
|
|
115
|
+
}
|
|
53
116
|
}
|
|
54
117
|
}
|
|
55
118
|
|
|
56
119
|
return () =>
|
|
57
120
|
h(
|
|
58
121
|
'div',
|
|
59
|
-
{
|
|
60
|
-
|
|
122
|
+
{
|
|
123
|
+
class: 'time-picker-roll-col',
|
|
124
|
+
onFocusout: (event: FocusEvent) => {
|
|
125
|
+
const currentTarget = event.currentTarget as HTMLElement
|
|
126
|
+
const relatedTarget = event.relatedTarget as HTMLElement | null
|
|
127
|
+
if (currentTarget && (!relatedTarget || !currentTarget.contains(relatedTarget))) {
|
|
128
|
+
scrollToSelectedElement()
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
ref: colRef,
|
|
132
|
+
role: 'listbox',
|
|
133
|
+
'aria-label': props.ariaLabel,
|
|
134
|
+
},
|
|
135
|
+
props.elements.map((element, index) => {
|
|
136
|
+
const isSelected = element.value === props.selected
|
|
61
137
|
return h(
|
|
62
138
|
'div',
|
|
63
139
|
{
|
|
64
140
|
class: [
|
|
65
141
|
'time-picker-roll-cell',
|
|
66
142
|
{
|
|
67
|
-
selected:
|
|
143
|
+
selected: isSelected,
|
|
68
144
|
},
|
|
69
145
|
],
|
|
70
146
|
onClick: () => emit('click', element.value),
|
|
71
147
|
onKeydown: (event: KeyboardEvent) => handleKeyDown(event, element.value),
|
|
72
|
-
role: '
|
|
73
|
-
tabindex: 0,
|
|
148
|
+
role: 'option',
|
|
149
|
+
tabindex: isSelected ? 0 : props.selected ? -1 : index === 0 ? 0 : -1,
|
|
150
|
+
'aria-label': element.label.toString(),
|
|
151
|
+
'aria-selected': isSelected,
|
|
74
152
|
},
|
|
75
153
|
element.label
|
|
76
154
|
)
|