@@ -187,6 +187,10 @@ export const BCalendar = Vue.extend({
187187 type : String
188188 // default: null
189189 } ,
190+ noKeyNav : {
191+ type : Boolean ,
192+ default : false
193+ } ,
190194 roleDescription : {
191195 type : String
192196 // default: null
@@ -382,9 +386,8 @@ export const BCalendar = Vue.extend({
382386 return isLocaleRTL ( this . computedLocale )
383387 } ,
384388 context ( ) {
385- const selectedYMD = this . selectedYMD
389+ const { selectedYMD, activeYMD } = this
386390 const selectedDate = parseYMD ( selectedYMD )
387- const activeYMD = this . activeYMD
388391 const activeDate = parseYMD ( activeYMD )
389392 return {
390393 // The current value of the `v-model`
@@ -408,11 +411,10 @@ export const BCalendar = Vue.extend({
408411 // Computed props that return a function reference
409412 dateOutOfRange ( ) {
410413 // Check whether a date is within the min/max range
411- // returns a new function ref if the pops change
414+ // Returns a new function ref if the pops change
412415 // We do this as we need to trigger the calendar computed prop
413416 // to update when these props update
414- const min = this . computedMin
415- const max = this . computedMax
417+ const { computedMin : min , computedMax : max } = this
416418 return date => {
417419 // Handle both `YYYY-MM-DD` and `Date` objects
418420 date = parseYMD ( date )
@@ -676,6 +678,10 @@ export const BCalendar = Vue.extend({
676678 // Calendar keyboard navigation
677679 // Handles PAGEUP/PAGEDOWN/END/HOME/LEFT/UP/RIGHT/DOWN
678680 // Focuses grid after updating
681+ if ( this . noKeyNav ) {
682+ /* istanbul ignore next */
683+ return
684+ }
679685 const { altKey, ctrlKey, keyCode } = evt
680686 if (
681687 ! arrayIncludes (
@@ -769,8 +775,7 @@ export const BCalendar = Vue.extend({
769775 } ,
770776 onClickDay ( day ) {
771777 // Clicking on a date "button" to select it
772- const selectedDate = this . selectedDate
773- const activeDate = this . activeDate
778+ const { selectedDate, activeDate } = this
774779 const clickedDate = parseYMD ( day . ymd )
775780 if ( ! this . disabled && ! day . isDisabled && ! this . dateDisabled ( clickedDate ) ) {
776781 if ( ! this . readonly ) {
@@ -831,6 +836,8 @@ export const BCalendar = Vue.extend({
831836 gridCaptionId,
832837 gridHelpId,
833838 activeId,
839+ disabled,
840+ noKeyNav,
834841 isLive,
835842 isRTL,
836843 activeYMD,
@@ -846,12 +853,12 @@ export const BCalendar = Vue.extend({
846853 'output' ,
847854 {
848855 staticClass : 'form-control form-control-sm text-center' ,
849- class : { 'text-muted' : this . disabled , readonly : this . readonly || this . disabled } ,
856+ class : { 'text-muted' : disabled , readonly : this . readonly || disabled } ,
850857 attrs : {
851858 id : valueId ,
852859 for : gridId ,
853860 role : 'status' ,
854- tabindex : this . disabled ? null : '-1' ,
861+ tabindex : disabled ? null : '-1' ,
855862 // Mainly for testing purposes, as we do not know
856863 // the exact format `Intl` will format the date string
857864 'data-selected' : toString ( selectedYMD ) ,
@@ -920,6 +927,7 @@ export const BCalendar = Vue.extend({
920927 attrs : {
921928 title : label || null ,
922929 type : 'button' ,
930+ tabindex : noKeyNav ? '-1' : null ,
923931 'aria-label' : label || null ,
924932 'aria-disabled' : btnDisabled ? 'true' : null ,
925933 'aria-keyshortcuts' : shortcut || null
@@ -938,7 +946,8 @@ export const BCalendar = Vue.extend({
938946 attrs : {
939947 id : navId ,
940948 role : 'group' ,
941- 'aria-hidden' : this . disabled ? 'true' : null ,
949+ tabindex : noKeyNav ? '-1' : null ,
950+ 'aria-hidden' : disabled ? 'true' : null ,
942951 'aria-label' : this . labelNav || null ,
943952 'aria-controls' : gridId
944953 }
@@ -1006,7 +1015,7 @@ export const BCalendar = Vue.extend({
10061015 {
10071016 key : 'grid-caption' ,
10081017 staticClass : 'b-calendar-grid-caption text-center font-weight-bold' ,
1009- class : { 'text-muted' : this . disabled } ,
1018+ class : { 'text-muted' : disabled } ,
10101019 attrs : {
10111020 id : gridCaptionId ,
10121021 'aria-live' : isLive ? 'polite' : null ,
@@ -1029,7 +1038,7 @@ export const BCalendar = Vue.extend({
10291038 {
10301039 key : idx ,
10311040 staticClass : 'col text-truncate' ,
1032- class : { 'text-muted' : this . disabled } ,
1041+ class : { 'text-muted' : disabled } ,
10331042 attrs : {
10341043 title : d . label === d . text ? null : d . label ,
10351044 'aria-label' : d . label
@@ -1057,7 +1066,7 @@ export const BCalendar = Vue.extend({
10571066 // Give the fake button a focus ring
10581067 focus : isActive && this . gridHasFocus ,
10591068 // Styling
1060- disabled : day . isDisabled || this . disabled ,
1069+ disabled : day . isDisabled || disabled ,
10611070 active : isSelected , // makes the button look "pressed"
10621071 // Selected date style (need to computed from variant)
10631072 [ this . computedVariant ] : isSelected ,
@@ -1089,7 +1098,7 @@ export const BCalendar = Vue.extend({
10891098 'data-date' : day . ymd , // Primarily for testing purposes
10901099 // Only days in the month are presented as buttons to screen readers
10911100 'aria-hidden' : day . isThisMonth ? null : 'true' ,
1092- 'aria-disabled' : day . isDisabled || this . disabled ? 'true' : null ,
1101+ 'aria-disabled' : day . isDisabled || disabled ? 'true' : null ,
10931102 'aria-label' : [
10941103 day . label ,
10951104 isSelected ? `(${ this . labelSelected } )` : null ,
@@ -1118,7 +1127,7 @@ export const BCalendar = Vue.extend({
11181127 // A key is only required on the body if we add in transition support
11191128 // key: this.activeYMD.slice(0, -3),
11201129 staticClass : 'b-calendar-grid-body' ,
1121- style : this . disabled ? { pointerEvents : 'none' } : { }
1130+ style : disabled ? { pointerEvents : 'none' } : { }
11221131 } ,
11231132 $gridBody
11241133 )
@@ -1142,15 +1151,15 @@ export const BCalendar = Vue.extend({
11421151 attrs : {
11431152 id : gridId ,
11441153 role : 'application' ,
1145- tabindex : this . disabled ? null : '0' ,
1154+ tabindex : noKeyNav ? '-1' : disabled ? null : '0' ,
11461155 'data-month' : activeYMD . slice ( 0 , - 3 ) , // `YYYY-MM`, mainly for testing
11471156 'aria-roledescription' : this . labelCalendar || null ,
11481157 'aria-labelledby' : gridCaptionId ,
11491158 'aria-describedby' : gridHelpId ,
11501159 // `aria-readonly` is not considered valid on `role="application"`
11511160 // https://www.w3.org/TR/wai-aria-1.1/#aria-readonly
1152- // 'aria-readonly': this.readonly && !this. disabled ? 'true' : null,
1153- 'aria-disabled' : this . disabled ? 'true' : null ,
1161+ // 'aria-readonly': this.readonly && !disabled ? 'true' : null,
1162+ 'aria-disabled' : disabled ? 'true' : null ,
11541163 'aria-activedescendant' : activeId
11551164 } ,
11561165 on : {
@@ -1176,7 +1185,7 @@ export const BCalendar = Vue.extend({
11761185 dir : isRTL ? 'rtl' : 'ltr' ,
11771186 lang : this . computedLocale || null ,
11781187 role : 'group' ,
1179- 'aria-disabled' : this . disabled ? 'true' : null ,
1188+ 'aria-disabled' : disabled ? 'true' : null ,
11801189 // If datepicker controls an input, this will specify the ID of the input
11811190 'aria-controls' : this . ariaControls || null ,
11821191 // This should be a prop (so it can be changed to Date picker, etc, localized
0 commit comments