@@ -10,7 +10,9 @@ import BaseComponent from './base-component.js'
1010import EventHandler from './dom/event-handler.js'
1111import Manipulator from './dom/manipulator.js'
1212import SelectorEngine from './dom/selector-engine.js'
13- import { defineJQueryPlugin , getElement , isRTL } from './util/index.js'
13+ import {
14+ defineJQueryPlugin , getElement , getNextActiveElement , isRTL
15+ } from './util/index.js'
1416import {
1517 convert12hTo24h ,
1618 convert24hTo12h ,
@@ -33,9 +35,14 @@ const ENTER_KEY = 'Enter'
3335const ESCAPE_KEY = 'Escape'
3436const SPACE_KEY = 'Space'
3537const TAB_KEY = 'Tab'
38+ const ARROW_UP_KEY = 'ArrowUp'
39+ const ARROW_DOWN_KEY = 'ArrowDown'
40+ const ARROW_LEFT_KEY = 'ArrowLeft'
41+ const ARROW_RIGHT_KEY = 'ArrowRight'
3642const RIGHT_MOUSE_BUTTON = 2
3743
3844const EVENT_CLICK = `click${ EVENT_KEY } `
45+ const EVENT_FOCUSOUT = `focusout${ EVENT_KEY } `
3946const EVENT_HIDE = `hide${ EVENT_KEY } `
4047const EVENT_HIDDEN = `hidden${ EVENT_KEY } `
4148const EVENT_INPUT = 'input'
@@ -71,6 +78,9 @@ const CLASS_NAME_WAS_VALIDATED = 'was-validated'
7178const SELECTOR_DATA_TOGGLE =
7279 '[data-coreui-toggle="time-picker"]:not(.disabled):not(:disabled)'
7380const SELECTOR_DATA_TOGGLE_SHOWN = `${ SELECTOR_DATA_TOGGLE } .${ CLASS_NAME_SHOW } `
81+ const SELECTOR_ROLL_CELL = '.time-picker-roll-cell'
82+ const SELECTOR_ROLL_CELL_SELECTED = '.time-picker-roll-cell.selected'
83+ const SELECTOR_ROLL_COL = '.time-picker-roll-col'
7484const SELECTOR_WAS_VALIDATED = 'form.was-validated'
7585
7686const Default = {
@@ -294,6 +304,58 @@ class TimePicker extends BaseComponent {
294304 }
295305 } )
296306
307+ if ( this . _config . variant === 'roll' ) {
308+ EventHandler . on ( this . _timePickerBody , EVENT_FOCUSOUT , SELECTOR_ROLL_COL , ( ) => {
309+ this . _setUpRolls ( false )
310+ } )
311+
312+ EventHandler . on ( this . _timePickerBody , EVENT_KEYDOWN , SELECTOR_ROLL_CELL , event => {
313+ if ( event . key === ARROW_DOWN_KEY || event . key === ARROW_UP_KEY ) {
314+ event . preventDefault ( )
315+ const { key, target } = event
316+ const items = SelectorEngine . find ( SELECTOR_ROLL_CELL , target . parentElement )
317+
318+ if ( ! items . length ) {
319+ return
320+ }
321+
322+ getNextActiveElement ( items , target , key === ARROW_DOWN_KEY , ! items . includes ( target ) ) . focus ( )
323+ }
324+
325+ if ( event . key === ARROW_LEFT_KEY || event . key === ARROW_RIGHT_KEY ) {
326+ event . preventDefault ( )
327+ const { key, target } = event
328+ const columnElement = target . parentElement
329+
330+ if ( this . _timePickerBody ) {
331+ const columns = SelectorEngine . find ( SELECTOR_ROLL_COL , this . _timePickerBody )
332+ const currentColumnIndex = columns . indexOf ( columnElement )
333+
334+ let targetColumnIndex
335+ const isRtl = isRTL ( )
336+ const shouldGoLeft = ( key === ARROW_LEFT_KEY && ! isRtl ) || ( key === ARROW_RIGHT_KEY && isRtl )
337+ if ( shouldGoLeft ) {
338+ targetColumnIndex = currentColumnIndex > 0 ? currentColumnIndex - 1 : columns . length - 1
339+ } else {
340+ targetColumnIndex = currentColumnIndex < columns . length - 1 ? currentColumnIndex + 1 : 0
341+ }
342+
343+ const targetColumn = columns [ targetColumnIndex ]
344+ const selectedCell = SelectorEngine . findOne ( SELECTOR_ROLL_CELL_SELECTED , targetColumn )
345+
346+ if ( selectedCell ) {
347+ selectedCell . focus ( )
348+ return
349+ }
350+
351+ const firstFocusableCell = SelectorEngine . findOne ( SELECTOR_ROLL_CELL , targetColumn )
352+
353+ firstFocusableCell . focus ( )
354+ }
355+ }
356+ } )
357+ }
358+
297359 EventHandler . on ( this . _element , EVENT_KEYDOWN , event => {
298360 if ( event . key === ESCAPE_KEY ) {
299361 this . hide ( )
0 commit comments