@@ -187,6 +187,10 @@ export const BCalendar = Vue.extend({
187
187
type : String
188
188
// default: null
189
189
} ,
190
+ noKeyNav : {
191
+ type : Boolean ,
192
+ default : false
193
+ } ,
190
194
roleDescription : {
191
195
type : String
192
196
// default: null
@@ -382,9 +386,8 @@ export const BCalendar = Vue.extend({
382
386
return isLocaleRTL ( this . computedLocale )
383
387
} ,
384
388
context ( ) {
385
- const selectedYMD = this . selectedYMD
389
+ const { selectedYMD, activeYMD } = this
386
390
const selectedDate = parseYMD ( selectedYMD )
387
- const activeYMD = this . activeYMD
388
391
const activeDate = parseYMD ( activeYMD )
389
392
return {
390
393
// The current value of the `v-model`
@@ -408,11 +411,10 @@ export const BCalendar = Vue.extend({
408
411
// Computed props that return a function reference
409
412
dateOutOfRange ( ) {
410
413
// 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
412
415
// We do this as we need to trigger the calendar computed prop
413
416
// to update when these props update
414
- const min = this . computedMin
415
- const max = this . computedMax
417
+ const { computedMin : min , computedMax : max } = this
416
418
return date => {
417
419
// Handle both `YYYY-MM-DD` and `Date` objects
418
420
date = parseYMD ( date )
@@ -676,6 +678,10 @@ export const BCalendar = Vue.extend({
676
678
// Calendar keyboard navigation
677
679
// Handles PAGEUP/PAGEDOWN/END/HOME/LEFT/UP/RIGHT/DOWN
678
680
// Focuses grid after updating
681
+ if ( this . noKeyNav ) {
682
+ /* istanbul ignore next */
683
+ return
684
+ }
679
685
const { altKey, ctrlKey, keyCode } = evt
680
686
if (
681
687
! arrayIncludes (
@@ -769,8 +775,7 @@ export const BCalendar = Vue.extend({
769
775
} ,
770
776
onClickDay ( day ) {
771
777
// Clicking on a date "button" to select it
772
- const selectedDate = this . selectedDate
773
- const activeDate = this . activeDate
778
+ const { selectedDate, activeDate } = this
774
779
const clickedDate = parseYMD ( day . ymd )
775
780
if ( ! this . disabled && ! day . isDisabled && ! this . dateDisabled ( clickedDate ) ) {
776
781
if ( ! this . readonly ) {
@@ -831,6 +836,8 @@ export const BCalendar = Vue.extend({
831
836
gridCaptionId,
832
837
gridHelpId,
833
838
activeId,
839
+ disabled,
840
+ noKeyNav,
834
841
isLive,
835
842
isRTL,
836
843
activeYMD,
@@ -846,12 +853,12 @@ export const BCalendar = Vue.extend({
846
853
'output' ,
847
854
{
848
855
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 } ,
850
857
attrs : {
851
858
id : valueId ,
852
859
for : gridId ,
853
860
role : 'status' ,
854
- tabindex : this . disabled ? null : '-1' ,
861
+ tabindex : disabled ? null : '-1' ,
855
862
// Mainly for testing purposes, as we do not know
856
863
// the exact format `Intl` will format the date string
857
864
'data-selected' : toString ( selectedYMD ) ,
@@ -920,6 +927,7 @@ export const BCalendar = Vue.extend({
920
927
attrs : {
921
928
title : label || null ,
922
929
type : 'button' ,
930
+ tabindex : noKeyNav ? '-1' : null ,
923
931
'aria-label' : label || null ,
924
932
'aria-disabled' : btnDisabled ? 'true' : null ,
925
933
'aria-keyshortcuts' : shortcut || null
@@ -938,7 +946,8 @@ export const BCalendar = Vue.extend({
938
946
attrs : {
939
947
id : navId ,
940
948
role : 'group' ,
941
- 'aria-hidden' : this . disabled ? 'true' : null ,
949
+ tabindex : noKeyNav ? '-1' : null ,
950
+ 'aria-hidden' : disabled ? 'true' : null ,
942
951
'aria-label' : this . labelNav || null ,
943
952
'aria-controls' : gridId
944
953
}
@@ -1006,7 +1015,7 @@ export const BCalendar = Vue.extend({
1006
1015
{
1007
1016
key : 'grid-caption' ,
1008
1017
staticClass : 'b-calendar-grid-caption text-center font-weight-bold' ,
1009
- class : { 'text-muted' : this . disabled } ,
1018
+ class : { 'text-muted' : disabled } ,
1010
1019
attrs : {
1011
1020
id : gridCaptionId ,
1012
1021
'aria-live' : isLive ? 'polite' : null ,
@@ -1029,7 +1038,7 @@ export const BCalendar = Vue.extend({
1029
1038
{
1030
1039
key : idx ,
1031
1040
staticClass : 'col text-truncate' ,
1032
- class : { 'text-muted' : this . disabled } ,
1041
+ class : { 'text-muted' : disabled } ,
1033
1042
attrs : {
1034
1043
title : d . label === d . text ? null : d . label ,
1035
1044
'aria-label' : d . label
@@ -1057,7 +1066,7 @@ export const BCalendar = Vue.extend({
1057
1066
// Give the fake button a focus ring
1058
1067
focus : isActive && this . gridHasFocus ,
1059
1068
// Styling
1060
- disabled : day . isDisabled || this . disabled ,
1069
+ disabled : day . isDisabled || disabled ,
1061
1070
active : isSelected , // makes the button look "pressed"
1062
1071
// Selected date style (need to computed from variant)
1063
1072
[ this . computedVariant ] : isSelected ,
@@ -1089,7 +1098,7 @@ export const BCalendar = Vue.extend({
1089
1098
'data-date' : day . ymd , // Primarily for testing purposes
1090
1099
// Only days in the month are presented as buttons to screen readers
1091
1100
'aria-hidden' : day . isThisMonth ? null : 'true' ,
1092
- 'aria-disabled' : day . isDisabled || this . disabled ? 'true' : null ,
1101
+ 'aria-disabled' : day . isDisabled || disabled ? 'true' : null ,
1093
1102
'aria-label' : [
1094
1103
day . label ,
1095
1104
isSelected ? `(${ this . labelSelected } )` : null ,
@@ -1118,7 +1127,7 @@ export const BCalendar = Vue.extend({
1118
1127
// A key is only required on the body if we add in transition support
1119
1128
// key: this.activeYMD.slice(0, -3),
1120
1129
staticClass : 'b-calendar-grid-body' ,
1121
- style : this . disabled ? { pointerEvents : 'none' } : { }
1130
+ style : disabled ? { pointerEvents : 'none' } : { }
1122
1131
} ,
1123
1132
$gridBody
1124
1133
)
@@ -1142,15 +1151,15 @@ export const BCalendar = Vue.extend({
1142
1151
attrs : {
1143
1152
id : gridId ,
1144
1153
role : 'application' ,
1145
- tabindex : this . disabled ? null : '0' ,
1154
+ tabindex : noKeyNav ? '-1' : disabled ? null : '0' ,
1146
1155
'data-month' : activeYMD . slice ( 0 , - 3 ) , // `YYYY-MM`, mainly for testing
1147
1156
'aria-roledescription' : this . labelCalendar || null ,
1148
1157
'aria-labelledby' : gridCaptionId ,
1149
1158
'aria-describedby' : gridHelpId ,
1150
1159
// `aria-readonly` is not considered valid on `role="application"`
1151
1160
// 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 ,
1154
1163
'aria-activedescendant' : activeId
1155
1164
} ,
1156
1165
on : {
@@ -1176,7 +1185,7 @@ export const BCalendar = Vue.extend({
1176
1185
dir : isRTL ? 'rtl' : 'ltr' ,
1177
1186
lang : this . computedLocale || null ,
1178
1187
role : 'group' ,
1179
- 'aria-disabled' : this . disabled ? 'true' : null ,
1188
+ 'aria-disabled' : disabled ? 'true' : null ,
1180
1189
// If datepicker controls an input, this will specify the ID of the input
1181
1190
'aria-controls' : this . ariaControls || null ,
1182
1191
// This should be a prop (so it can be changed to Date picker, etc, localized
0 commit comments