@ditojs/ui 3.2.6 → 3.3.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/dist/dito-ui.css +1 -1
- package/dist/dito-ui.es.js +1350 -3294
- package/dist/dito-ui.umd.js +1 -7
- package/package.json +15 -9
- package/src/components/DitoButton.vue +91 -16
- package/src/components/DitoCalendar.vue +318 -248
- package/src/components/DitoDatePicker.vue +36 -147
- package/src/components/DitoDateTimePicker.vue +75 -181
- package/src/components/DitoInput.vue +5 -3
- package/src/components/DitoMenuButton.vue +226 -0
- package/src/components/DitoPagination.vue +9 -3
- package/src/components/DitoPickerInput.vue +285 -0
- package/src/components/DitoSwitch.vue +4 -6
- package/src/components/DitoTimePanel.vue +264 -0
- package/src/components/DitoTimePicker.vue +47 -454
- package/src/components/DitoTrigger.vue +250 -89
- package/src/components/index.js +1 -0
- package/src/styles/components/_resize.scss +8 -0
- package/src/styles/mixins/_input.scss +6 -0
- package/src/utils/button.js +24 -0
- package/src/utils/date.js +18 -0
- package/src/utils/event.js +18 -9
- package/src/utils/index.js +1 -0
- package/src/utils/time.js +107 -0
|
@@ -10,62 +10,70 @@
|
|
|
10
10
|
v-if="currentMode === 'day'"
|
|
11
11
|
)
|
|
12
12
|
.dito-calendar-header
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
tabindex="0"
|
|
13
|
+
button.dito-calendar-step-prev.dito-calendar-step-year(
|
|
14
|
+
type="button"
|
|
16
15
|
aria-label="Previous year"
|
|
17
16
|
@click="stepYear(-1)"
|
|
18
17
|
)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
tabindex="0"
|
|
18
|
+
button.dito-calendar-step-prev.dito-calendar-step-month(
|
|
19
|
+
type="button"
|
|
22
20
|
aria-label="Previous month"
|
|
23
21
|
@click="stepMonth(-1)"
|
|
24
22
|
)
|
|
25
23
|
span
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
tabindex="0"
|
|
24
|
+
button.dito-calendar-select-year(
|
|
25
|
+
type="button"
|
|
29
26
|
aria-label="Switch to year selection"
|
|
30
27
|
@click="setMode('year')"
|
|
31
28
|
) {{ dateToString(currentValue, { year: true }) }}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
tabindex="0"
|
|
29
|
+
button.dito-calendar-select-month(
|
|
30
|
+
type="button"
|
|
35
31
|
aria-label="Switch to month selection"
|
|
36
32
|
@click="setMode('month')"
|
|
37
33
|
) {{ dateToString(currentValue, { month: true }) }}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
tabindex="0"
|
|
34
|
+
button.dito-calendar-step-next.dito-calendar-step-month(
|
|
35
|
+
type="button"
|
|
41
36
|
aria-label="Next month"
|
|
42
37
|
@click="stepMonth(1)"
|
|
43
38
|
)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
tabindex="0"
|
|
39
|
+
button.dito-calendar-step-next.dito-calendar-step-year(
|
|
40
|
+
type="button"
|
|
47
41
|
aria-label="Next year"
|
|
48
42
|
@click="stepYear(1)"
|
|
49
43
|
)
|
|
50
44
|
.dito-calendar-body
|
|
51
|
-
.dito-calendar-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
45
|
+
.dito-calendar-dates(
|
|
46
|
+
role="grid"
|
|
47
|
+
:aria-label="monthLabel"
|
|
48
|
+
@keydown="onDatesKeyDown"
|
|
49
|
+
)
|
|
50
|
+
.dito-calendar-weekdays(role="row")
|
|
51
|
+
span(
|
|
52
|
+
v-for="weekday in weekdayNames"
|
|
53
|
+
role="columnheader"
|
|
54
|
+
:aria-label="weekday.long"
|
|
55
|
+
) {{ weekday.short }}
|
|
56
|
+
.dito-calendar__week(
|
|
57
|
+
v-for="week in weeks"
|
|
58
|
+
:key="+week[0].date"
|
|
59
|
+
role="row"
|
|
60
|
+
)
|
|
61
|
+
button.dito-calendar__item(
|
|
62
|
+
v-for="item in week"
|
|
63
|
+
:key="+item.date"
|
|
64
|
+
:ref="item.isCursor ? 'cursorItem' : undefined"
|
|
65
|
+
type="button"
|
|
66
|
+
role="gridcell"
|
|
67
|
+
:tabindex="item.isCursor ? 0 : -1"
|
|
68
|
+
:class="item.state && `dito-calendar-item-${item.state}`"
|
|
69
|
+
:aria-label="dateToString(item.date)"
|
|
70
|
+
:aria-selected="item.state === 'active' ? 'true' : 'false'"
|
|
71
|
+
:aria-disabled="item.isDisabled ? 'true' : null"
|
|
72
|
+
@click="selectDay(item.date)"
|
|
73
|
+
) {{ item.date.getDate() }}
|
|
65
74
|
.dito-calendar-footer
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
tabindex="0"
|
|
75
|
+
button.dito-calendar-select-now(
|
|
76
|
+
type="button"
|
|
69
77
|
:aria-label="`Select today (${dateToString(new Date())})`"
|
|
70
78
|
:title="dateToString(new Date())"
|
|
71
79
|
@click="selectDate(new Date())"
|
|
@@ -74,72 +82,81 @@
|
|
|
74
82
|
v-else-if="currentMode === 'month'"
|
|
75
83
|
)
|
|
76
84
|
.dito-calendar-header
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
tabindex="0"
|
|
85
|
+
button.dito-calendar-step-prev(
|
|
86
|
+
type="button"
|
|
80
87
|
aria-label="Previous year"
|
|
81
88
|
@click="stepYear(-1)"
|
|
82
89
|
)
|
|
83
90
|
span
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
tabindex="0"
|
|
91
|
+
button.dito-calendar-select-year(
|
|
92
|
+
type="button"
|
|
87
93
|
aria-label="Switch to year selection"
|
|
88
94
|
@click="setMode('year')"
|
|
89
95
|
) {{ dateToString(currentValue, { year: true }) }}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
tabindex="0"
|
|
96
|
+
button.dito-calendar-step-next(
|
|
97
|
+
type="button"
|
|
93
98
|
aria-label="Next year"
|
|
94
99
|
@click="stepYear(1)"
|
|
95
100
|
)
|
|
96
101
|
.dito-calendar-body
|
|
97
|
-
.dito-calendar-months
|
|
98
|
-
|
|
99
|
-
aria-label="Month"
|
|
100
|
-
)
|
|
101
|
-
span(
|
|
102
|
+
.dito-calendar-months
|
|
103
|
+
button.dito-calendar__item(
|
|
102
104
|
v-for="(month, index) in monthNames"
|
|
105
|
+
:ref="isCurrentMonth(index) ? 'cursorItem' : undefined"
|
|
106
|
+
type="button"
|
|
103
107
|
:class="getMonthClass(index)"
|
|
104
|
-
role="option"
|
|
105
108
|
:aria-label="month.long"
|
|
106
|
-
:aria-
|
|
109
|
+
:aria-pressed="isActiveMonth(index) ? 'true' : 'false'"
|
|
107
110
|
@click="selectMonth(index)"
|
|
108
111
|
) {{ month.short }}
|
|
109
112
|
template(
|
|
110
113
|
v-else-if="currentMode === 'year'"
|
|
111
114
|
)
|
|
112
115
|
.dito-calendar-header
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
tabindex="0"
|
|
116
|
+
button.dito-calendar-step-prev(
|
|
117
|
+
type="button"
|
|
116
118
|
aria-label="Previous decade"
|
|
117
119
|
@click="stepDecade(-1)"
|
|
118
120
|
)
|
|
119
121
|
span {{ decadeToString(currentValue) }}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
tabindex="0"
|
|
122
|
+
button.dito-calendar-step-next(
|
|
123
|
+
type="button"
|
|
123
124
|
aria-label="Next decade"
|
|
124
125
|
@click="stepDecade(1)"
|
|
125
126
|
)
|
|
126
127
|
.dito-calendar-body
|
|
127
|
-
.dito-calendar-years
|
|
128
|
-
|
|
129
|
-
aria-label="Year"
|
|
130
|
-
)
|
|
131
|
-
span(
|
|
128
|
+
.dito-calendar-years
|
|
129
|
+
button.dito-calendar__item(
|
|
132
130
|
v-for="year in yearRange"
|
|
131
|
+
:ref="isCurrentYear(year) ? 'cursorItem' : undefined"
|
|
132
|
+
type="button"
|
|
133
133
|
:class="getYearClass(year)"
|
|
134
|
-
role="option"
|
|
135
134
|
:aria-label="String(year)"
|
|
136
|
-
:aria-
|
|
135
|
+
:aria-pressed="isActiveYear(year) ? 'true' : 'false'"
|
|
137
136
|
@click="selectYear(year)"
|
|
138
137
|
) {{ year }}
|
|
139
138
|
</template>
|
|
140
139
|
|
|
141
140
|
<script>
|
|
142
|
-
import {
|
|
141
|
+
import { asArray } from '@ditojs/utils'
|
|
142
|
+
import { alterDate, stepDate } from '../utils/date.js'
|
|
143
|
+
import { getKeyNavigation } from '../utils/event.js'
|
|
144
|
+
|
|
145
|
+
// Returns the start of the current day, as the date that the calendar shows
|
|
146
|
+
// without a value, so that selecting a day selects it without a time.
|
|
147
|
+
function getStartOfToday() {
|
|
148
|
+
return alterDate(new Date(), {
|
|
149
|
+
hour: 0,
|
|
150
|
+
minute: 0,
|
|
151
|
+
second: 0,
|
|
152
|
+
millisecond: 0
|
|
153
|
+
})
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// The most steps that `navigate()` takes past disabled dates, in any date part
|
|
157
|
+
// (day, month or year), before giving up, as a guard against `disabledDate`
|
|
158
|
+
// disabling every date.
|
|
159
|
+
const maxSkippedDateCount = 366
|
|
143
160
|
|
|
144
161
|
export default {
|
|
145
162
|
emits: ['update:modelValue', 'select'],
|
|
@@ -156,104 +173,182 @@ export default {
|
|
|
156
173
|
return {
|
|
157
174
|
weekdayNames,
|
|
158
175
|
monthNames,
|
|
159
|
-
|
|
160
|
-
yearRange: [],
|
|
161
|
-
currentValue: (
|
|
162
|
-
this.modelValue ||
|
|
163
|
-
// If no value is provided, use current date but clear time fields:
|
|
164
|
-
alterDate(new Date(), { hour: 0, minute: 0, second: 0, millisecond: 0 })
|
|
165
|
-
),
|
|
176
|
+
currentValue: this.modelValue || getStartOfToday(),
|
|
166
177
|
currentMode: this.mode
|
|
167
178
|
}
|
|
168
179
|
},
|
|
169
180
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
181
|
+
computed: {
|
|
182
|
+
// The 42 days of the six weeks shown for the month of `currentValue`.
|
|
183
|
+
dateRange() {
|
|
184
|
+
const { currentValue } = this
|
|
185
|
+
const year = currentValue.getFullYear()
|
|
186
|
+
const month = currentValue.getMonth()
|
|
187
|
+
// The weeks start on Sunday:
|
|
188
|
+
const firstDate = new Date(
|
|
189
|
+
year,
|
|
190
|
+
month,
|
|
191
|
+
1 - new Date(year, month).getDay()
|
|
192
|
+
)
|
|
193
|
+
const isSameDay = (date, other) => (
|
|
194
|
+
!!other &&
|
|
195
|
+
date.getDate() === other.getDate() &&
|
|
196
|
+
date.getMonth() === other.getMonth() &&
|
|
197
|
+
date.getFullYear() === other.getFullYear()
|
|
198
|
+
)
|
|
199
|
+
const now = new Date()
|
|
200
|
+
const items = []
|
|
201
|
+
for (let i = 0; i < 42; i++) {
|
|
202
|
+
const date = new Date(
|
|
203
|
+
firstDate.getFullYear(),
|
|
204
|
+
firstDate.getMonth(),
|
|
205
|
+
firstDate.getDate() + i
|
|
206
|
+
)
|
|
207
|
+
const isDisabled = this.disabledDate(date)
|
|
208
|
+
const state =
|
|
209
|
+
date.getMonth() !== month
|
|
210
|
+
? isDisabled
|
|
211
|
+
? 'disabled'
|
|
212
|
+
: 'gray'
|
|
213
|
+
: isSameDay(date, this.modelValue)
|
|
214
|
+
? 'active'
|
|
215
|
+
: isSameDay(date, now)
|
|
216
|
+
? 'today'
|
|
217
|
+
: isDisabled
|
|
218
|
+
? 'disabled'
|
|
219
|
+
: isSameDay(date, currentValue)
|
|
220
|
+
? 'current'
|
|
221
|
+
: null
|
|
222
|
+
items.push({
|
|
223
|
+
date,
|
|
224
|
+
state,
|
|
225
|
+
isDisabled,
|
|
226
|
+
isCursor: isSameDay(date, currentValue)
|
|
227
|
+
})
|
|
175
228
|
}
|
|
229
|
+
return items
|
|
176
230
|
},
|
|
177
231
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
232
|
+
monthLabel() {
|
|
233
|
+
return this.dateToString(this.currentValue, { year: true, month: true })
|
|
234
|
+
},
|
|
235
|
+
|
|
236
|
+
weeks() {
|
|
237
|
+
const weeks = []
|
|
238
|
+
for (let i = 0; i < this.dateRange.length; i += 7) {
|
|
239
|
+
weeks.push(this.dateRange.slice(i, i + 7))
|
|
181
240
|
}
|
|
241
|
+
return weeks
|
|
182
242
|
},
|
|
183
243
|
|
|
184
|
-
|
|
244
|
+
yearRange() {
|
|
245
|
+
const startYear = this.getFirstYearOfDecade(
|
|
246
|
+
this.currentValue.getFullYear()
|
|
247
|
+
)
|
|
248
|
+
return Array.from({ length: 10 }, (_, index) => startYear + index)
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
|
|
252
|
+
watch: {
|
|
253
|
+
modelValue(to, from) {
|
|
254
|
+
if (+to !== +from) {
|
|
255
|
+
this.currentValue = to || getStartOfToday()
|
|
256
|
+
}
|
|
257
|
+
},
|
|
185
258
|
|
|
186
259
|
mode(mode) {
|
|
187
260
|
this.currentMode = mode
|
|
188
261
|
}
|
|
189
262
|
},
|
|
190
263
|
|
|
191
|
-
mounted() {
|
|
192
|
-
this.updateDateRange()
|
|
193
|
-
},
|
|
194
|
-
|
|
195
264
|
methods: {
|
|
265
|
+
isActiveMonth(month) {
|
|
266
|
+
return (
|
|
267
|
+
!!this.modelValue &&
|
|
268
|
+
month === this.modelValue.getMonth() &&
|
|
269
|
+
this.currentValue.getFullYear() === this.modelValue.getFullYear()
|
|
270
|
+
)
|
|
271
|
+
},
|
|
272
|
+
|
|
273
|
+
isCurrentMonth(month) {
|
|
274
|
+
return month === this.currentValue.getMonth()
|
|
275
|
+
},
|
|
276
|
+
|
|
277
|
+
isActiveYear(year) {
|
|
278
|
+
return !!this.modelValue && year === this.modelValue.getFullYear()
|
|
279
|
+
},
|
|
280
|
+
|
|
281
|
+
isCurrentYear(year) {
|
|
282
|
+
return year === this.currentValue.getFullYear()
|
|
283
|
+
},
|
|
284
|
+
|
|
196
285
|
getMonthClass(month) {
|
|
197
286
|
return {
|
|
198
|
-
'dito-calendar-item-active': (
|
|
199
|
-
|
|
200
|
-
month === this.modelValue.getMonth() &&
|
|
201
|
-
this.currentValue.getFullYear() === this.modelValue.getFullYear()
|
|
202
|
-
),
|
|
203
|
-
'dito-calendar-item-current': month === this.currentValue.getMonth()
|
|
287
|
+
'dito-calendar-item-active': this.isActiveMonth(month),
|
|
288
|
+
'dito-calendar-item-current': this.isCurrentMonth(month)
|
|
204
289
|
}
|
|
205
290
|
},
|
|
206
291
|
|
|
207
292
|
getYearClass(year) {
|
|
208
293
|
return {
|
|
209
|
-
'dito-calendar-item-active': (
|
|
210
|
-
|
|
211
|
-
),
|
|
212
|
-
'dito-calendar-item-current': year === this.currentValue.getFullYear()
|
|
294
|
+
'dito-calendar-item-active': this.isActiveYear(year),
|
|
295
|
+
'dito-calendar-item-current': this.isCurrentYear(year)
|
|
213
296
|
}
|
|
214
297
|
},
|
|
215
298
|
|
|
299
|
+
// Moves the cursor of the calendar to `date`, and also selects it if
|
|
300
|
+
// `update` is true.
|
|
216
301
|
setDate(overrides, update = false) {
|
|
217
|
-
|
|
302
|
+
const date = alterDate(this.currentValue, overrides)
|
|
303
|
+
this.currentValue = date
|
|
218
304
|
if (update) {
|
|
219
|
-
this
|
|
305
|
+
this.commitDate(date)
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
|
|
309
|
+
// All changes of the value go through here, so disabled dates are never
|
|
310
|
+
// selected. Returns whether the date was selected.
|
|
311
|
+
commitDate(date) {
|
|
312
|
+
if (this.disabledDate(date)) {
|
|
313
|
+
return false
|
|
220
314
|
}
|
|
315
|
+
this.currentValue = date
|
|
316
|
+
this.$emit('update:modelValue', date)
|
|
317
|
+
return true
|
|
221
318
|
},
|
|
222
319
|
|
|
223
320
|
stepDecade(step) {
|
|
224
|
-
this.
|
|
225
|
-
year: this.currentValue.getFullYear() + step * 10
|
|
226
|
-
})
|
|
321
|
+
this.currentValue = stepDate(this.currentValue, 'year', step * 10)
|
|
227
322
|
},
|
|
228
323
|
|
|
229
324
|
setMode(mode) {
|
|
230
325
|
this.currentMode = mode
|
|
326
|
+
this.focusCursorItemIfFocused()
|
|
231
327
|
},
|
|
232
328
|
|
|
233
329
|
stepMonth(step) {
|
|
234
|
-
|
|
235
|
-
const { year, month } = this.getYearMonth(
|
|
236
|
-
currentValue.getFullYear(),
|
|
237
|
-
currentValue.getMonth() + step
|
|
238
|
-
)
|
|
239
|
-
this.setDate({
|
|
240
|
-
month,
|
|
241
|
-
day: Math.min(
|
|
242
|
-
this.getDaysInMonth(year, month),
|
|
243
|
-
this.currentValue.getDate()
|
|
244
|
-
)
|
|
245
|
-
})
|
|
330
|
+
this.currentValue = stepDate(this.currentValue, 'month', step)
|
|
246
331
|
},
|
|
247
332
|
|
|
248
333
|
stepYear(step) {
|
|
249
|
-
this.
|
|
250
|
-
year: this.currentValue.getFullYear() + step
|
|
251
|
-
})
|
|
334
|
+
this.currentValue = stepDate(this.currentValue, 'year', step)
|
|
252
335
|
},
|
|
253
336
|
|
|
254
337
|
selectDate(date) {
|
|
255
|
-
this.
|
|
256
|
-
|
|
338
|
+
if (this.commitDate(date)) {
|
|
339
|
+
this.$emit('select')
|
|
340
|
+
}
|
|
341
|
+
},
|
|
342
|
+
|
|
343
|
+
// Selects the day of `date`, keeping the time of the current value.
|
|
344
|
+
selectDay(date) {
|
|
345
|
+
this.selectDate(
|
|
346
|
+
alterDate(this.currentValue, {
|
|
347
|
+
year: date.getFullYear(),
|
|
348
|
+
month: date.getMonth(),
|
|
349
|
+
day: date.getDate()
|
|
350
|
+
})
|
|
351
|
+
)
|
|
257
352
|
},
|
|
258
353
|
|
|
259
354
|
selectMonth(month) {
|
|
@@ -268,17 +363,6 @@ export default {
|
|
|
268
363
|
this.setDate({ year }, true)
|
|
269
364
|
},
|
|
270
365
|
|
|
271
|
-
getYearMonth(year, month) {
|
|
272
|
-
if (month > 11) {
|
|
273
|
-
year++
|
|
274
|
-
month = 0
|
|
275
|
-
} else if (month < 0) {
|
|
276
|
-
year--
|
|
277
|
-
month = 11
|
|
278
|
-
}
|
|
279
|
-
return { year, month }
|
|
280
|
-
},
|
|
281
|
-
|
|
282
366
|
dateToString(
|
|
283
367
|
date,
|
|
284
368
|
{ year, month, day } = { year: true, month: true, day: true }
|
|
@@ -295,34 +379,37 @@ export default {
|
|
|
295
379
|
return `${year} – ${year + 9}`
|
|
296
380
|
},
|
|
297
381
|
|
|
298
|
-
getDaysInMonth(year, month) {
|
|
299
|
-
return new Date(year, month + 1, 0).getDate()
|
|
300
|
-
},
|
|
301
|
-
|
|
302
382
|
getFirstYearOfDecade(year) {
|
|
303
383
|
const yearStr = year.toString()
|
|
304
384
|
return +`${yearStr.slice(0, -1)}0`
|
|
305
385
|
},
|
|
306
386
|
|
|
387
|
+
// Steps the date part `mode` of the cursor by `step`, or confirms the
|
|
388
|
+
// cursor with `enter`. With `update`, the stepped date is also selected,
|
|
389
|
+
// skipping disabled dates. Returns whether anything happened.
|
|
307
390
|
navigate({ step, enter, mode = this.currentMode, update = false }) {
|
|
308
|
-
const { currentValue } = this
|
|
309
391
|
if (step) {
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
392
|
+
if (!['day', 'month', 'year'].includes(mode)) {
|
|
393
|
+
return false
|
|
394
|
+
}
|
|
395
|
+
let date = this.currentValue
|
|
396
|
+
let skippedCount = 0
|
|
397
|
+
do {
|
|
398
|
+
date = stepDate(date, mode, step)
|
|
399
|
+
} while (
|
|
400
|
+
update &&
|
|
401
|
+
this.disabledDate(date) &&
|
|
402
|
+
++skippedCount < maxSkippedDateCount
|
|
403
|
+
)
|
|
404
|
+
if (update) {
|
|
405
|
+
return this.commitDate(date)
|
|
320
406
|
}
|
|
407
|
+
this.currentValue = date
|
|
321
408
|
return true
|
|
322
409
|
} else if (enter) {
|
|
323
410
|
switch (this.currentMode) {
|
|
324
411
|
case 'day':
|
|
325
|
-
this.selectDate(currentValue)
|
|
412
|
+
this.selectDate(this.currentValue)
|
|
326
413
|
break
|
|
327
414
|
case 'month':
|
|
328
415
|
this.setMode('day')
|
|
@@ -333,80 +420,54 @@ export default {
|
|
|
333
420
|
}
|
|
334
421
|
return true
|
|
335
422
|
}
|
|
423
|
+
return false
|
|
336
424
|
},
|
|
337
425
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
for (let i = 0; i < 10; i++) {
|
|
347
|
-
this.yearRange.push(startYear + i)
|
|
348
|
-
}
|
|
349
|
-
const currMonthFirstDay = new Date(year, month, 1)
|
|
350
|
-
let firstDayWeek = currMonthFirstDay.getDay() + 1
|
|
351
|
-
if (firstDayWeek === 0) {
|
|
352
|
-
firstDayWeek = 7
|
|
353
|
-
}
|
|
354
|
-
const numDays = this.getDaysInMonth(year, month)
|
|
355
|
-
if (firstDayWeek > 1) {
|
|
356
|
-
const prevMonth = this.getYearMonth(year, month - 1)
|
|
357
|
-
const prevMonthNumDays = this.getDaysInMonth(
|
|
358
|
-
prevMonth.year,
|
|
359
|
-
prevMonth.month
|
|
360
|
-
)
|
|
361
|
-
for (let i = 1; i < firstDayWeek; i++) {
|
|
362
|
-
const day = prevMonthNumDays - firstDayWeek + i + 1
|
|
363
|
-
const date = new Date(prevMonth.year, prevMonth.month, day)
|
|
364
|
-
this.dateRange.push({
|
|
365
|
-
text: day,
|
|
366
|
-
date,
|
|
367
|
-
state: this.disabledDate(date) ? 'disabled' : 'gray'
|
|
368
|
-
})
|
|
369
|
-
}
|
|
370
|
-
}
|
|
426
|
+
// Handles a keydown event of a picker's input, with the caret inside the
|
|
427
|
+
// date part `part`, and returns whether it was handled.
|
|
428
|
+
handleKey(event, part) {
|
|
429
|
+
const { ver: step, enter } = getKeyNavigation(event)
|
|
430
|
+
return step
|
|
431
|
+
? !!part && this.navigate({ step, mode: part.name, update: true })
|
|
432
|
+
: this.navigate({ enter })
|
|
433
|
+
},
|
|
371
434
|
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
date &&
|
|
377
|
-
date.getDate() === i &&
|
|
378
|
-
date.getFullYear() === year &&
|
|
379
|
-
date.getMonth() === month
|
|
380
|
-
)
|
|
381
|
-
const state = isDay(this.modelValue)
|
|
382
|
-
? 'active'
|
|
383
|
-
: isDay(now)
|
|
384
|
-
? 'today'
|
|
385
|
-
: this.disabledDate(date)
|
|
386
|
-
? 'disabled'
|
|
387
|
-
: isDay(currentValue)
|
|
388
|
-
? 'current'
|
|
389
|
-
: null
|
|
390
|
-
this.dateRange.push({
|
|
391
|
-
text: i,
|
|
392
|
-
date,
|
|
393
|
-
state
|
|
394
|
-
})
|
|
435
|
+
focusCursorItemIfFocused() {
|
|
436
|
+
if (this.$el?.contains(document.activeElement)) {
|
|
437
|
+
// Wait for the items of the current mode to be rendered.
|
|
438
|
+
this.$nextTick(() => asArray(this.$refs.cursorItem)[0]?.focus())
|
|
395
439
|
}
|
|
440
|
+
},
|
|
396
441
|
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
442
|
+
onDatesKeyDown(event) {
|
|
443
|
+
const { key, shiftKey } = event
|
|
444
|
+
const { currentValue } = this
|
|
445
|
+
const day = currentValue.getDate()
|
|
446
|
+
const dayOffset = {
|
|
447
|
+
ArrowLeft: -1,
|
|
448
|
+
ArrowRight: 1,
|
|
449
|
+
ArrowUp: -7,
|
|
450
|
+
ArrowDown: 7
|
|
451
|
+
}[key]
|
|
452
|
+
if (dayOffset) {
|
|
453
|
+
this.setDate({ day: day + dayOffset })
|
|
454
|
+
} else if (key === 'PageUp' || key === 'PageDown') {
|
|
455
|
+
const step = key === 'PageUp' ? -1 : 1
|
|
456
|
+
if (shiftKey) {
|
|
457
|
+
this.stepYear(step)
|
|
458
|
+
} else {
|
|
459
|
+
this.stepMonth(step)
|
|
408
460
|
}
|
|
461
|
+
} else if (key === 'Home') {
|
|
462
|
+
this.setDate({ day: 1 })
|
|
463
|
+
} else if (key === 'End') {
|
|
464
|
+
// Day 0 of the next month is the last day of the current one.
|
|
465
|
+
this.setDate({ month: currentValue.getMonth() + 1, day: 0 })
|
|
466
|
+
} else {
|
|
467
|
+
return
|
|
409
468
|
}
|
|
469
|
+
event.preventDefault()
|
|
470
|
+
this.focusCursorItemIfFocused()
|
|
410
471
|
}
|
|
411
472
|
}
|
|
412
473
|
}
|
|
@@ -448,6 +509,22 @@ function getLocaleNames(locale) {
|
|
|
448
509
|
.dito-calendar {
|
|
449
510
|
min-width: 240px;
|
|
450
511
|
box-sizing: border-box;
|
|
512
|
+
|
|
513
|
+
button {
|
|
514
|
+
padding: 0;
|
|
515
|
+
border: 0;
|
|
516
|
+
font: inherit;
|
|
517
|
+
color: inherit;
|
|
518
|
+
background: none;
|
|
519
|
+
white-space: nowrap;
|
|
520
|
+
cursor: pointer;
|
|
521
|
+
@include user-select(none);
|
|
522
|
+
|
|
523
|
+
&:focus-visible {
|
|
524
|
+
outline: none;
|
|
525
|
+
box-shadow: $shadow-focus;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
451
528
|
}
|
|
452
529
|
|
|
453
530
|
.dito-calendar-popup {
|
|
@@ -461,17 +538,6 @@ function getLocaleNames(locale) {
|
|
|
461
538
|
.dito-calendar-body {
|
|
462
539
|
padding: 0 0.5em;
|
|
463
540
|
|
|
464
|
-
span {
|
|
465
|
-
display: inline-block;
|
|
466
|
-
width: calc(100% / 7);
|
|
467
|
-
height: $input-height;
|
|
468
|
-
line-height: calc($input-height - 2 * $border-width);
|
|
469
|
-
box-sizing: border-box;
|
|
470
|
-
border-radius: $border-radius;
|
|
471
|
-
border: $border-width solid transparent;
|
|
472
|
-
text-align: center;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
541
|
.dito-calendar-item-today {
|
|
476
542
|
border: $border-width solid $color-active;
|
|
477
543
|
color: $color-active;
|
|
@@ -496,39 +562,36 @@ function getLocaleNames(locale) {
|
|
|
496
562
|
}
|
|
497
563
|
}
|
|
498
564
|
|
|
565
|
+
.dito-calendar-weekdays,
|
|
566
|
+
.dito-calendar__week {
|
|
567
|
+
display: flex;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
.dito-calendar-weekdays span,
|
|
571
|
+
.dito-calendar__item {
|
|
572
|
+
display: inline-block;
|
|
573
|
+
width: calc(100% / 7);
|
|
574
|
+
height: $input-height;
|
|
575
|
+
line-height: calc($input-height - 2 * $border-width);
|
|
576
|
+
box-sizing: border-box;
|
|
577
|
+
border-radius: $border-radius;
|
|
578
|
+
border: $border-width solid transparent;
|
|
579
|
+
text-align: center;
|
|
580
|
+
}
|
|
581
|
+
|
|
499
582
|
.dito-calendar-months,
|
|
500
583
|
.dito-calendar-years {
|
|
501
|
-
|
|
584
|
+
.dito-calendar__item {
|
|
502
585
|
width: calc(100% / 4);
|
|
503
586
|
margin: 0.5em 0;
|
|
504
587
|
}
|
|
505
588
|
}
|
|
506
589
|
|
|
507
|
-
.dito-calendar-years
|
|
590
|
+
.dito-calendar-years .dito-calendar__item {
|
|
508
591
|
width: calc(100% / 5);
|
|
509
592
|
}
|
|
510
593
|
|
|
511
|
-
.dito-
|
|
512
|
-
.dito-calendar-dates span,
|
|
513
|
-
.dito-calendar-months span,
|
|
514
|
-
.dito-calendar-years span {
|
|
515
|
-
@include user-select(none);
|
|
516
|
-
|
|
517
|
-
white-space: nowrap;
|
|
518
|
-
cursor: pointer;
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
.dito-calendar-header span {
|
|
522
|
-
cursor: default;
|
|
523
|
-
|
|
524
|
-
a {
|
|
525
|
-
padding: 0 0.2em;
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
.dito-calendar-dates span:hover,
|
|
530
|
-
.dito-calendar-months span:hover,
|
|
531
|
-
.dito-calendar-years span:hover,
|
|
594
|
+
.dito-calendar__item:hover,
|
|
532
595
|
.dito-calendar:not(:hover) .dito-calendar-item-current {
|
|
533
596
|
background: $color-highlight;
|
|
534
597
|
}
|
|
@@ -558,9 +621,14 @@ function getLocaleNames(locale) {
|
|
|
558
621
|
> span {
|
|
559
622
|
margin: auto;
|
|
560
623
|
padding: 0 0.5em;
|
|
624
|
+
cursor: default;
|
|
625
|
+
|
|
626
|
+
button {
|
|
627
|
+
padding: 0 0.2em;
|
|
628
|
+
}
|
|
561
629
|
}
|
|
562
630
|
|
|
563
|
-
|
|
631
|
+
button {
|
|
564
632
|
font-weight: bold;
|
|
565
633
|
|
|
566
634
|
&:hover {
|
|
@@ -578,8 +646,10 @@ function getLocaleNames(locale) {
|
|
|
578
646
|
|
|
579
647
|
&::after {
|
|
580
648
|
position: absolute;
|
|
581
|
-
|
|
582
|
-
|
|
649
|
+
inset: 0;
|
|
650
|
+
display: flex;
|
|
651
|
+
align-items: center;
|
|
652
|
+
justify-content: center;
|
|
583
653
|
font-size: 1.25em;
|
|
584
654
|
}
|
|
585
655
|
}
|