@vaadin/date-picker 25.3.0-dev.1fa5a51482 → 25.3.0-rc1
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/custom-elements.json +391 -79
- package/package.json +13 -13
- package/src/styles/vaadin-date-picker-overlay-content-base-styles.js +0 -3
- package/src/styles/vaadin-month-calendar-base-styles.js +3 -0
- package/src/vaadin-date-metadata-controller.d.ts +54 -35
- package/src/vaadin-date-metadata-controller.js +170 -156
- package/src/vaadin-date-picker-helper.d.ts +144 -13
- package/src/vaadin-date-picker-helper.js +119 -15
- package/src/vaadin-date-picker-mixin.d.ts +71 -31
- package/src/vaadin-date-picker-mixin.js +116 -136
- package/src/vaadin-date-picker-overlay-content-mixin.js +143 -163
- package/src/vaadin-date-picker-year.js +3 -1
- package/src/vaadin-date-picker.d.ts +67 -11
- package/src/vaadin-date-picker.js +66 -13
- package/src/vaadin-infinite-scroller.js +19 -6
- package/src/vaadin-month-calendar-mixin.js +41 -64
- package/src/vaadin-month-calendar.js +4 -0
- package/web-types.json +29 -11
- package/web-types.lit.json +14 -7
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { hideOthers } from '@vaadin/a11y-base/src/aria-hidden.js';
|
|
7
7
|
import { DelegateFocusMixin } from '@vaadin/a11y-base/src/delegate-focus-mixin.js';
|
|
8
|
-
import { isKeyboardActive } from '@vaadin/a11y-base/src/focus-utils.js';
|
|
8
|
+
import { isElementFocused, isKeyboardActive } from '@vaadin/a11y-base/src/focus-utils.js';
|
|
9
9
|
import { KeyboardMixin } from '@vaadin/a11y-base/src/keyboard-mixin.js';
|
|
10
10
|
import { isIOS } from '@vaadin/component-base/src/browser-utils.js';
|
|
11
|
+
import { setOrRemoveAttribute } from '@vaadin/component-base/src/dom-utils.js';
|
|
11
12
|
import { I18nMixin } from '@vaadin/component-base/src/i18n-mixin.js';
|
|
12
13
|
import { MediaQueryController } from '@vaadin/component-base/src/media-query-controller.js';
|
|
13
14
|
import { InputConstraintsMixin } from '@vaadin/field-base/src/input-constraints-mixin.js';
|
|
@@ -16,6 +17,7 @@ import { DateMetadataController } from './vaadin-date-metadata-controller.js';
|
|
|
16
17
|
import {
|
|
17
18
|
dateAllowed,
|
|
18
19
|
dateEquals,
|
|
20
|
+
dateSelectable,
|
|
19
21
|
extractDateParts,
|
|
20
22
|
formatISODate,
|
|
21
23
|
getAdjustedYear,
|
|
@@ -43,6 +45,7 @@ export const datePickerI18nDefaults = Object.freeze({
|
|
|
43
45
|
firstDayOfWeek: 0,
|
|
44
46
|
today: 'Today',
|
|
45
47
|
cancel: 'Cancel',
|
|
48
|
+
dialogAccessibleName: 'Calendar',
|
|
46
49
|
referenceDate: '',
|
|
47
50
|
formatDate(d) {
|
|
48
51
|
const yearStr = String(d.year).replace(/\d+/u, (y) => '0000'.substr(y.length) + y);
|
|
@@ -60,7 +63,7 @@ export const datePickerI18nDefaults = Object.freeze({
|
|
|
60
63
|
date = parseInt(parts[1]);
|
|
61
64
|
year = parseInt(parts[2]);
|
|
62
65
|
if (parts[2].length < 3 && year >= 0) {
|
|
63
|
-
const usedReferenceDate =
|
|
66
|
+
const usedReferenceDate = parseDate(this.referenceDate) || new Date();
|
|
64
67
|
year = getAdjustedYear(usedReferenceDate, year, month, date);
|
|
65
68
|
}
|
|
66
69
|
} else if (parts.length === 2) {
|
|
@@ -203,6 +206,10 @@ export const DatePickerMixin = (subclass) =>
|
|
|
203
206
|
* Receives a `DatePickerDate` object of the date to be selected and should return a
|
|
204
207
|
* boolean.
|
|
205
208
|
*
|
|
209
|
+
* The function is called once per date and has to answer synchronously. Use
|
|
210
|
+
* `dateMetadataProvider` when the answer has to be loaded first, or when dates also need
|
|
211
|
+
* custom part names. A date is disabled when either of the two disables it.
|
|
212
|
+
*
|
|
206
213
|
* @type {function(DatePickerDate): boolean | undefined}
|
|
207
214
|
*/
|
|
208
215
|
isDateDisabled: {
|
|
@@ -210,33 +217,43 @@ export const DatePickerMixin = (subclass) =>
|
|
|
210
217
|
},
|
|
211
218
|
|
|
212
219
|
/**
|
|
213
|
-
* A
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
220
|
+
* A function that provides metadata for the dates the calendar is about to render: whether they
|
|
221
|
+
* are disabled, and CSS `part` names for styling from outside using the `::part()` selector.
|
|
222
|
+
* Unlike `isDateDisabled`, which is called once per date, the metadata provider is called for
|
|
223
|
+
* a range of dates at a time, and again as the calendar renders further dates.
|
|
224
|
+
*
|
|
225
|
+
* It receives a `DatePickerDateRange` and returns an array of `DatePickerDateMetadata` objects
|
|
226
|
+
* for the dates in that range that have metadata. It can return a `Promise` to load the metadata
|
|
227
|
+
* asynchronously, and `null` or `undefined` when no date in the range has metadata.
|
|
228
|
+
*
|
|
229
|
+
* The returned array has the following structure:
|
|
230
|
+
*
|
|
231
|
+
* ```js
|
|
232
|
+
* [
|
|
233
|
+
* // The date is an ISO 8601 string.
|
|
234
|
+
* { date: '2026-01-01', disabled: true },
|
|
235
|
+
*
|
|
236
|
+
* // Adds a custom part name to the date.
|
|
237
|
+
* { date: '2026-01-02', part: 'busy' },
|
|
238
|
+
* ]
|
|
239
|
+
* ```
|
|
219
240
|
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
* the
|
|
223
|
-
*
|
|
224
|
-
* until it resolves.
|
|
241
|
+
* A date is disabled if its metadata marks it disabled, or `isDateDisabled` returns `true`, or
|
|
242
|
+
* it is outside `min` and `max`. Disabled dates are not selectable, and typing a disabled date in
|
|
243
|
+
* the field makes it invalid. The provider does not affect which date is focused when opening the
|
|
244
|
+
* overlay. Use `initialPosition` property to provide a selectable date.
|
|
225
245
|
*
|
|
226
|
-
* `
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
* a theme can style specific dates via `::part()`.
|
|
246
|
+
* While a returned `Promise` is pending, the dates it covers are not disabled yet and render with
|
|
247
|
+
* the `loading` part. If the function throws or rejects, corresponding dates are requested again
|
|
248
|
+
* the next time the user navigates.
|
|
230
249
|
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
* instead of being split into two passes over the same data.
|
|
250
|
+
* The provider is used for validation also when the overlay is closed. Date is considered valid
|
|
251
|
+
* while the provider is pending, and is re-validated again after the metadata is loaded.
|
|
234
252
|
*
|
|
235
|
-
* Keep a stable reference to the function
|
|
236
|
-
*
|
|
237
|
-
* while keeping the same function, call `clearCache()`.
|
|
253
|
+
* Keep a stable reference to the function: assigning a new one clears the cache and re-fetches
|
|
254
|
+
* visible range. Call `clearCache()` to re-fetch when the data behind the same function changed.
|
|
238
255
|
*
|
|
239
|
-
* @type {
|
|
256
|
+
* @type {DatePickerDateMetadataProvider | null | undefined}
|
|
240
257
|
*/
|
|
241
258
|
dateMetadataProvider: {
|
|
242
259
|
type: Function,
|
|
@@ -295,8 +312,7 @@ export const DatePickerMixin = (subclass) =>
|
|
|
295
312
|
return [
|
|
296
313
|
'_selectedDateChanged(_selectedDate, __effectiveI18n)',
|
|
297
314
|
'_focusedDateChanged(_focusedDate, __effectiveI18n)',
|
|
298
|
-
'__updateOverlayContent(_overlayContent, __effectiveI18n, label, _minDate, _maxDate, _focusedDate, _selectedDate, showWeekNumbers, isDateDisabled,
|
|
299
|
-
'__dateMetadataProviderChanged(dateMetadataProvider)',
|
|
315
|
+
'__updateOverlayContent(_overlayContent, __effectiveI18n, label, _minDate, _maxDate, _focusedDate, _selectedDate, showWeekNumbers, isDateDisabled, __enteredDate)',
|
|
300
316
|
'__updateOverlayContentTheme(_overlayContent, _theme)',
|
|
301
317
|
'__updateOverlayContentFullScreen(_overlayContent, _fullscreen)',
|
|
302
318
|
];
|
|
@@ -307,7 +323,7 @@ export const DatePickerMixin = (subclass) =>
|
|
|
307
323
|
}
|
|
308
324
|
|
|
309
325
|
static get constraints() {
|
|
310
|
-
return [...super.constraints, 'min', 'max'];
|
|
326
|
+
return [...super.constraints, 'min', 'max', 'dateMetadataProvider'];
|
|
311
327
|
}
|
|
312
328
|
|
|
313
329
|
constructor() {
|
|
@@ -315,6 +331,9 @@ export const DatePickerMixin = (subclass) =>
|
|
|
315
331
|
|
|
316
332
|
this._boundOnClick = this._onClick.bind(this);
|
|
317
333
|
this._boundOnScroll = this._onScroll.bind(this);
|
|
334
|
+
|
|
335
|
+
this._dateMetadataController = new DateMetadataController(this, () => this.__onDateMetadataChanged());
|
|
336
|
+
this.addController(this._dateMetadataController);
|
|
318
337
|
}
|
|
319
338
|
|
|
320
339
|
/**
|
|
@@ -357,6 +376,10 @@ export const DatePickerMixin = (subclass) =>
|
|
|
357
376
|
* // Translation of the Cancel button text.
|
|
358
377
|
* cancel: 'Cancel',
|
|
359
378
|
*
|
|
379
|
+
* // Accessible name of the overlay content, announced by screen readers
|
|
380
|
+
* // when the overlay opens.
|
|
381
|
+
* dialogAccessibleName: 'Calendar',
|
|
382
|
+
*
|
|
360
383
|
* // Used for adjusting the year value when parsing dates with short years.
|
|
361
384
|
* // The year values between 0 and 99 are evaluated and adjusted.
|
|
362
385
|
* // Example: for a referenceDate of 1970-10-30;
|
|
@@ -436,7 +459,10 @@ export const DatePickerMixin = (subclass) =>
|
|
|
436
459
|
super._onFocus(event);
|
|
437
460
|
|
|
438
461
|
if (this._noInput && !isKeyboardActive()) {
|
|
462
|
+
// Blur to hide the virtual keyboard, but do not validate.
|
|
463
|
+
this.__ignoreInternalBlur = true;
|
|
439
464
|
event.target.blur();
|
|
465
|
+
this.__ignoreInternalBlur = false;
|
|
440
466
|
}
|
|
441
467
|
}
|
|
442
468
|
|
|
@@ -447,6 +473,10 @@ export const DatePickerMixin = (subclass) =>
|
|
|
447
473
|
_onBlur(event) {
|
|
448
474
|
super._onBlur(event);
|
|
449
475
|
|
|
476
|
+
if (this.__ignoreInternalBlur) {
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
479
|
+
|
|
450
480
|
if (!this.opened) {
|
|
451
481
|
this.__commitParsedOrFocusedDate();
|
|
452
482
|
|
|
@@ -472,13 +502,6 @@ export const DatePickerMixin = (subclass) =>
|
|
|
472
502
|
|
|
473
503
|
this.addController(new VirtualKeyboardController(this));
|
|
474
504
|
|
|
475
|
-
// Owns the cache of dates resolved by `dateMetadataProvider`. It lives on the date-picker
|
|
476
|
-
// rather than the overlay content so validation works even when the overlay is never opened.
|
|
477
|
-
// The open overlay reads the same controller to render months and show the loading spinner.
|
|
478
|
-
this._dateMetadataController = new DateMetadataController(this, () => this.__onDateMetadataChanged());
|
|
479
|
-
this.addController(this._dateMetadataController);
|
|
480
|
-
this._dateMetadataController.setProvider(this.dateMetadataProvider);
|
|
481
|
-
|
|
482
505
|
this._overlayElement = this.$.overlay;
|
|
483
506
|
}
|
|
484
507
|
|
|
@@ -486,6 +509,11 @@ export const DatePickerMixin = (subclass) =>
|
|
|
486
509
|
updated(props) {
|
|
487
510
|
super.updated(props);
|
|
488
511
|
|
|
512
|
+
if (props.has('dateMetadataProvider')) {
|
|
513
|
+
this._dateMetadataController.setProvider(this.dateMetadataProvider);
|
|
514
|
+
this.__reloadDateMetadata();
|
|
515
|
+
}
|
|
516
|
+
|
|
489
517
|
if (props.has('showWeekNumbers') || props.has('__effectiveI18n')) {
|
|
490
518
|
// Currently only supported for locales that start the week on Monday.
|
|
491
519
|
this.toggleAttribute('week-numbers', this.showWeekNumbers && this.__effectiveI18n.firstDayOfWeek === 1);
|
|
@@ -529,22 +557,24 @@ export const DatePickerMixin = (subclass) =>
|
|
|
529
557
|
}
|
|
530
558
|
|
|
531
559
|
/**
|
|
532
|
-
* Clears the
|
|
533
|
-
* the data behind the provider has changed (for example a date became booked) so the calendar
|
|
534
|
-
* reflects it, without having to replace the provider function.
|
|
535
|
-
*
|
|
536
|
-
* The visible range is reloaded when the overlay is open, and the selected value is
|
|
537
|
-
* re-validated once its month resolves.
|
|
560
|
+
* Clears the `dateMetadataProvider` cache and reloads the date metadata.
|
|
538
561
|
*/
|
|
539
562
|
clearCache() {
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
563
|
+
this._dateMetadataController.clearCache();
|
|
564
|
+
this.__reloadDateMetadata();
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* Asks for what the dropped cache was holding: the months the overlay is showing, and the month
|
|
569
|
+
* of the value being validated. Requested from here rather than from the controller's
|
|
570
|
+
* notification, which would turn a provider that keeps failing into an endless retry, since a
|
|
571
|
+
* failed month is dropped and so becomes missing again.
|
|
572
|
+
* @private
|
|
573
|
+
*/
|
|
574
|
+
__reloadDateMetadata() {
|
|
575
|
+
if (this.opened) {
|
|
576
|
+
this._overlayContent?.loadVisibleDateMetadata();
|
|
543
577
|
}
|
|
544
|
-
// Drops the cache and notifies, which re-renders the open overlay in the pending state and
|
|
545
|
-
// reloads its visible range (via __updateCalendars). Also reload the selected month so a
|
|
546
|
-
// value can be re-validated even while the overlay is closed.
|
|
547
|
-
controller.reset();
|
|
548
578
|
this.__ensureSelectedDateLoaded();
|
|
549
579
|
}
|
|
550
580
|
|
|
@@ -641,8 +671,13 @@ export const DatePickerMixin = (subclass) =>
|
|
|
641
671
|
const inputValid = !inputValue || (!!this._selectedDate && inputValue === this.__formatDate(this._selectedDate));
|
|
642
672
|
const isDateValid =
|
|
643
673
|
!this._selectedDate ||
|
|
644
|
-
(
|
|
645
|
-
|
|
674
|
+
dateSelectable(
|
|
675
|
+
this._selectedDate,
|
|
676
|
+
this._minDate,
|
|
677
|
+
this._maxDate,
|
|
678
|
+
this.isDateDisabled,
|
|
679
|
+
this._dateMetadataController,
|
|
680
|
+
);
|
|
646
681
|
|
|
647
682
|
let inputValidity = true;
|
|
648
683
|
if (this.inputElement && this.inputElement.checkValidity) {
|
|
@@ -653,90 +688,44 @@ export const DatePickerMixin = (subclass) =>
|
|
|
653
688
|
}
|
|
654
689
|
|
|
655
690
|
/**
|
|
656
|
-
*
|
|
657
|
-
*
|
|
658
|
-
*
|
|
659
|
-
* overlay is closed is re-validated once the provider answers (see `__onDateMetadataChanged`).
|
|
660
|
-
* Until then the date is treated as allowed, matching the overlay's rendering.
|
|
691
|
+
* Asks the controller for the month holding the selected date, so a value that was set or typed
|
|
692
|
+
* without ever opening the overlay is still checked against the provider. Validation is re-run
|
|
693
|
+
* from the host callback once the month resolves.
|
|
661
694
|
* @private
|
|
662
695
|
*/
|
|
663
|
-
|
|
696
|
+
__ensureSelectedDateLoaded() {
|
|
664
697
|
const controller = this._dateMetadataController;
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
this._dateMetadataController.setProvider(dateMetadataProvider);
|
|
673
|
-
this.__ensureSelectedDateLoaded();
|
|
698
|
+
const awaiting = !!(controller?.provider && this._selectedDate && !controller.isMonthLoaded(this._selectedDate));
|
|
699
|
+
// Always assigned, so clearing the value or removing the provider while a request is in
|
|
700
|
+
// flight disarms the pending re-validation, and a later answer for some other month does not
|
|
701
|
+
// re-validate a value that never waited for it.
|
|
702
|
+
this.__awaitingProviderValidation = awaiting;
|
|
703
|
+
if (awaiting) {
|
|
704
|
+
controller.ensureRangeLoaded(this._selectedDate, this._selectedDate);
|
|
674
705
|
}
|
|
675
706
|
}
|
|
676
707
|
|
|
677
708
|
/**
|
|
678
|
-
*
|
|
679
|
-
*
|
|
680
|
-
*
|
|
709
|
+
* Called by the date metadata controller, one microtask after its state changed
|
|
710
|
+
* and coalesced, so this never writes reactive state from inside an update. The
|
|
711
|
+
* rendered months refresh on their own because they subscribe to the controller.
|
|
681
712
|
* @private
|
|
682
713
|
*/
|
|
683
|
-
__ensureSelectedDateLoaded() {
|
|
684
|
-
const controller = this._dateMetadataController;
|
|
685
|
-
if (controller?.provider && this._selectedDate && !controller.isMonthLoaded(this._selectedDate)) {
|
|
686
|
-
this.__awaitingProviderValidation = true;
|
|
687
|
-
controller.ensureRangeLoaded(this._selectedDate, this._selectedDate);
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
/** @private */
|
|
692
714
|
__onDateMetadataChanged() {
|
|
693
715
|
const controller = this._dateMetadataController;
|
|
694
|
-
|
|
695
|
-
//
|
|
716
|
+
|
|
717
|
+
// Only the open overlay has a spinner to update and a today button to re-evaluate.
|
|
696
718
|
if (this._overlayContent) {
|
|
697
|
-
this._overlayContent.loading = controller.
|
|
698
|
-
this._overlayContent.
|
|
719
|
+
this._overlayContent.loading = controller.isLoading();
|
|
720
|
+
this._overlayContent.updateTodayButton();
|
|
699
721
|
}
|
|
700
|
-
|
|
701
|
-
//
|
|
722
|
+
|
|
723
|
+
// Runs whether or not the overlay was ever opened, which is the case this exists for: a value
|
|
724
|
+
// set or typed with the overlay closed is reported invalid as soon as its month answers.
|
|
702
725
|
if (this.__awaitingProviderValidation && this._selectedDate && controller.isMonthLoaded(this._selectedDate)) {
|
|
703
726
|
this.__awaitingProviderValidation = false;
|
|
704
727
|
this._requestValidation();
|
|
705
728
|
}
|
|
706
|
-
|
|
707
|
-
this.__adjustInitialFocusForProvider();
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
/**
|
|
711
|
-
* Moves the overlay's initial focus off a date the provider turns out to disable, once the
|
|
712
|
-
* provider has answered for that month. Only touches the auto-picked initial date and only
|
|
713
|
-
* while the user has not navigated away, so disabled dates the user focuses on purpose (which
|
|
714
|
-
* stay keyboard-focusable) are left alone.
|
|
715
|
-
* @private
|
|
716
|
-
*/
|
|
717
|
-
__adjustInitialFocusForProvider() {
|
|
718
|
-
const content = this._overlayContent;
|
|
719
|
-
const controller = this._dateMetadataController;
|
|
720
|
-
const initial = this.__initialFocusDate;
|
|
721
|
-
if (!content || !initial || !controller.provider) {
|
|
722
|
-
return;
|
|
723
|
-
}
|
|
724
|
-
// The user has moved focus; stop trying to adjust the initial date.
|
|
725
|
-
if (!dateEquals(content.focusedDate, initial)) {
|
|
726
|
-
this.__initialFocusDate = null;
|
|
727
|
-
return;
|
|
728
|
-
}
|
|
729
|
-
// Wait until the provider has answered for the initial month.
|
|
730
|
-
if (!controller.isMonthLoaded(initial)) {
|
|
731
|
-
return;
|
|
732
|
-
}
|
|
733
|
-
this.__initialFocusDate = null;
|
|
734
|
-
if (controller.isDateDisabled(initial)) {
|
|
735
|
-
const closest = content.__closestSelectableDate(initial);
|
|
736
|
-
if (closest) {
|
|
737
|
-
content.focusDate(closest);
|
|
738
|
-
}
|
|
739
|
-
}
|
|
740
729
|
}
|
|
741
730
|
|
|
742
731
|
/**
|
|
@@ -922,14 +911,12 @@ export const DatePickerMixin = (subclass) =>
|
|
|
922
911
|
this._applyInputValue(selectedDate);
|
|
923
912
|
}
|
|
924
913
|
|
|
925
|
-
// Preload the provider's answer for the selected month so the value can be validated even
|
|
926
|
-
// when the overlay is never opened.
|
|
927
|
-
this.__ensureSelectedDateLoaded();
|
|
928
|
-
|
|
929
914
|
this.value = this._formatISO(selectedDate);
|
|
930
915
|
this._ignoreFocusedDateChange = true;
|
|
931
916
|
this._focusedDate = selectedDate;
|
|
932
917
|
this._ignoreFocusedDateChange = false;
|
|
918
|
+
|
|
919
|
+
this.__ensureSelectedDateLoaded();
|
|
933
920
|
}
|
|
934
921
|
|
|
935
922
|
/** @private */
|
|
@@ -997,12 +984,10 @@ export const DatePickerMixin = (subclass) =>
|
|
|
997
984
|
selectedDate,
|
|
998
985
|
showWeekNumbers,
|
|
999
986
|
isDateDisabled,
|
|
1000
|
-
dateMetadataProvider,
|
|
1001
987
|
enteredDate,
|
|
1002
988
|
) {
|
|
1003
989
|
if (overlayContent) {
|
|
1004
|
-
//
|
|
1005
|
-
// validation uses. Assigned before the other properties, which trigger `__updateCalendars`.
|
|
990
|
+
// Reuse the date-picker's controller so the overlay shares the same cache.
|
|
1006
991
|
overlayContent._dateMetadataController = this._dateMetadataController;
|
|
1007
992
|
overlayContent.i18n = effectiveI18n;
|
|
1008
993
|
overlayContent.label = label;
|
|
@@ -1012,7 +997,6 @@ export const DatePickerMixin = (subclass) =>
|
|
|
1012
997
|
overlayContent.selectedDate = selectedDate;
|
|
1013
998
|
overlayContent.showWeekNumbers = showWeekNumbers;
|
|
1014
999
|
overlayContent.isDateDisabled = isDateDisabled;
|
|
1015
|
-
overlayContent.dateMetadataProvider = dateMetadataProvider;
|
|
1016
1000
|
overlayContent.enteredDate = enteredDate;
|
|
1017
1001
|
}
|
|
1018
1002
|
}
|
|
@@ -1020,11 +1004,7 @@ export const DatePickerMixin = (subclass) =>
|
|
|
1020
1004
|
/** @private */
|
|
1021
1005
|
__updateOverlayContentTheme(overlayContent, theme) {
|
|
1022
1006
|
if (overlayContent) {
|
|
1023
|
-
|
|
1024
|
-
overlayContent.setAttribute('theme', theme);
|
|
1025
|
-
} else {
|
|
1026
|
-
overlayContent.removeAttribute('theme');
|
|
1027
|
-
}
|
|
1007
|
+
setOrRemoveAttribute(overlayContent, 'theme', theme);
|
|
1028
1008
|
}
|
|
1029
1009
|
}
|
|
1030
1010
|
|
|
@@ -1061,12 +1041,6 @@ export const DatePickerMixin = (subclass) =>
|
|
|
1061
1041
|
content.focusedDate = scrollFocusDate;
|
|
1062
1042
|
this._ignoreFocusedDateChange = false;
|
|
1063
1043
|
|
|
1064
|
-
// When opening without a selected value, remember the auto-picked initial date so it can be
|
|
1065
|
-
// moved off a provider-disabled date once the provider answers (see __onDateMetadataChanged).
|
|
1066
|
-
// A date the user selected themselves is left in place even if the provider disables it.
|
|
1067
|
-
this.__initialFocusDate = this._selectedDate ? null : scrollFocusDate;
|
|
1068
|
-
this.__adjustInitialFocusForProvider();
|
|
1069
|
-
|
|
1070
1044
|
window.addEventListener('scroll', this._boundOnScroll, true);
|
|
1071
1045
|
|
|
1072
1046
|
if (this._focusOverlayOnOpen) {
|
|
@@ -1130,7 +1104,7 @@ export const DatePickerMixin = (subclass) =>
|
|
|
1130
1104
|
|
|
1131
1105
|
/** @protected */
|
|
1132
1106
|
_onOverlayClosed() {
|
|
1133
|
-
this.
|
|
1107
|
+
this._overlayContent?.cancelLoadVisibleDateMetadata();
|
|
1134
1108
|
|
|
1135
1109
|
// Reset `aria-hidden` state.
|
|
1136
1110
|
if (this.__showOthers) {
|
|
@@ -1150,6 +1124,12 @@ export const DatePickerMixin = (subclass) =>
|
|
|
1150
1124
|
if (!this.value && !this._keyboardActive) {
|
|
1151
1125
|
this._requestValidation();
|
|
1152
1126
|
}
|
|
1127
|
+
|
|
1128
|
+
// Focusout events while closing arrive with `opened` still true and keep the focused state.
|
|
1129
|
+
// Clear it here unless focus was restored to the input, as at a wide viewport or on Esc.
|
|
1130
|
+
if (!this.inputElement || !isElementFocused(this.inputElement)) {
|
|
1131
|
+
this._setFocused(false);
|
|
1132
|
+
}
|
|
1153
1133
|
}
|
|
1154
1134
|
|
|
1155
1135
|
/** @private */
|