diff --git a/__test__/__snapshots__/date-picker.test.js.snap b/__test__/__snapshots__/date-picker.test.js.snap index f60a4c5f..a2bce5cf 100644 --- a/__test__/__snapshots__/date-picker.test.js.snap +++ b/__test__/__snapshots__/date-picker.test.js.snap @@ -159,6 +159,8 @@ exports[`DatePicker prop: formatter 1`] = `
{{ day }} | - +||
---|---|---|
{{ cell.getDate() }}
|
@@ -111,6 +125,10 @@ export default {
type: Date,
default: () => new Date(),
},
+ isDisabled: {
+ type: Function,
+ default: () => false,
+ },
showWeekNumber: {
type: Boolean,
default: false,
@@ -127,6 +145,14 @@ export default {
type: Function,
default: () => [],
},
+ range: {
+ type: Boolean,
+ default: false,
+ },
+ rangeIndex: {
+ type: Number,
+ default: 0,
+ },
},
computed: {
firstDayOfWeek() {
@@ -159,6 +185,15 @@ export default {
});
return chunk(arr, 7);
},
+ locale() {
+ return this.getLocale();
+ },
+ refsArray() {
+ if (this.$refs) {
+ return Object.entries(this.$refs);
+ }
+ return [];
+ },
},
methods: {
isDisabledArrows(type) {
@@ -183,6 +218,96 @@ export default {
}
return this.disabledCalendarChanger(date, type);
},
+ handleArrowUp(cell, row, column) {
+ if (row === 0) {
+ return;
+ }
+ const refName = this.handleRefName(cell, row - 1, column);
+ const ref = this.$refs[refName]?.[0];
+ if (ref) {
+ ref.focus();
+ }
+ },
+ handleArrowDown(cell, row, column) {
+ if (row === this.dates.length - 1) {
+ return;
+ }
+ const refName = this.handleRefName(cell, row + 1, column);
+ const ref = this.$refs[refName]?.[0];
+ if (ref) {
+ ref.focus();
+ }
+ },
+ handleArrowLeft(cell, row, column) {
+ const currentRefName = this.handleRefName(cell, row, column);
+ const firstRef = this.refsArray[0];
+ if (currentRefName !== firstRef[0]) {
+ const refName = this.handleRefName(cell, row, column - 1);
+ const ref = this.$refs[refName]?.[0];
+ if (ref) {
+ ref.focus();
+ }
+ } else if (this.range) {
+ let index = 0;
+ if (this.rangeIndex === 0) {
+ this.handleIconLeftClick();
+ } else {
+ index = this.rangeIndex - 1;
+ }
+ const lastRow = this.dates[this.dates.length - 1];
+ const cellName = `#range-date-${index}-cell-${this.dates.length - 1}-${lastRow.length - 1}`;
+ const cellElement = document.querySelector(cellName);
+ if (cellElement) {
+ cellElement.focus();
+ }
+ } else {
+ this.$nextTick(() => {
+ this.handleIconLeftClick();
+ const lastRef = this.refsArray[this.refsArray.length - 1];
+ if (lastRef.length) {
+ const element = lastRef[1];
+ if (element.length) {
+ element[0].focus();
+ }
+ }
+ });
+ }
+ },
+ handleArrowRight(cell, row, column) {
+ const currentRefName = this.handleRefName(cell, row, column);
+ const lastRef = this.refsArray[this.refsArray.length - 1];
+ if (currentRefName !== lastRef[0]) {
+ const refName = this.handleRefName(cell, row, column + 1);
+ const ref = this.$refs[refName]?.[0];
+ if (ref) {
+ ref.focus();
+ }
+ } else if (this.range) {
+ let index = 0;
+ if (this.rangeIndex === 0) {
+ index = this.rangeIndex + 1;
+ } else {
+ index = this.rangeIndex - 1;
+ this.handleIconRightClick();
+ }
+ const cellName = `#range-date-${index}-cell-0-0`;
+ const cellElement = document.querySelector(cellName);
+ if (cellElement) {
+ cellElement.focus();
+ }
+ } else {
+ this.$nextTick(() => {
+ this.handleIconLeftClick();
+ const firstRef = this.refsArray[0];
+ if (firstRef.length) {
+ const element = firstRef[1];
+ if (element.length) {
+ element[0].focus();
+ }
+ }
+ });
+ }
+ },
handleIconLeftClick() {
this.$emit(
'changecalendar',
@@ -246,6 +371,25 @@ export default {
getWeekNumber(date) {
return this.getWeek(date, this.getLocale().formatLocale);
},
+ handleRefName(cellDate, row, col) {
+ if (!this.isDisabled(cellDate)) {
+ if (this.range) {
+ return `range-date-${this.rangeIndex}-cell-${row}-${col}`;
+ }
+ return `date-cell-${row}-${col}`;
+ }
+ return undefined;
+ },
+ handleId(row, col) {
+ if (this.range) {
+ return `range-date-${this.rangeIndex}-cell-${row}-${col}`;
+ }
+ return undefined;
+ },
+ handleTabIndex(cellDate) {
+ const response = this.isDisabled(cellDate);
+ return response ? -1 : 0;
+ },
},
};
diff --git a/src/calendar/table-month.vue b/src/calendar/table-month.vue
index 21f940a9..c58a5e63 100644
--- a/src/calendar/table-month.vue
+++ b/src/calendar/table-month.vue
@@ -3,14 +3,10 @@
{{ cell.text }}
|
@@ -43,7 +58,7 @@
import { chunk } from '../util/base';
import IconButton from './icon-button';
import { getLocale } from '../locale';
-import { setYear } from '../util/date';
+import { createDate, setYear } from '../util/date';
export default {
name: 'TableMonth',
@@ -69,19 +84,32 @@ export default {
type: Function,
default: () => [],
},
+ isDisabled: {
+ type: Function,
+ default: () => false,
+ },
},
computed: {
calendarYear() {
return this.calendar.getFullYear();
},
months() {
- const locale = this.getLocale();
+ const { locale } = this;
const monthsLocale = locale.months || locale.formatLocale.monthsShort;
const months = monthsLocale.map((text, month) => {
return { text, month };
});
return chunk(months, 3);
},
+ locale() {
+ return this.getLocale();
+ },
+ refsArray() {
+ if (this.$refs) {
+ return Object.entries(this.$refs);
+ }
+ return [];
+ },
},
methods: {
isDisabledArrows(type) {
@@ -99,6 +127,66 @@ export default {
}
return this.disabledCalendarChanger(date, type);
},
+ handleArrowUp(cell, row, column) {
+ if (row === 0) {
+ return;
+ }
+ const refName = this.handleRefName(cell, row - 1, column);
+ const ref = this.$refs[refName]?.[0];
+ if (ref) {
+ ref.focus();
+ }
+ },
+ handleArrowDown(cell, row, column) {
+ if (row === this.months.length - 1) {
+ return;
+ }
+ const refName = this.handleRefName(cell, row + 1, column);
+ const ref = this.$refs[refName]?.[0];
+ if (ref) {
+ ref.focus();
+ }
+ },
+ handleArrowLeft(cell, row, column) {
+ const currentRefName = this.handleRefName(cell, row, column);
+ const firstRef = this.refsArray[0];
+ if (currentRefName !== firstRef[0]) {
+ const refName = this.handleRefName(cell, row, column - 1);
+ const ref = this.$refs[refName]?.[0];
+ if (ref) {
+ ref.focus();
+ }
+ } else {
+ this.handleIconDoubleLeftClick();
+ const lastRef = this.refsArray[this.refsArray.length - 1];
+ if (lastRef.length) {
+ const element = lastRef[1];
+ if (element.length) {
+ element[0].focus();
+ }
+ }
+ }
+ },
+ handleArrowRight(cell, row, column) {
+ const currentRefName = this.handleRefName(cell, row, column);
+ const lastRef = this.refsArray[this.refsArray.length - 1];
+ if (currentRefName !== lastRef[0]) {
+ const refName = this.handleRefName(cell, row, column + 1);
+ const ref = this.$refs[refName]?.[0];
+ if (ref) {
+ ref.focus();
+ }
+ } else {
+ this.handleIconDoubleRightClick();
+ const firstRef = this.refsArray[0];
+ if (firstRef.length) {
+ const element = firstRef[1];
+ if (element.length) {
+ element[0].focus();
+ }
+ }
+ }
+ },
handleIconDoubleLeftClick() {
this.$emit(
'changecalendar',
@@ -126,6 +214,17 @@ export default {
this.$emit('select', parseInt(month, 10));
}
},
+ handleRefName(cellDate, row, col) {
+ const date = createDate(cellDate, 0);
+ if (!this.isDisabled(date)) {
+ return `year-cell-${row}-${col}`;
+ }
+ return undefined;
+ },
+ handleTabIndex(cellDate) {
+ const date = createDate(cellDate, 0);
+ return this.isDisabled(date) ? -1 : 0;
+ },
},
};
diff --git a/src/calendar/table-year.vue b/src/calendar/table-year.vue
index dbf9c8d9..99f1647b 100644
--- a/src/calendar/table-year.vue
+++ b/src/calendar/table-year.vue
@@ -3,29 +3,44 @@
{{ cell }}
|
@@ -38,12 +53,16 @@
diff --git a/src/style/btn.scss b/src/style/btn.scss
index f8e90e95..b8c219b7 100644
--- a/src/style/btn.scss
+++ b/src/style/btn.scss
@@ -9,7 +9,6 @@
margin: 0;
cursor: pointer;
background-color: transparent;
- outline: none;
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: 4px;
color: $default-color;
@@ -28,6 +27,11 @@
.#{$namespace}-btn-text {
border: 0;
padding: 0 4px;
- text-align: left;
+ text-align: center;
line-height: inherit;
+ min-width: 32px;
+
+ &:focus-visible {
+ outline-offset: -1px;
+ }
}
diff --git a/src/style/index.scss b/src/style/index.scss
index 6ba834cc..728129d6 100644
--- a/src/style/index.scss
+++ b/src/style/index.scss
@@ -63,8 +63,23 @@
}
}
-.#{$namespace}-icon-calendar,
-.#{$namespace}-icon-clear {
+
+.#{$namespace}-button-clear{
+ position: absolute;
+ top: 50%;
+ right: 8px;
+ background: #fff;
+ transform: translateY(-50%);
+ border: none;
+ color: rgba(0, 0, 0, 0.5);
+
+ &:hover,
+ &:focus {
+ color: rgba(0, 0, 0, 0.8);
+ }
+}
+
+.#{$namespace}-icon-calendar {
position: absolute;
top: 50%;
right: 8px;
@@ -75,18 +90,16 @@
vertical-align: middle;
}
-.#{$namespace}-icon-clear {
- cursor: pointer;
- &:hover {
- color: rgba(0, 0, 0, 0.8);
- }
-}
.#{$namespace}-datepicker-main {
font: 14px/1.5 'Helvetica Neue', Helvetica, Arial, 'Microsoft Yahei', sans-serif;
color: $default-color;
background-color: #fff;
border: 1px solid $border-color;
+
+ &:focus{
+ outline: none;
+ }
}
.#{$namespace}-datepicker-popup {
@@ -154,15 +167,8 @@
line-height: 34px;
text-align: center;
overflow: hidden;
-}
-
-.#{$namespace}-btn-icon-left,
-.#{$namespace}-btn-icon-double-left {
- float: left;
-}
-.#{$namespace}-btn-icon-right,
-.#{$namespace}-btn-icon-double-right {
- float: right;
+ display: flex;
+ justify-content: space-between;
}
.#{$namespace}-calendar-header-label {
@@ -200,6 +206,9 @@
color: $disabled-color;
background-color: $disabled-background-color;
}
+ &.focus {
+ outline: -webkit-focus-ring-color auto 1px;
+ }
}
}
diff --git a/src/time/list-columns.vue b/src/time/list-columns.vue
index c91634ff..3441906b 100644
--- a/src/time/list-columns.vue
+++ b/src/time/list-columns.vue
@@ -6,12 +6,17 @@
:data-type="col.type"
:data-index="i"
@click="handleSelect"
+ @keydown.enter="handleSelect"
>