@angular/material 19.0.3 → 19.0.5
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/LICENSE +1 -1
- package/autocomplete/index.d.ts +6 -6
- package/badge/index.d.ts +2 -2
- package/button/index.d.ts +6 -4
- package/checkbox/index.d.ts +4 -4
- package/chips/index.d.ts +3 -3
- package/core/theming/_theming.scss +1 -1
- package/datepicker/index.d.ts +16 -39
- package/expansion/index.d.ts +2 -0
- package/fesm2022/autocomplete.mjs +41 -37
- package/fesm2022/autocomplete.mjs.map +1 -1
- package/fesm2022/badge.mjs +2 -2
- package/fesm2022/badge.mjs.map +1 -1
- package/fesm2022/button.mjs +7 -5
- package/fesm2022/button.mjs.map +1 -1
- package/fesm2022/checkbox.mjs +2 -2
- package/fesm2022/checkbox.mjs.map +1 -1
- package/fesm2022/chips.mjs +2 -2
- package/fesm2022/chips.mjs.map +1 -1
- package/fesm2022/core.mjs +1 -1
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/datepicker.mjs +737 -745
- package/fesm2022/datepicker.mjs.map +1 -1
- package/fesm2022/expansion.mjs +5 -3
- package/fesm2022/expansion.mjs.map +1 -1
- package/fesm2022/form-field.mjs +7 -5
- package/fesm2022/form-field.mjs.map +1 -1
- package/fesm2022/icon.mjs +2 -2
- package/fesm2022/icon.mjs.map +1 -1
- package/fesm2022/input.mjs +19 -25
- package/fesm2022/input.mjs.map +1 -1
- package/fesm2022/list.mjs +14 -10
- package/fesm2022/list.mjs.map +1 -1
- package/fesm2022/menu.mjs +163 -118
- package/fesm2022/menu.mjs.map +1 -1
- package/fesm2022/paginator.mjs +12 -15
- package/fesm2022/paginator.mjs.map +1 -1
- package/fesm2022/progress-bar.mjs +7 -5
- package/fesm2022/progress-bar.mjs.map +1 -1
- package/fesm2022/progress-spinner.mjs +2 -2
- package/fesm2022/progress-spinner.mjs.map +1 -1
- package/fesm2022/radio.mjs +9 -8
- package/fesm2022/radio.mjs.map +1 -1
- package/fesm2022/select.mjs.map +1 -1
- package/fesm2022/sidenav.mjs +118 -94
- package/fesm2022/sidenav.mjs.map +1 -1
- package/fesm2022/slide-toggle.mjs +2 -2
- package/fesm2022/slide-toggle.mjs.map +1 -1
- package/fesm2022/slider.mjs +24 -25
- package/fesm2022/slider.mjs.map +1 -1
- package/fesm2022/sort.mjs +2 -2
- package/fesm2022/sort.mjs.map +1 -1
- package/fesm2022/stepper.mjs +6 -6
- package/fesm2022/stepper.mjs.map +1 -1
- package/fesm2022/table.mjs +4 -15
- package/fesm2022/table.mjs.map +1 -1
- package/fesm2022/tabs.mjs +8 -8
- package/fesm2022/tabs.mjs.map +1 -1
- package/fesm2022/timepicker.mjs +8 -4
- package/fesm2022/timepicker.mjs.map +1 -1
- package/fesm2022/toolbar.mjs +2 -2
- package/fesm2022/toolbar.mjs.map +1 -1
- package/fesm2022/tooltip.mjs +11 -7
- package/fesm2022/tooltip.mjs.map +1 -1
- package/form-field/index.d.ts +5 -4
- package/icon/index.d.ts +4 -4
- package/input/index.d.ts +8 -5
- package/list/index.d.ts +8 -5
- package/menu/index.d.ts +13 -14
- package/package.json +2 -2
- package/paginator/index.d.ts +5 -5
- package/progress-bar/index.d.ts +6 -4
- package/progress-spinner/index.d.ts +4 -4
- package/radio/index.d.ts +8 -6
- package/schematics/ng-add/index.js +1 -1
- package/schematics/ng-add/index.mjs +1 -1
- package/schematics/ng-generate/theme-color/index_bundled.js +2 -2
- package/schematics/ng-update/index_bundled.js +31 -31
- package/select/index.d.ts +1 -1
- package/sidenav/index.d.ts +12 -10
- package/slide-toggle/index.d.ts +4 -4
- package/slider/index.d.ts +6 -3
- package/stepper/index.d.ts +6 -6
- package/tabs/index.d.ts +8 -8
- package/timepicker/index.d.ts +1 -0
- package/toolbar/index.d.ts +2 -2
- package/tooltip/index.d.ts +1 -0
package/fesm2022/datepicker.mjs
CHANGED
|
@@ -16,7 +16,7 @@ import { _CdkPrivateStyleLoader, _VisuallyHiddenLoader } from '@angular/cdk/priv
|
|
|
16
16
|
import { startWith, take, filter } from 'rxjs/operators';
|
|
17
17
|
import { coerceStringArray } from '@angular/cdk/coercion';
|
|
18
18
|
import { trigger, transition, animate, keyframes, style, state } from '@angular/animations';
|
|
19
|
-
import { NG_VALUE_ACCESSOR, NG_VALIDATORS, Validators, NgForm, FormGroupDirective, NgControl
|
|
19
|
+
import { NG_VALUE_ACCESSOR, NG_VALIDATORS, Validators, ControlContainer, NgForm, FormGroupDirective, NgControl } from '@angular/forms';
|
|
20
20
|
import { MAT_FORM_FIELD, MatFormFieldControl } from '@angular/material/form-field';
|
|
21
21
|
import { MAT_INPUT_VALUE_ACCESSOR } from '@angular/material/input';
|
|
22
22
|
|
|
@@ -2514,10 +2514,10 @@ class MatDatepickerContent {
|
|
|
2514
2514
|
_calendar;
|
|
2515
2515
|
/**
|
|
2516
2516
|
* Theme color of the internal calendar. This API is supported in M2 themes
|
|
2517
|
-
* only, it has no effect in M3 themes.
|
|
2517
|
+
* only, it has no effect in M3 themes. For color customization in M3, see https://material.angular.io/components/datepicker/styling.
|
|
2518
2518
|
*
|
|
2519
2519
|
* For information on applying color variants in M3, see
|
|
2520
|
-
* https://material.angular.io/guide/theming#
|
|
2520
|
+
* https://material.angular.io/guide/material-2-theming#optional-add-backwards-compatibility-styles-for-color-variants
|
|
2521
2521
|
*/
|
|
2522
2522
|
color;
|
|
2523
2523
|
/** Reference to the datepicker that created the overlay. */
|
|
@@ -2670,10 +2670,10 @@ class MatDatepickerBase {
|
|
|
2670
2670
|
startView = 'month';
|
|
2671
2671
|
/**
|
|
2672
2672
|
* Theme color of the datepicker's calendar. This API is supported in M2 themes only, it
|
|
2673
|
-
* has no effect in M3 themes.
|
|
2673
|
+
* has no effect in M3 themes. For color customization in M3, see https://material.angular.io/components/datepicker/styling.
|
|
2674
2674
|
*
|
|
2675
2675
|
* For information on applying color variants in M3, see
|
|
2676
|
-
* https://material.angular.io/guide/theming#
|
|
2676
|
+
* https://material.angular.io/guide/material-2-theming#optional-add-backwards-compatibility-styles-for-color-variants
|
|
2677
2677
|
*/
|
|
2678
2678
|
get color() {
|
|
2679
2679
|
return (this._color || (this.datepickerInput ? this.datepickerInput.getThemePalette() : undefined));
|
|
@@ -3707,467 +3707,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImpor
|
|
|
3707
3707
|
args: ['button']
|
|
3708
3708
|
}] } });
|
|
3709
3709
|
|
|
3710
|
-
// This file contains the `_computeAriaAccessibleName` function, which computes what the *expected*
|
|
3711
|
-
// ARIA accessible name would be for a given element. Implements a subset of ARIA specification
|
|
3712
|
-
// [Accessible Name and Description Computation 1.2](https://www.w3.org/TR/accname-1.2/).
|
|
3713
|
-
//
|
|
3714
|
-
// Specification accname-1.2 can be summarized by returning the result of the first method
|
|
3715
|
-
// available.
|
|
3716
|
-
//
|
|
3717
|
-
// 1. `aria-labelledby` attribute
|
|
3718
|
-
// ```
|
|
3719
|
-
// <!-- example using aria-labelledby-->
|
|
3720
|
-
// <label id='label-id'>Start Date</label>
|
|
3721
|
-
// <input aria-labelledby='label-id'/>
|
|
3722
|
-
// ```
|
|
3723
|
-
// 2. `aria-label` attribute (e.g. `<input aria-label="Departure"/>`)
|
|
3724
|
-
// 3. Label with `for`/`id`
|
|
3725
|
-
// ```
|
|
3726
|
-
// <!-- example using for/id -->
|
|
3727
|
-
// <label for="current-node">Label</label>
|
|
3728
|
-
// <input id="current-node"/>
|
|
3729
|
-
// ```
|
|
3730
|
-
// 4. `placeholder` attribute (e.g. `<input placeholder="06/03/1990"/>`)
|
|
3731
|
-
// 5. `title` attribute (e.g. `<input title="Check-In"/>`)
|
|
3732
|
-
// 6. text content
|
|
3733
|
-
// ```
|
|
3734
|
-
// <!-- example using text content -->
|
|
3735
|
-
// <label for="current-node"><span>Departure</span> Date</label>
|
|
3736
|
-
// <input id="current-node"/>
|
|
3737
|
-
// ```
|
|
3738
|
-
/**
|
|
3739
|
-
* Computes the *expected* ARIA accessible name for argument element based on [accname-1.2
|
|
3740
|
-
* specification](https://www.w3.org/TR/accname-1.2/). Implements a subset of accname-1.2,
|
|
3741
|
-
* and should only be used for the Datepicker's specific use case.
|
|
3742
|
-
*
|
|
3743
|
-
* Intended use:
|
|
3744
|
-
* This is not a general use implementation. Only implements the parts of accname-1.2 that are
|
|
3745
|
-
* required for the Datepicker's specific use case. This function is not intended for any other
|
|
3746
|
-
* use.
|
|
3747
|
-
*
|
|
3748
|
-
* Limitations:
|
|
3749
|
-
* - Only covers the needs of `matStartDate` and `matEndDate`. Does not support other use cases.
|
|
3750
|
-
* - See NOTES's in implementation for specific details on what parts of the accname-1.2
|
|
3751
|
-
* specification are not implemented.
|
|
3752
|
-
*
|
|
3753
|
-
* @param element {HTMLInputElement} native <input/> element of `matStartDate` or
|
|
3754
|
-
* `matEndDate` component. Corresponds to the 'Root Element' from accname-1.2
|
|
3755
|
-
*
|
|
3756
|
-
* @return expected ARIA accessible name of argument <input/>
|
|
3757
|
-
*/
|
|
3758
|
-
function _computeAriaAccessibleName(element) {
|
|
3759
|
-
return _computeAriaAccessibleNameInternal(element, true);
|
|
3760
|
-
}
|
|
3761
|
-
/**
|
|
3762
|
-
* Determine if argument node is an Element based on `nodeType` property. This function is safe to
|
|
3763
|
-
* use with server-side rendering.
|
|
3764
|
-
*/
|
|
3765
|
-
function ssrSafeIsElement(node) {
|
|
3766
|
-
return node.nodeType === Node.ELEMENT_NODE;
|
|
3767
|
-
}
|
|
3768
|
-
/**
|
|
3769
|
-
* Determine if argument node is an HTMLInputElement based on `nodeName` property. This funciton is
|
|
3770
|
-
* safe to use with server-side rendering.
|
|
3771
|
-
*/
|
|
3772
|
-
function ssrSafeIsHTMLInputElement(node) {
|
|
3773
|
-
return node.nodeName === 'INPUT';
|
|
3774
|
-
}
|
|
3775
|
-
/**
|
|
3776
|
-
* Determine if argument node is an HTMLTextAreaElement based on `nodeName` property. This
|
|
3777
|
-
* funciton is safe to use with server-side rendering.
|
|
3778
|
-
*/
|
|
3779
|
-
function ssrSafeIsHTMLTextAreaElement(node) {
|
|
3780
|
-
return node.nodeName === 'TEXTAREA';
|
|
3781
|
-
}
|
|
3782
|
-
/**
|
|
3783
|
-
* Calculate the expected ARIA accessible name for given DOM Node. Given DOM Node may be either the
|
|
3784
|
-
* "Root node" passed to `_computeAriaAccessibleName` or "Current node" as result of recursion.
|
|
3785
|
-
*
|
|
3786
|
-
* @return the accessible name of argument DOM Node
|
|
3787
|
-
*
|
|
3788
|
-
* @param currentNode node to determine accessible name of
|
|
3789
|
-
* @param isDirectlyReferenced true if `currentNode` is the root node to calculate ARIA accessible
|
|
3790
|
-
* name of. False if it is a result of recursion.
|
|
3791
|
-
*/
|
|
3792
|
-
function _computeAriaAccessibleNameInternal(currentNode, isDirectlyReferenced) {
|
|
3793
|
-
// NOTE: this differs from accname-1.2 specification.
|
|
3794
|
-
// - Does not implement Step 1. of accname-1.2: '''If `currentNode`'s role prohibits naming,
|
|
3795
|
-
// return the empty string ("")'''.
|
|
3796
|
-
// - Does not implement Step 2.A. of accname-1.2: '''if current node is hidden and not directly
|
|
3797
|
-
// referenced by aria-labelledby... return the empty string.'''
|
|
3798
|
-
// acc-name-1.2 Step 2.B.: aria-labelledby
|
|
3799
|
-
if (ssrSafeIsElement(currentNode) && isDirectlyReferenced) {
|
|
3800
|
-
const labelledbyIds = currentNode.getAttribute?.('aria-labelledby')?.split(/\s+/g) || [];
|
|
3801
|
-
const validIdRefs = labelledbyIds.reduce((validIds, id) => {
|
|
3802
|
-
const elem = document.getElementById(id);
|
|
3803
|
-
if (elem) {
|
|
3804
|
-
validIds.push(elem);
|
|
3805
|
-
}
|
|
3806
|
-
return validIds;
|
|
3807
|
-
}, []);
|
|
3808
|
-
if (validIdRefs.length) {
|
|
3809
|
-
return validIdRefs
|
|
3810
|
-
.map(idRef => {
|
|
3811
|
-
return _computeAriaAccessibleNameInternal(idRef, false);
|
|
3812
|
-
})
|
|
3813
|
-
.join(' ');
|
|
3814
|
-
}
|
|
3815
|
-
}
|
|
3816
|
-
// acc-name-1.2 Step 2.C.: aria-label
|
|
3817
|
-
if (ssrSafeIsElement(currentNode)) {
|
|
3818
|
-
const ariaLabel = currentNode.getAttribute('aria-label')?.trim();
|
|
3819
|
-
if (ariaLabel) {
|
|
3820
|
-
return ariaLabel;
|
|
3821
|
-
}
|
|
3822
|
-
}
|
|
3823
|
-
// acc-name-1.2 Step 2.D. attribute or element that defines a text alternative
|
|
3824
|
-
//
|
|
3825
|
-
// NOTE: this differs from accname-1.2 specification.
|
|
3826
|
-
// Only implements Step 2.D. for `<label>`,`<input/>`, and `<textarea/>` element. Does not
|
|
3827
|
-
// implement other elements that have an attribute or element that defines a text alternative.
|
|
3828
|
-
if (ssrSafeIsHTMLInputElement(currentNode) || ssrSafeIsHTMLTextAreaElement(currentNode)) {
|
|
3829
|
-
// use label with a `for` attribute referencing the current node
|
|
3830
|
-
if (currentNode.labels?.length) {
|
|
3831
|
-
return Array.from(currentNode.labels)
|
|
3832
|
-
.map(x => _computeAriaAccessibleNameInternal(x, false))
|
|
3833
|
-
.join(' ');
|
|
3834
|
-
}
|
|
3835
|
-
// use placeholder if available
|
|
3836
|
-
const placeholder = currentNode.getAttribute('placeholder')?.trim();
|
|
3837
|
-
if (placeholder) {
|
|
3838
|
-
return placeholder;
|
|
3839
|
-
}
|
|
3840
|
-
// use title if available
|
|
3841
|
-
const title = currentNode.getAttribute('title')?.trim();
|
|
3842
|
-
if (title) {
|
|
3843
|
-
return title;
|
|
3844
|
-
}
|
|
3845
|
-
}
|
|
3846
|
-
// NOTE: this differs from accname-1.2 specification.
|
|
3847
|
-
// - does not implement acc-name-1.2 Step 2.E.: '''if the current node is a control embedded
|
|
3848
|
-
// within the label... then include the embedded control as part of the text alternative in
|
|
3849
|
-
// the following manner...'''. Step 2E applies to embedded controls such as textbox, listbox,
|
|
3850
|
-
// range, etc.
|
|
3851
|
-
// - does not implement acc-name-1.2 step 2.F.: check that '''role allows name from content''',
|
|
3852
|
-
// which applies to `currentNode` and its children.
|
|
3853
|
-
// - does not implement acc-name-1.2 Step 2.F.ii.: '''Check for CSS generated textual content'''
|
|
3854
|
-
// (e.g. :before and :after).
|
|
3855
|
-
// - does not implement acc-name-1.2 Step 2.I.: '''if the current node has a Tooltip attribute,
|
|
3856
|
-
// return its value'''
|
|
3857
|
-
// Return text content with whitespace collapsed into a single space character. Accomplish
|
|
3858
|
-
// acc-name-1.2 steps 2F, 2G, and 2H.
|
|
3859
|
-
return (currentNode.textContent || '').replace(/\s+/g, ' ').trim();
|
|
3860
|
-
}
|
|
3861
|
-
|
|
3862
|
-
/**
|
|
3863
|
-
* Used to provide the date range input wrapper component
|
|
3864
|
-
* to the parts without circular dependencies.
|
|
3865
|
-
*/
|
|
3866
|
-
const MAT_DATE_RANGE_INPUT_PARENT = new InjectionToken('MAT_DATE_RANGE_INPUT_PARENT');
|
|
3867
|
-
/**
|
|
3868
|
-
* Base class for the individual inputs that can be projected inside a `mat-date-range-input`.
|
|
3869
|
-
*/
|
|
3870
|
-
class MatDateRangeInputPartBase extends MatDatepickerInputBase {
|
|
3871
|
-
_rangeInput = inject(MAT_DATE_RANGE_INPUT_PARENT);
|
|
3872
|
-
_elementRef = inject(ElementRef);
|
|
3873
|
-
_defaultErrorStateMatcher = inject(ErrorStateMatcher);
|
|
3874
|
-
_injector = inject(Injector);
|
|
3875
|
-
_parentForm = inject(NgForm, { optional: true });
|
|
3876
|
-
_parentFormGroup = inject(FormGroupDirective, { optional: true });
|
|
3877
|
-
/**
|
|
3878
|
-
* Form control bound to this input part.
|
|
3879
|
-
* @docs-private
|
|
3880
|
-
*/
|
|
3881
|
-
ngControl;
|
|
3882
|
-
_dir = inject(Directionality, { optional: true });
|
|
3883
|
-
_errorStateTracker;
|
|
3884
|
-
/** Object used to control when error messages are shown. */
|
|
3885
|
-
get errorStateMatcher() {
|
|
3886
|
-
return this._errorStateTracker.matcher;
|
|
3887
|
-
}
|
|
3888
|
-
set errorStateMatcher(value) {
|
|
3889
|
-
this._errorStateTracker.matcher = value;
|
|
3890
|
-
}
|
|
3891
|
-
/** Whether the input is in an error state. */
|
|
3892
|
-
get errorState() {
|
|
3893
|
-
return this._errorStateTracker.errorState;
|
|
3894
|
-
}
|
|
3895
|
-
set errorState(value) {
|
|
3896
|
-
this._errorStateTracker.errorState = value;
|
|
3897
|
-
}
|
|
3898
|
-
constructor() {
|
|
3899
|
-
super();
|
|
3900
|
-
this._errorStateTracker = new _ErrorStateTracker(this._defaultErrorStateMatcher, null, this._parentFormGroup, this._parentForm, this.stateChanges);
|
|
3901
|
-
}
|
|
3902
|
-
ngOnInit() {
|
|
3903
|
-
// We need the date input to provide itself as a `ControlValueAccessor` and a `Validator`, while
|
|
3904
|
-
// injecting its `NgControl` so that the error state is handled correctly. This introduces a
|
|
3905
|
-
// circular dependency, because both `ControlValueAccessor` and `Validator` depend on the input
|
|
3906
|
-
// itself. Usually we can work around it for the CVA, but there's no API to do it for the
|
|
3907
|
-
// validator. We work around it here by injecting the `NgControl` in `ngOnInit`, after
|
|
3908
|
-
// everything has been resolved.
|
|
3909
|
-
const ngControl = this._injector.get(NgControl, null, { optional: true, self: true });
|
|
3910
|
-
if (ngControl) {
|
|
3911
|
-
this.ngControl = ngControl;
|
|
3912
|
-
this._errorStateTracker.ngControl = ngControl;
|
|
3913
|
-
}
|
|
3914
|
-
}
|
|
3915
|
-
ngDoCheck() {
|
|
3916
|
-
if (this.ngControl) {
|
|
3917
|
-
// We need to re-evaluate this on every change detection cycle, because there are some
|
|
3918
|
-
// error triggers that we can't subscribe to (e.g. parent form submissions). This means
|
|
3919
|
-
// that whatever logic is in here has to be super lean or we risk destroying the performance.
|
|
3920
|
-
this.updateErrorState();
|
|
3921
|
-
}
|
|
3922
|
-
}
|
|
3923
|
-
/** Gets whether the input is empty. */
|
|
3924
|
-
isEmpty() {
|
|
3925
|
-
return this._elementRef.nativeElement.value.length === 0;
|
|
3926
|
-
}
|
|
3927
|
-
/** Gets the placeholder of the input. */
|
|
3928
|
-
_getPlaceholder() {
|
|
3929
|
-
return this._elementRef.nativeElement.placeholder;
|
|
3930
|
-
}
|
|
3931
|
-
/** Focuses the input. */
|
|
3932
|
-
focus() {
|
|
3933
|
-
this._elementRef.nativeElement.focus();
|
|
3934
|
-
}
|
|
3935
|
-
/** Gets the value that should be used when mirroring the input's size. */
|
|
3936
|
-
getMirrorValue() {
|
|
3937
|
-
const element = this._elementRef.nativeElement;
|
|
3938
|
-
const value = element.value;
|
|
3939
|
-
return value.length > 0 ? value : element.placeholder;
|
|
3940
|
-
}
|
|
3941
|
-
/** Refreshes the error state of the input. */
|
|
3942
|
-
updateErrorState() {
|
|
3943
|
-
this._errorStateTracker.updateErrorState();
|
|
3944
|
-
}
|
|
3945
|
-
/** Handles `input` events on the input element. */
|
|
3946
|
-
_onInput(value) {
|
|
3947
|
-
super._onInput(value);
|
|
3948
|
-
this._rangeInput._handleChildValueChange();
|
|
3949
|
-
}
|
|
3950
|
-
/** Opens the datepicker associated with the input. */
|
|
3951
|
-
_openPopup() {
|
|
3952
|
-
this._rangeInput._openDatepicker();
|
|
3953
|
-
}
|
|
3954
|
-
/** Gets the minimum date from the range input. */
|
|
3955
|
-
_getMinDate() {
|
|
3956
|
-
return this._rangeInput.min;
|
|
3957
|
-
}
|
|
3958
|
-
/** Gets the maximum date from the range input. */
|
|
3959
|
-
_getMaxDate() {
|
|
3960
|
-
return this._rangeInput.max;
|
|
3961
|
-
}
|
|
3962
|
-
/** Gets the date filter function from the range input. */
|
|
3963
|
-
_getDateFilter() {
|
|
3964
|
-
return this._rangeInput.dateFilter;
|
|
3965
|
-
}
|
|
3966
|
-
_parentDisabled() {
|
|
3967
|
-
return this._rangeInput._groupDisabled;
|
|
3968
|
-
}
|
|
3969
|
-
_shouldHandleChangeEvent({ source }) {
|
|
3970
|
-
return source !== this._rangeInput._startInput && source !== this._rangeInput._endInput;
|
|
3971
|
-
}
|
|
3972
|
-
_assignValueProgrammatically(value) {
|
|
3973
|
-
super._assignValueProgrammatically(value);
|
|
3974
|
-
const opposite = (this === this._rangeInput._startInput
|
|
3975
|
-
? this._rangeInput._endInput
|
|
3976
|
-
: this._rangeInput._startInput);
|
|
3977
|
-
opposite?._validatorOnChange();
|
|
3978
|
-
}
|
|
3979
|
-
/** return the ARIA accessible name of the input element */
|
|
3980
|
-
_getAccessibleName() {
|
|
3981
|
-
return _computeAriaAccessibleName(this._elementRef.nativeElement);
|
|
3982
|
-
}
|
|
3983
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatDateRangeInputPartBase, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
3984
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.0", type: MatDateRangeInputPartBase, isStandalone: true, inputs: { errorStateMatcher: "errorStateMatcher" }, usesInheritance: true, ngImport: i0 });
|
|
3985
|
-
}
|
|
3986
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatDateRangeInputPartBase, decorators: [{
|
|
3987
|
-
type: Directive
|
|
3988
|
-
}], ctorParameters: () => [], propDecorators: { errorStateMatcher: [{
|
|
3989
|
-
type: Input
|
|
3990
|
-
}] } });
|
|
3991
|
-
/** Input for entering the start date in a `mat-date-range-input`. */
|
|
3992
|
-
class MatStartDate extends MatDateRangeInputPartBase {
|
|
3993
|
-
/** Validator that checks that the start date isn't after the end date. */
|
|
3994
|
-
_startValidator = (control) => {
|
|
3995
|
-
const start = this._dateAdapter.getValidDateOrNull(this._dateAdapter.deserialize(control.value));
|
|
3996
|
-
const end = this._model ? this._model.selection.end : null;
|
|
3997
|
-
return !start || !end || this._dateAdapter.compareDate(start, end) <= 0
|
|
3998
|
-
? null
|
|
3999
|
-
: { 'matStartDateInvalid': { 'end': end, 'actual': start } };
|
|
4000
|
-
};
|
|
4001
|
-
_validator = Validators.compose([...super._getValidators(), this._startValidator]);
|
|
4002
|
-
_getValueFromModel(modelValue) {
|
|
4003
|
-
return modelValue.start;
|
|
4004
|
-
}
|
|
4005
|
-
_shouldHandleChangeEvent(change) {
|
|
4006
|
-
if (!super._shouldHandleChangeEvent(change)) {
|
|
4007
|
-
return false;
|
|
4008
|
-
}
|
|
4009
|
-
else {
|
|
4010
|
-
return !change.oldValue?.start
|
|
4011
|
-
? !!change.selection.start
|
|
4012
|
-
: !change.selection.start ||
|
|
4013
|
-
!!this._dateAdapter.compareDate(change.oldValue.start, change.selection.start);
|
|
4014
|
-
}
|
|
4015
|
-
}
|
|
4016
|
-
_assignValueToModel(value) {
|
|
4017
|
-
if (this._model) {
|
|
4018
|
-
const range = new DateRange(value, this._model.selection.end);
|
|
4019
|
-
this._model.updateSelection(range, this);
|
|
4020
|
-
}
|
|
4021
|
-
}
|
|
4022
|
-
_formatValue(value) {
|
|
4023
|
-
super._formatValue(value);
|
|
4024
|
-
// Any time the input value is reformatted we need to tell the parent.
|
|
4025
|
-
this._rangeInput._handleChildValueChange();
|
|
4026
|
-
}
|
|
4027
|
-
_onKeydown(event) {
|
|
4028
|
-
const endInput = this._rangeInput._endInput;
|
|
4029
|
-
const element = this._elementRef.nativeElement;
|
|
4030
|
-
const isLtr = this._dir?.value !== 'rtl';
|
|
4031
|
-
// If the user hits RIGHT (LTR) when at the end of the input (and no
|
|
4032
|
-
// selection), move the cursor to the start of the end input.
|
|
4033
|
-
if (((event.keyCode === RIGHT_ARROW && isLtr) || (event.keyCode === LEFT_ARROW && !isLtr)) &&
|
|
4034
|
-
element.selectionStart === element.value.length &&
|
|
4035
|
-
element.selectionEnd === element.value.length) {
|
|
4036
|
-
event.preventDefault();
|
|
4037
|
-
endInput._elementRef.nativeElement.setSelectionRange(0, 0);
|
|
4038
|
-
endInput.focus();
|
|
4039
|
-
}
|
|
4040
|
-
else {
|
|
4041
|
-
super._onKeydown(event);
|
|
4042
|
-
}
|
|
4043
|
-
}
|
|
4044
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatStartDate, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
4045
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.0", type: MatStartDate, isStandalone: true, selector: "input[matStartDate]", outputs: { dateChange: "dateChange", dateInput: "dateInput" }, host: { attributes: { "type": "text" }, listeners: { "input": "_onInput($event.target.value)", "change": "_onChange()", "keydown": "_onKeydown($event)", "blur": "_onBlur()" }, properties: { "disabled": "disabled", "attr.aria-haspopup": "_rangeInput.rangePicker ? \"dialog\" : null", "attr.aria-owns": "_rangeInput._ariaOwns\n ? _rangeInput._ariaOwns()\n : (_rangeInput.rangePicker?.opened && _rangeInput.rangePicker.id) || null", "attr.min": "_getMinDate() ? _dateAdapter.toIso8601(_getMinDate()) : null", "attr.max": "_getMaxDate() ? _dateAdapter.toIso8601(_getMaxDate()) : null" }, classAttribute: "mat-start-date mat-date-range-input-inner" }, providers: [
|
|
4046
|
-
{ provide: NG_VALUE_ACCESSOR, useExisting: MatStartDate, multi: true },
|
|
4047
|
-
{ provide: NG_VALIDATORS, useExisting: MatStartDate, multi: true },
|
|
4048
|
-
], usesInheritance: true, ngImport: i0 });
|
|
4049
|
-
}
|
|
4050
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatStartDate, decorators: [{
|
|
4051
|
-
type: Directive,
|
|
4052
|
-
args: [{
|
|
4053
|
-
selector: 'input[matStartDate]',
|
|
4054
|
-
host: {
|
|
4055
|
-
'class': 'mat-start-date mat-date-range-input-inner',
|
|
4056
|
-
'[disabled]': 'disabled',
|
|
4057
|
-
'(input)': '_onInput($event.target.value)',
|
|
4058
|
-
'(change)': '_onChange()',
|
|
4059
|
-
'(keydown)': '_onKeydown($event)',
|
|
4060
|
-
'[attr.aria-haspopup]': '_rangeInput.rangePicker ? "dialog" : null',
|
|
4061
|
-
'[attr.aria-owns]': `_rangeInput._ariaOwns
|
|
4062
|
-
? _rangeInput._ariaOwns()
|
|
4063
|
-
: (_rangeInput.rangePicker?.opened && _rangeInput.rangePicker.id) || null`,
|
|
4064
|
-
'[attr.min]': '_getMinDate() ? _dateAdapter.toIso8601(_getMinDate()) : null',
|
|
4065
|
-
'[attr.max]': '_getMaxDate() ? _dateAdapter.toIso8601(_getMaxDate()) : null',
|
|
4066
|
-
'(blur)': '_onBlur()',
|
|
4067
|
-
'type': 'text',
|
|
4068
|
-
},
|
|
4069
|
-
providers: [
|
|
4070
|
-
{ provide: NG_VALUE_ACCESSOR, useExisting: MatStartDate, multi: true },
|
|
4071
|
-
{ provide: NG_VALIDATORS, useExisting: MatStartDate, multi: true },
|
|
4072
|
-
],
|
|
4073
|
-
// These need to be specified explicitly, because some tooling doesn't
|
|
4074
|
-
// seem to pick them up from the base class. See #20932.
|
|
4075
|
-
outputs: ['dateChange', 'dateInput'],
|
|
4076
|
-
}]
|
|
4077
|
-
}] });
|
|
4078
|
-
/** Input for entering the end date in a `mat-date-range-input`. */
|
|
4079
|
-
class MatEndDate extends MatDateRangeInputPartBase {
|
|
4080
|
-
/** Validator that checks that the end date isn't before the start date. */
|
|
4081
|
-
_endValidator = (control) => {
|
|
4082
|
-
const end = this._dateAdapter.getValidDateOrNull(this._dateAdapter.deserialize(control.value));
|
|
4083
|
-
const start = this._model ? this._model.selection.start : null;
|
|
4084
|
-
return !end || !start || this._dateAdapter.compareDate(end, start) >= 0
|
|
4085
|
-
? null
|
|
4086
|
-
: { 'matEndDateInvalid': { 'start': start, 'actual': end } };
|
|
4087
|
-
};
|
|
4088
|
-
_validator = Validators.compose([...super._getValidators(), this._endValidator]);
|
|
4089
|
-
_getValueFromModel(modelValue) {
|
|
4090
|
-
return modelValue.end;
|
|
4091
|
-
}
|
|
4092
|
-
_shouldHandleChangeEvent(change) {
|
|
4093
|
-
if (!super._shouldHandleChangeEvent(change)) {
|
|
4094
|
-
return false;
|
|
4095
|
-
}
|
|
4096
|
-
else {
|
|
4097
|
-
return !change.oldValue?.end
|
|
4098
|
-
? !!change.selection.end
|
|
4099
|
-
: !change.selection.end ||
|
|
4100
|
-
!!this._dateAdapter.compareDate(change.oldValue.end, change.selection.end);
|
|
4101
|
-
}
|
|
4102
|
-
}
|
|
4103
|
-
_assignValueToModel(value) {
|
|
4104
|
-
if (this._model) {
|
|
4105
|
-
const range = new DateRange(this._model.selection.start, value);
|
|
4106
|
-
this._model.updateSelection(range, this);
|
|
4107
|
-
}
|
|
4108
|
-
}
|
|
4109
|
-
_moveCaretToEndOfStartInput() {
|
|
4110
|
-
const startInput = this._rangeInput._startInput._elementRef.nativeElement;
|
|
4111
|
-
const value = startInput.value;
|
|
4112
|
-
if (value.length > 0) {
|
|
4113
|
-
startInput.setSelectionRange(value.length, value.length);
|
|
4114
|
-
}
|
|
4115
|
-
startInput.focus();
|
|
4116
|
-
}
|
|
4117
|
-
_onKeydown(event) {
|
|
4118
|
-
const element = this._elementRef.nativeElement;
|
|
4119
|
-
const isLtr = this._dir?.value !== 'rtl';
|
|
4120
|
-
// If the user is pressing backspace on an empty end input, move focus back to the start.
|
|
4121
|
-
if (event.keyCode === BACKSPACE && !element.value) {
|
|
4122
|
-
this._moveCaretToEndOfStartInput();
|
|
4123
|
-
}
|
|
4124
|
-
// If the user hits LEFT (LTR) when at the start of the input (and no
|
|
4125
|
-
// selection), move the cursor to the end of the start input.
|
|
4126
|
-
else if (((event.keyCode === LEFT_ARROW && isLtr) || (event.keyCode === RIGHT_ARROW && !isLtr)) &&
|
|
4127
|
-
element.selectionStart === 0 &&
|
|
4128
|
-
element.selectionEnd === 0) {
|
|
4129
|
-
event.preventDefault();
|
|
4130
|
-
this._moveCaretToEndOfStartInput();
|
|
4131
|
-
}
|
|
4132
|
-
else {
|
|
4133
|
-
super._onKeydown(event);
|
|
4134
|
-
}
|
|
4135
|
-
}
|
|
4136
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatEndDate, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
4137
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.0", type: MatEndDate, isStandalone: true, selector: "input[matEndDate]", outputs: { dateChange: "dateChange", dateInput: "dateInput" }, host: { attributes: { "type": "text" }, listeners: { "input": "_onInput($event.target.value)", "change": "_onChange()", "keydown": "_onKeydown($event)", "blur": "_onBlur()" }, properties: { "disabled": "disabled", "attr.aria-haspopup": "_rangeInput.rangePicker ? \"dialog\" : null", "attr.aria-owns": "_rangeInput._ariaOwns\n ? _rangeInput._ariaOwns()\n : (_rangeInput.rangePicker?.opened && _rangeInput.rangePicker.id) || null", "attr.min": "_getMinDate() ? _dateAdapter.toIso8601(_getMinDate()) : null", "attr.max": "_getMaxDate() ? _dateAdapter.toIso8601(_getMaxDate()) : null" }, classAttribute: "mat-end-date mat-date-range-input-inner" }, providers: [
|
|
4138
|
-
{ provide: NG_VALUE_ACCESSOR, useExisting: MatEndDate, multi: true },
|
|
4139
|
-
{ provide: NG_VALIDATORS, useExisting: MatEndDate, multi: true },
|
|
4140
|
-
], usesInheritance: true, ngImport: i0 });
|
|
4141
|
-
}
|
|
4142
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatEndDate, decorators: [{
|
|
4143
|
-
type: Directive,
|
|
4144
|
-
args: [{
|
|
4145
|
-
selector: 'input[matEndDate]',
|
|
4146
|
-
host: {
|
|
4147
|
-
'class': 'mat-end-date mat-date-range-input-inner',
|
|
4148
|
-
'[disabled]': 'disabled',
|
|
4149
|
-
'(input)': '_onInput($event.target.value)',
|
|
4150
|
-
'(change)': '_onChange()',
|
|
4151
|
-
'(keydown)': '_onKeydown($event)',
|
|
4152
|
-
'[attr.aria-haspopup]': '_rangeInput.rangePicker ? "dialog" : null',
|
|
4153
|
-
'[attr.aria-owns]': `_rangeInput._ariaOwns
|
|
4154
|
-
? _rangeInput._ariaOwns()
|
|
4155
|
-
: (_rangeInput.rangePicker?.opened && _rangeInput.rangePicker.id) || null`,
|
|
4156
|
-
'[attr.min]': '_getMinDate() ? _dateAdapter.toIso8601(_getMinDate()) : null',
|
|
4157
|
-
'[attr.max]': '_getMaxDate() ? _dateAdapter.toIso8601(_getMaxDate()) : null',
|
|
4158
|
-
'(blur)': '_onBlur()',
|
|
4159
|
-
'type': 'text',
|
|
4160
|
-
},
|
|
4161
|
-
providers: [
|
|
4162
|
-
{ provide: NG_VALUE_ACCESSOR, useExisting: MatEndDate, multi: true },
|
|
4163
|
-
{ provide: NG_VALIDATORS, useExisting: MatEndDate, multi: true },
|
|
4164
|
-
],
|
|
4165
|
-
// These need to be specified explicitly, because some tooling doesn't
|
|
4166
|
-
// seem to pick them up from the base class. See #20932.
|
|
4167
|
-
outputs: ['dateChange', 'dateInput'],
|
|
4168
|
-
}]
|
|
4169
|
-
}] });
|
|
4170
|
-
|
|
4171
3710
|
class MatDateRangeInput {
|
|
4172
3711
|
_changeDetectorRef = inject(ChangeDetectorRef);
|
|
4173
3712
|
_elementRef = inject(ElementRef);
|
|
@@ -4175,6 +3714,8 @@ class MatDateRangeInput {
|
|
|
4175
3714
|
_formField = inject(MAT_FORM_FIELD, { optional: true });
|
|
4176
3715
|
_closedSubscription = Subscription.EMPTY;
|
|
4177
3716
|
_openedSubscription = Subscription.EMPTY;
|
|
3717
|
+
_startInput;
|
|
3718
|
+
_endInput;
|
|
4178
3719
|
/** Current value of the range input. */
|
|
4179
3720
|
get value() {
|
|
4180
3721
|
return this._model ? this._model.selection : null;
|
|
@@ -4187,339 +3728,790 @@ class MatDateRangeInput {
|
|
|
4187
3728
|
get shouldLabelFloat() {
|
|
4188
3729
|
return this.focused || !this.empty;
|
|
4189
3730
|
}
|
|
4190
|
-
/** Name of the form control. */
|
|
4191
|
-
controlType = 'mat-date-range-input';
|
|
4192
|
-
/**
|
|
4193
|
-
* Implemented as a part of `MatFormFieldControl`.
|
|
4194
|
-
* Set the placeholder attribute on `matStartDate` and `matEndDate`.
|
|
4195
|
-
* @docs-private
|
|
4196
|
-
*/
|
|
4197
|
-
get placeholder() {
|
|
4198
|
-
const start = this._startInput?._getPlaceholder() || '';
|
|
4199
|
-
const end = this._endInput?._getPlaceholder() || '';
|
|
4200
|
-
return start || end ? `${start} ${this.separator} ${end}` : '';
|
|
3731
|
+
/** Name of the form control. */
|
|
3732
|
+
controlType = 'mat-date-range-input';
|
|
3733
|
+
/**
|
|
3734
|
+
* Implemented as a part of `MatFormFieldControl`.
|
|
3735
|
+
* Set the placeholder attribute on `matStartDate` and `matEndDate`.
|
|
3736
|
+
* @docs-private
|
|
3737
|
+
*/
|
|
3738
|
+
get placeholder() {
|
|
3739
|
+
const start = this._startInput?._getPlaceholder() || '';
|
|
3740
|
+
const end = this._endInput?._getPlaceholder() || '';
|
|
3741
|
+
return start || end ? `${start} ${this.separator} ${end}` : '';
|
|
3742
|
+
}
|
|
3743
|
+
/** The range picker that this input is associated with. */
|
|
3744
|
+
get rangePicker() {
|
|
3745
|
+
return this._rangePicker;
|
|
3746
|
+
}
|
|
3747
|
+
set rangePicker(rangePicker) {
|
|
3748
|
+
if (rangePicker) {
|
|
3749
|
+
this._model = rangePicker.registerInput(this);
|
|
3750
|
+
this._rangePicker = rangePicker;
|
|
3751
|
+
this._closedSubscription.unsubscribe();
|
|
3752
|
+
this._openedSubscription.unsubscribe();
|
|
3753
|
+
this._ariaOwns.set(this.rangePicker.opened ? rangePicker.id : null);
|
|
3754
|
+
this._closedSubscription = rangePicker.closedStream.subscribe(() => {
|
|
3755
|
+
this._startInput?._onTouched();
|
|
3756
|
+
this._endInput?._onTouched();
|
|
3757
|
+
this._ariaOwns.set(null);
|
|
3758
|
+
});
|
|
3759
|
+
this._openedSubscription = rangePicker.openedStream.subscribe(() => {
|
|
3760
|
+
this._ariaOwns.set(rangePicker.id);
|
|
3761
|
+
});
|
|
3762
|
+
this._registerModel(this._model);
|
|
3763
|
+
}
|
|
3764
|
+
}
|
|
3765
|
+
_rangePicker;
|
|
3766
|
+
/** The id of the panel owned by this input. */
|
|
3767
|
+
_ariaOwns = signal(null);
|
|
3768
|
+
/** Whether the input is required. */
|
|
3769
|
+
get required() {
|
|
3770
|
+
return (this._required ??
|
|
3771
|
+
(this._isTargetRequired(this) ||
|
|
3772
|
+
this._isTargetRequired(this._startInput) ||
|
|
3773
|
+
this._isTargetRequired(this._endInput)) ??
|
|
3774
|
+
false);
|
|
3775
|
+
}
|
|
3776
|
+
set required(value) {
|
|
3777
|
+
this._required = value;
|
|
3778
|
+
}
|
|
3779
|
+
_required;
|
|
3780
|
+
/** Function that can be used to filter out dates within the date range picker. */
|
|
3781
|
+
get dateFilter() {
|
|
3782
|
+
return this._dateFilter;
|
|
3783
|
+
}
|
|
3784
|
+
set dateFilter(value) {
|
|
3785
|
+
const start = this._startInput;
|
|
3786
|
+
const end = this._endInput;
|
|
3787
|
+
const wasMatchingStart = start && start._matchesFilter(start.value);
|
|
3788
|
+
const wasMatchingEnd = end && end._matchesFilter(start.value);
|
|
3789
|
+
this._dateFilter = value;
|
|
3790
|
+
if (start && start._matchesFilter(start.value) !== wasMatchingStart) {
|
|
3791
|
+
start._validatorOnChange();
|
|
3792
|
+
}
|
|
3793
|
+
if (end && end._matchesFilter(end.value) !== wasMatchingEnd) {
|
|
3794
|
+
end._validatorOnChange();
|
|
3795
|
+
}
|
|
3796
|
+
}
|
|
3797
|
+
_dateFilter;
|
|
3798
|
+
/** The minimum valid date. */
|
|
3799
|
+
get min() {
|
|
3800
|
+
return this._min;
|
|
3801
|
+
}
|
|
3802
|
+
set min(value) {
|
|
3803
|
+
const validValue = this._dateAdapter.getValidDateOrNull(this._dateAdapter.deserialize(value));
|
|
3804
|
+
if (!this._dateAdapter.sameDate(validValue, this._min)) {
|
|
3805
|
+
this._min = validValue;
|
|
3806
|
+
this._revalidate();
|
|
3807
|
+
}
|
|
3808
|
+
}
|
|
3809
|
+
_min;
|
|
3810
|
+
/** The maximum valid date. */
|
|
3811
|
+
get max() {
|
|
3812
|
+
return this._max;
|
|
3813
|
+
}
|
|
3814
|
+
set max(value) {
|
|
3815
|
+
const validValue = this._dateAdapter.getValidDateOrNull(this._dateAdapter.deserialize(value));
|
|
3816
|
+
if (!this._dateAdapter.sameDate(validValue, this._max)) {
|
|
3817
|
+
this._max = validValue;
|
|
3818
|
+
this._revalidate();
|
|
3819
|
+
}
|
|
3820
|
+
}
|
|
3821
|
+
_max;
|
|
3822
|
+
/** Whether the input is disabled. */
|
|
3823
|
+
get disabled() {
|
|
3824
|
+
return this._startInput && this._endInput
|
|
3825
|
+
? this._startInput.disabled && this._endInput.disabled
|
|
3826
|
+
: this._groupDisabled;
|
|
3827
|
+
}
|
|
3828
|
+
set disabled(value) {
|
|
3829
|
+
if (value !== this._groupDisabled) {
|
|
3830
|
+
this._groupDisabled = value;
|
|
3831
|
+
this.stateChanges.next(undefined);
|
|
3832
|
+
}
|
|
3833
|
+
}
|
|
3834
|
+
_groupDisabled = false;
|
|
3835
|
+
/** Whether the input is in an error state. */
|
|
3836
|
+
get errorState() {
|
|
3837
|
+
if (this._startInput && this._endInput) {
|
|
3838
|
+
return this._startInput.errorState || this._endInput.errorState;
|
|
3839
|
+
}
|
|
3840
|
+
return false;
|
|
3841
|
+
}
|
|
3842
|
+
/** Whether the datepicker input is empty. */
|
|
3843
|
+
get empty() {
|
|
3844
|
+
const startEmpty = this._startInput ? this._startInput.isEmpty() : false;
|
|
3845
|
+
const endEmpty = this._endInput ? this._endInput.isEmpty() : false;
|
|
3846
|
+
return startEmpty && endEmpty;
|
|
3847
|
+
}
|
|
3848
|
+
/** Value for the `aria-describedby` attribute of the inputs. */
|
|
3849
|
+
_ariaDescribedBy = null;
|
|
3850
|
+
/** Date selection model currently registered with the input. */
|
|
3851
|
+
_model;
|
|
3852
|
+
/** Separator text to be shown between the inputs. */
|
|
3853
|
+
separator = '–';
|
|
3854
|
+
/** Start of the comparison range that should be shown in the calendar. */
|
|
3855
|
+
comparisonStart = null;
|
|
3856
|
+
/** End of the comparison range that should be shown in the calendar. */
|
|
3857
|
+
comparisonEnd = null;
|
|
3858
|
+
/**
|
|
3859
|
+
* Implemented as a part of `MatFormFieldControl`.
|
|
3860
|
+
* TODO(crisbeto): change type to `AbstractControlDirective` after #18206 lands.
|
|
3861
|
+
* @docs-private
|
|
3862
|
+
*/
|
|
3863
|
+
ngControl;
|
|
3864
|
+
/** Emits when the input's state has changed. */
|
|
3865
|
+
stateChanges = new Subject();
|
|
3866
|
+
/**
|
|
3867
|
+
* Disable the automatic labeling to avoid issues like #27241.
|
|
3868
|
+
* @docs-private
|
|
3869
|
+
*/
|
|
3870
|
+
disableAutomaticLabeling = true;
|
|
3871
|
+
constructor() {
|
|
3872
|
+
if (!this._dateAdapter && (typeof ngDevMode === 'undefined' || ngDevMode)) {
|
|
3873
|
+
throw createMissingDateImplError('DateAdapter');
|
|
3874
|
+
}
|
|
3875
|
+
// The datepicker module can be used both with MDC and non-MDC form fields. We have
|
|
3876
|
+
// to conditionally add the MDC input class so that the range picker looks correctly.
|
|
3877
|
+
if (this._formField?._elementRef.nativeElement.classList.contains('mat-mdc-form-field')) {
|
|
3878
|
+
this._elementRef.nativeElement.classList.add('mat-mdc-input-element', 'mat-mdc-form-field-input-control', 'mdc-text-field__input');
|
|
3879
|
+
}
|
|
3880
|
+
// TODO(crisbeto): remove `as any` after #18206 lands.
|
|
3881
|
+
this.ngControl = inject(ControlContainer, { optional: true, self: true });
|
|
3882
|
+
}
|
|
3883
|
+
/**
|
|
3884
|
+
* Implemented as a part of `MatFormFieldControl`.
|
|
3885
|
+
* @docs-private
|
|
3886
|
+
*/
|
|
3887
|
+
setDescribedByIds(ids) {
|
|
3888
|
+
this._ariaDescribedBy = ids.length ? ids.join(' ') : null;
|
|
3889
|
+
}
|
|
3890
|
+
/**
|
|
3891
|
+
* Implemented as a part of `MatFormFieldControl`.
|
|
3892
|
+
* @docs-private
|
|
3893
|
+
*/
|
|
3894
|
+
onContainerClick() {
|
|
3895
|
+
if (!this.focused && !this.disabled) {
|
|
3896
|
+
if (!this._model || !this._model.selection.start) {
|
|
3897
|
+
this._startInput.focus();
|
|
3898
|
+
}
|
|
3899
|
+
else {
|
|
3900
|
+
this._endInput.focus();
|
|
3901
|
+
}
|
|
3902
|
+
}
|
|
3903
|
+
}
|
|
3904
|
+
ngAfterContentInit() {
|
|
3905
|
+
if (typeof ngDevMode === 'undefined' || ngDevMode) {
|
|
3906
|
+
if (!this._startInput) {
|
|
3907
|
+
throw Error('mat-date-range-input must contain a matStartDate input');
|
|
3908
|
+
}
|
|
3909
|
+
if (!this._endInput) {
|
|
3910
|
+
throw Error('mat-date-range-input must contain a matEndDate input');
|
|
3911
|
+
}
|
|
3912
|
+
}
|
|
3913
|
+
if (this._model) {
|
|
3914
|
+
this._registerModel(this._model);
|
|
3915
|
+
}
|
|
3916
|
+
// We don't need to unsubscribe from this, because we
|
|
3917
|
+
// know that the input streams will be completed on destroy.
|
|
3918
|
+
merge(this._startInput.stateChanges, this._endInput.stateChanges).subscribe(() => {
|
|
3919
|
+
this.stateChanges.next(undefined);
|
|
3920
|
+
});
|
|
3921
|
+
}
|
|
3922
|
+
ngOnChanges(changes) {
|
|
3923
|
+
if (dateInputsHaveChanged(changes, this._dateAdapter)) {
|
|
3924
|
+
this.stateChanges.next(undefined);
|
|
3925
|
+
}
|
|
3926
|
+
}
|
|
3927
|
+
ngOnDestroy() {
|
|
3928
|
+
this._closedSubscription.unsubscribe();
|
|
3929
|
+
this._openedSubscription.unsubscribe();
|
|
3930
|
+
this.stateChanges.complete();
|
|
3931
|
+
}
|
|
3932
|
+
/** Gets the date at which the calendar should start. */
|
|
3933
|
+
getStartValue() {
|
|
3934
|
+
return this.value ? this.value.start : null;
|
|
3935
|
+
}
|
|
3936
|
+
/** Gets the input's theme palette. */
|
|
3937
|
+
getThemePalette() {
|
|
3938
|
+
return this._formField ? this._formField.color : undefined;
|
|
3939
|
+
}
|
|
3940
|
+
/** Gets the element to which the calendar overlay should be attached. */
|
|
3941
|
+
getConnectedOverlayOrigin() {
|
|
3942
|
+
return this._formField ? this._formField.getConnectedOverlayOrigin() : this._elementRef;
|
|
3943
|
+
}
|
|
3944
|
+
/** Gets the ID of an element that should be used a description for the calendar overlay. */
|
|
3945
|
+
getOverlayLabelId() {
|
|
3946
|
+
return this._formField ? this._formField.getLabelId() : null;
|
|
3947
|
+
}
|
|
3948
|
+
/** Gets the value that is used to mirror the state input. */
|
|
3949
|
+
_getInputMirrorValue(part) {
|
|
3950
|
+
const input = part === 'start' ? this._startInput : this._endInput;
|
|
3951
|
+
return input ? input.getMirrorValue() : '';
|
|
3952
|
+
}
|
|
3953
|
+
/** Whether the input placeholders should be hidden. */
|
|
3954
|
+
_shouldHidePlaceholders() {
|
|
3955
|
+
return this._startInput ? !this._startInput.isEmpty() : false;
|
|
4201
3956
|
}
|
|
4202
|
-
/**
|
|
4203
|
-
|
|
4204
|
-
|
|
3957
|
+
/** Handles the value in one of the child inputs changing. */
|
|
3958
|
+
_handleChildValueChange() {
|
|
3959
|
+
this.stateChanges.next(undefined);
|
|
3960
|
+
this._changeDetectorRef.markForCheck();
|
|
4205
3961
|
}
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
this._rangePicker
|
|
4210
|
-
this._closedSubscription.unsubscribe();
|
|
4211
|
-
this._openedSubscription.unsubscribe();
|
|
4212
|
-
this._ariaOwns.set(this.rangePicker.opened ? rangePicker.id : null);
|
|
4213
|
-
this._closedSubscription = rangePicker.closedStream.subscribe(() => {
|
|
4214
|
-
this._startInput?._onTouched();
|
|
4215
|
-
this._endInput?._onTouched();
|
|
4216
|
-
this._ariaOwns.set(null);
|
|
4217
|
-
});
|
|
4218
|
-
this._openedSubscription = rangePicker.openedStream.subscribe(() => {
|
|
4219
|
-
this._ariaOwns.set(rangePicker.id);
|
|
4220
|
-
});
|
|
4221
|
-
this._registerModel(this._model);
|
|
3962
|
+
/** Opens the date range picker associated with the input. */
|
|
3963
|
+
_openDatepicker() {
|
|
3964
|
+
if (this._rangePicker) {
|
|
3965
|
+
this._rangePicker.open();
|
|
4222
3966
|
}
|
|
4223
3967
|
}
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
return (this._required ??
|
|
4230
|
-
(this._isTargetRequired(this) ||
|
|
4231
|
-
this._isTargetRequired(this._startInput) ||
|
|
4232
|
-
this._isTargetRequired(this._endInput)) ??
|
|
4233
|
-
false);
|
|
3968
|
+
/** Whether the separate text should be hidden. */
|
|
3969
|
+
_shouldHideSeparator() {
|
|
3970
|
+
return ((!this._formField ||
|
|
3971
|
+
(this._formField.getLabelId() && !this._formField._shouldLabelFloat())) &&
|
|
3972
|
+
this.empty);
|
|
4234
3973
|
}
|
|
4235
|
-
|
|
4236
|
-
|
|
3974
|
+
/** Gets the value for the `aria-labelledby` attribute of the inputs. */
|
|
3975
|
+
_getAriaLabelledby() {
|
|
3976
|
+
const formField = this._formField;
|
|
3977
|
+
return formField && formField._hasFloatingLabel() ? formField._labelId : null;
|
|
4237
3978
|
}
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
get dateFilter() {
|
|
4241
|
-
return this._dateFilter;
|
|
3979
|
+
_getStartDateAccessibleName() {
|
|
3980
|
+
return this._startInput._getAccessibleName();
|
|
4242
3981
|
}
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
|
|
4247
|
-
|
|
4248
|
-
this.
|
|
4249
|
-
|
|
4250
|
-
|
|
3982
|
+
_getEndDateAccessibleName() {
|
|
3983
|
+
return this._endInput._getAccessibleName();
|
|
3984
|
+
}
|
|
3985
|
+
/** Updates the focused state of the range input. */
|
|
3986
|
+
_updateFocus(origin) {
|
|
3987
|
+
this.focused = origin !== null;
|
|
3988
|
+
this.stateChanges.next();
|
|
3989
|
+
}
|
|
3990
|
+
/** Re-runs the validators on the start/end inputs. */
|
|
3991
|
+
_revalidate() {
|
|
3992
|
+
if (this._startInput) {
|
|
3993
|
+
this._startInput._validatorOnChange();
|
|
4251
3994
|
}
|
|
4252
|
-
if (
|
|
4253
|
-
|
|
3995
|
+
if (this._endInput) {
|
|
3996
|
+
this._endInput._validatorOnChange();
|
|
4254
3997
|
}
|
|
4255
3998
|
}
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
if (!this._dateAdapter.sameDate(validValue, this._min)) {
|
|
4264
|
-
this._min = validValue;
|
|
4265
|
-
this._revalidate();
|
|
3999
|
+
/** Registers the current date selection model with the start/end inputs. */
|
|
4000
|
+
_registerModel(model) {
|
|
4001
|
+
if (this._startInput) {
|
|
4002
|
+
this._startInput._registerModel(model);
|
|
4003
|
+
}
|
|
4004
|
+
if (this._endInput) {
|
|
4005
|
+
this._endInput._registerModel(model);
|
|
4266
4006
|
}
|
|
4267
4007
|
}
|
|
4268
|
-
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
return this._max;
|
|
4008
|
+
/** Checks whether a specific range input directive is required. */
|
|
4009
|
+
_isTargetRequired(target) {
|
|
4010
|
+
return target?.ngControl?.control?.hasValidator(Validators.required);
|
|
4272
4011
|
}
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4012
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatDateRangeInput, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4013
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "16.1.0", version: "19.0.0", type: MatDateRangeInput, isStandalone: true, selector: "mat-date-range-input", inputs: { rangePicker: "rangePicker", required: ["required", "required", booleanAttribute], dateFilter: "dateFilter", min: "min", max: "max", disabled: ["disabled", "disabled", booleanAttribute], separator: "separator", comparisonStart: "comparisonStart", comparisonEnd: "comparisonEnd" }, host: { attributes: { "role": "group" }, properties: { "class.mat-date-range-input-hide-placeholders": "_shouldHidePlaceholders()", "class.mat-date-range-input-required": "required", "attr.id": "id", "attr.aria-labelledby": "_getAriaLabelledby()", "attr.aria-describedby": "_ariaDescribedBy", "attr.data-mat-calendar": "rangePicker ? rangePicker.id : null" }, classAttribute: "mat-date-range-input" }, providers: [{ provide: MatFormFieldControl, useExisting: MatDateRangeInput }], exportAs: ["matDateRangeInput"], usesOnChanges: true, ngImport: i0, template: "<div\n class=\"mat-date-range-input-container\"\n cdkMonitorSubtreeFocus\n (cdkFocusChange)=\"_updateFocus($event)\">\n <div class=\"mat-date-range-input-wrapper\">\n <ng-content select=\"input[matStartDate]\"></ng-content>\n <span\n class=\"mat-date-range-input-mirror\"\n aria-hidden=\"true\">{{_getInputMirrorValue('start')}}</span>\n </div>\n\n <span\n class=\"mat-date-range-input-separator\"\n [class.mat-date-range-input-separator-hidden]=\"_shouldHideSeparator()\">{{separator}}</span>\n\n <div class=\"mat-date-range-input-wrapper mat-date-range-input-end-wrapper\">\n <ng-content select=\"input[matEndDate]\"></ng-content>\n <span\n class=\"mat-date-range-input-mirror\"\n aria-hidden=\"true\">{{_getInputMirrorValue('end')}}</span>\n </div>\n</div>\n\n", styles: [".mat-date-range-input{display:block;width:100%}.mat-date-range-input-container{display:flex;align-items:center}.mat-date-range-input-separator{transition:opacity 400ms 133.3333333333ms cubic-bezier(0.25, 0.8, 0.25, 1);margin:0 4px;color:var(--mat-datepicker-range-input-separator-color, var(--mat-sys-on-surface))}.mat-form-field-disabled .mat-date-range-input-separator{color:var(--mat-datepicker-range-input-disabled-state-separator-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}._mat-animation-noopable .mat-date-range-input-separator{transition:none}.mat-date-range-input-separator-hidden{-webkit-user-select:none;user-select:none;opacity:0;transition:none}.mat-date-range-input-wrapper{position:relative;overflow:hidden;max-width:calc(50% - 4px)}.mat-date-range-input-end-wrapper{flex-grow:1}.mat-date-range-input-inner{position:absolute;top:0;left:0;font:inherit;background:rgba(0,0,0,0);color:currentColor;border:none;outline:none;padding:0;margin:0;vertical-align:bottom;text-align:inherit;-webkit-appearance:none;width:100%;height:100%}.mat-date-range-input-inner:-moz-ui-invalid{box-shadow:none}.mat-date-range-input-inner::placeholder{transition:color 400ms 133.3333333333ms cubic-bezier(0.25, 0.8, 0.25, 1)}.mat-date-range-input-inner::-moz-placeholder{transition:color 400ms 133.3333333333ms cubic-bezier(0.25, 0.8, 0.25, 1)}.mat-date-range-input-inner::-webkit-input-placeholder{transition:color 400ms 133.3333333333ms cubic-bezier(0.25, 0.8, 0.25, 1)}.mat-date-range-input-inner:-ms-input-placeholder{transition:color 400ms 133.3333333333ms cubic-bezier(0.25, 0.8, 0.25, 1)}.mat-date-range-input-inner[disabled]{color:var(--mat-datepicker-range-input-disabled-state-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-form-field-hide-placeholder .mat-date-range-input-inner::placeholder,.mat-date-range-input-hide-placeholders .mat-date-range-input-inner::placeholder{-webkit-user-select:none;user-select:none;color:rgba(0,0,0,0) !important;-webkit-text-fill-color:rgba(0,0,0,0);transition:none}@media(forced-colors: active){.mat-form-field-hide-placeholder .mat-date-range-input-inner::placeholder,.mat-date-range-input-hide-placeholders .mat-date-range-input-inner::placeholder{opacity:0}}.mat-form-field-hide-placeholder .mat-date-range-input-inner::-moz-placeholder,.mat-date-range-input-hide-placeholders .mat-date-range-input-inner::-moz-placeholder{-webkit-user-select:none;user-select:none;color:rgba(0,0,0,0) !important;-webkit-text-fill-color:rgba(0,0,0,0);transition:none}@media(forced-colors: active){.mat-form-field-hide-placeholder .mat-date-range-input-inner::-moz-placeholder,.mat-date-range-input-hide-placeholders .mat-date-range-input-inner::-moz-placeholder{opacity:0}}.mat-form-field-hide-placeholder .mat-date-range-input-inner::-webkit-input-placeholder,.mat-date-range-input-hide-placeholders .mat-date-range-input-inner::-webkit-input-placeholder{-webkit-user-select:none;user-select:none;color:rgba(0,0,0,0) !important;-webkit-text-fill-color:rgba(0,0,0,0);transition:none}@media(forced-colors: active){.mat-form-field-hide-placeholder .mat-date-range-input-inner::-webkit-input-placeholder,.mat-date-range-input-hide-placeholders .mat-date-range-input-inner::-webkit-input-placeholder{opacity:0}}.mat-form-field-hide-placeholder .mat-date-range-input-inner:-ms-input-placeholder,.mat-date-range-input-hide-placeholders .mat-date-range-input-inner:-ms-input-placeholder{-webkit-user-select:none;user-select:none;color:rgba(0,0,0,0) !important;-webkit-text-fill-color:rgba(0,0,0,0);transition:none}@media(forced-colors: active){.mat-form-field-hide-placeholder .mat-date-range-input-inner:-ms-input-placeholder,.mat-date-range-input-hide-placeholders .mat-date-range-input-inner:-ms-input-placeholder{opacity:0}}._mat-animation-noopable .mat-date-range-input-inner::placeholder{transition:none}._mat-animation-noopable .mat-date-range-input-inner::-moz-placeholder{transition:none}._mat-animation-noopable .mat-date-range-input-inner::-webkit-input-placeholder{transition:none}._mat-animation-noopable .mat-date-range-input-inner:-ms-input-placeholder{transition:none}.mat-date-range-input-mirror{-webkit-user-select:none;user-select:none;visibility:hidden;white-space:nowrap;display:inline-block;min-width:2px}.mat-mdc-form-field-type-mat-date-range-input .mat-mdc-form-field-infix{width:200px}"], dependencies: [{ kind: "directive", type: CdkMonitorFocus, selector: "[cdkMonitorElementFocus], [cdkMonitorSubtreeFocus]", outputs: ["cdkFocusChange"], exportAs: ["cdkMonitorFocus"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
4014
|
+
}
|
|
4015
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatDateRangeInput, decorators: [{
|
|
4016
|
+
type: Component,
|
|
4017
|
+
args: [{ selector: 'mat-date-range-input', exportAs: 'matDateRangeInput', host: {
|
|
4018
|
+
'class': 'mat-date-range-input',
|
|
4019
|
+
'[class.mat-date-range-input-hide-placeholders]': '_shouldHidePlaceholders()',
|
|
4020
|
+
'[class.mat-date-range-input-required]': 'required',
|
|
4021
|
+
'[attr.id]': 'id',
|
|
4022
|
+
'role': 'group',
|
|
4023
|
+
'[attr.aria-labelledby]': '_getAriaLabelledby()',
|
|
4024
|
+
'[attr.aria-describedby]': '_ariaDescribedBy',
|
|
4025
|
+
// Used by the test harness to tie this input to its calendar. We can't depend on
|
|
4026
|
+
// `aria-owns` for this, because it's only defined while the calendar is open.
|
|
4027
|
+
'[attr.data-mat-calendar]': 'rangePicker ? rangePicker.id : null',
|
|
4028
|
+
}, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, providers: [{ provide: MatFormFieldControl, useExisting: MatDateRangeInput }], imports: [CdkMonitorFocus], template: "<div\n class=\"mat-date-range-input-container\"\n cdkMonitorSubtreeFocus\n (cdkFocusChange)=\"_updateFocus($event)\">\n <div class=\"mat-date-range-input-wrapper\">\n <ng-content select=\"input[matStartDate]\"></ng-content>\n <span\n class=\"mat-date-range-input-mirror\"\n aria-hidden=\"true\">{{_getInputMirrorValue('start')}}</span>\n </div>\n\n <span\n class=\"mat-date-range-input-separator\"\n [class.mat-date-range-input-separator-hidden]=\"_shouldHideSeparator()\">{{separator}}</span>\n\n <div class=\"mat-date-range-input-wrapper mat-date-range-input-end-wrapper\">\n <ng-content select=\"input[matEndDate]\"></ng-content>\n <span\n class=\"mat-date-range-input-mirror\"\n aria-hidden=\"true\">{{_getInputMirrorValue('end')}}</span>\n </div>\n</div>\n\n", styles: [".mat-date-range-input{display:block;width:100%}.mat-date-range-input-container{display:flex;align-items:center}.mat-date-range-input-separator{transition:opacity 400ms 133.3333333333ms cubic-bezier(0.25, 0.8, 0.25, 1);margin:0 4px;color:var(--mat-datepicker-range-input-separator-color, var(--mat-sys-on-surface))}.mat-form-field-disabled .mat-date-range-input-separator{color:var(--mat-datepicker-range-input-disabled-state-separator-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}._mat-animation-noopable .mat-date-range-input-separator{transition:none}.mat-date-range-input-separator-hidden{-webkit-user-select:none;user-select:none;opacity:0;transition:none}.mat-date-range-input-wrapper{position:relative;overflow:hidden;max-width:calc(50% - 4px)}.mat-date-range-input-end-wrapper{flex-grow:1}.mat-date-range-input-inner{position:absolute;top:0;left:0;font:inherit;background:rgba(0,0,0,0);color:currentColor;border:none;outline:none;padding:0;margin:0;vertical-align:bottom;text-align:inherit;-webkit-appearance:none;width:100%;height:100%}.mat-date-range-input-inner:-moz-ui-invalid{box-shadow:none}.mat-date-range-input-inner::placeholder{transition:color 400ms 133.3333333333ms cubic-bezier(0.25, 0.8, 0.25, 1)}.mat-date-range-input-inner::-moz-placeholder{transition:color 400ms 133.3333333333ms cubic-bezier(0.25, 0.8, 0.25, 1)}.mat-date-range-input-inner::-webkit-input-placeholder{transition:color 400ms 133.3333333333ms cubic-bezier(0.25, 0.8, 0.25, 1)}.mat-date-range-input-inner:-ms-input-placeholder{transition:color 400ms 133.3333333333ms cubic-bezier(0.25, 0.8, 0.25, 1)}.mat-date-range-input-inner[disabled]{color:var(--mat-datepicker-range-input-disabled-state-text-color, color-mix(in srgb, var(--mat-sys-on-surface) 38%, transparent))}.mat-form-field-hide-placeholder .mat-date-range-input-inner::placeholder,.mat-date-range-input-hide-placeholders .mat-date-range-input-inner::placeholder{-webkit-user-select:none;user-select:none;color:rgba(0,0,0,0) !important;-webkit-text-fill-color:rgba(0,0,0,0);transition:none}@media(forced-colors: active){.mat-form-field-hide-placeholder .mat-date-range-input-inner::placeholder,.mat-date-range-input-hide-placeholders .mat-date-range-input-inner::placeholder{opacity:0}}.mat-form-field-hide-placeholder .mat-date-range-input-inner::-moz-placeholder,.mat-date-range-input-hide-placeholders .mat-date-range-input-inner::-moz-placeholder{-webkit-user-select:none;user-select:none;color:rgba(0,0,0,0) !important;-webkit-text-fill-color:rgba(0,0,0,0);transition:none}@media(forced-colors: active){.mat-form-field-hide-placeholder .mat-date-range-input-inner::-moz-placeholder,.mat-date-range-input-hide-placeholders .mat-date-range-input-inner::-moz-placeholder{opacity:0}}.mat-form-field-hide-placeholder .mat-date-range-input-inner::-webkit-input-placeholder,.mat-date-range-input-hide-placeholders .mat-date-range-input-inner::-webkit-input-placeholder{-webkit-user-select:none;user-select:none;color:rgba(0,0,0,0) !important;-webkit-text-fill-color:rgba(0,0,0,0);transition:none}@media(forced-colors: active){.mat-form-field-hide-placeholder .mat-date-range-input-inner::-webkit-input-placeholder,.mat-date-range-input-hide-placeholders .mat-date-range-input-inner::-webkit-input-placeholder{opacity:0}}.mat-form-field-hide-placeholder .mat-date-range-input-inner:-ms-input-placeholder,.mat-date-range-input-hide-placeholders .mat-date-range-input-inner:-ms-input-placeholder{-webkit-user-select:none;user-select:none;color:rgba(0,0,0,0) !important;-webkit-text-fill-color:rgba(0,0,0,0);transition:none}@media(forced-colors: active){.mat-form-field-hide-placeholder .mat-date-range-input-inner:-ms-input-placeholder,.mat-date-range-input-hide-placeholders .mat-date-range-input-inner:-ms-input-placeholder{opacity:0}}._mat-animation-noopable .mat-date-range-input-inner::placeholder{transition:none}._mat-animation-noopable .mat-date-range-input-inner::-moz-placeholder{transition:none}._mat-animation-noopable .mat-date-range-input-inner::-webkit-input-placeholder{transition:none}._mat-animation-noopable .mat-date-range-input-inner:-ms-input-placeholder{transition:none}.mat-date-range-input-mirror{-webkit-user-select:none;user-select:none;visibility:hidden;white-space:nowrap;display:inline-block;min-width:2px}.mat-mdc-form-field-type-mat-date-range-input .mat-mdc-form-field-infix{width:200px}"] }]
|
|
4029
|
+
}], ctorParameters: () => [], propDecorators: { rangePicker: [{
|
|
4030
|
+
type: Input
|
|
4031
|
+
}], required: [{
|
|
4032
|
+
type: Input,
|
|
4033
|
+
args: [{ transform: booleanAttribute }]
|
|
4034
|
+
}], dateFilter: [{
|
|
4035
|
+
type: Input
|
|
4036
|
+
}], min: [{
|
|
4037
|
+
type: Input
|
|
4038
|
+
}], max: [{
|
|
4039
|
+
type: Input
|
|
4040
|
+
}], disabled: [{
|
|
4041
|
+
type: Input,
|
|
4042
|
+
args: [{ transform: booleanAttribute }]
|
|
4043
|
+
}], separator: [{
|
|
4044
|
+
type: Input
|
|
4045
|
+
}], comparisonStart: [{
|
|
4046
|
+
type: Input
|
|
4047
|
+
}], comparisonEnd: [{
|
|
4048
|
+
type: Input
|
|
4049
|
+
}] } });
|
|
4050
|
+
|
|
4051
|
+
// This file contains the `_computeAriaAccessibleName` function, which computes what the *expected*
|
|
4052
|
+
// ARIA accessible name would be for a given element. Implements a subset of ARIA specification
|
|
4053
|
+
// [Accessible Name and Description Computation 1.2](https://www.w3.org/TR/accname-1.2/).
|
|
4054
|
+
//
|
|
4055
|
+
// Specification accname-1.2 can be summarized by returning the result of the first method
|
|
4056
|
+
// available.
|
|
4057
|
+
//
|
|
4058
|
+
// 1. `aria-labelledby` attribute
|
|
4059
|
+
// ```
|
|
4060
|
+
// <!-- example using aria-labelledby-->
|
|
4061
|
+
// <label id='label-id'>Start Date</label>
|
|
4062
|
+
// <input aria-labelledby='label-id'/>
|
|
4063
|
+
// ```
|
|
4064
|
+
// 2. `aria-label` attribute (e.g. `<input aria-label="Departure"/>`)
|
|
4065
|
+
// 3. Label with `for`/`id`
|
|
4066
|
+
// ```
|
|
4067
|
+
// <!-- example using for/id -->
|
|
4068
|
+
// <label for="current-node">Label</label>
|
|
4069
|
+
// <input id="current-node"/>
|
|
4070
|
+
// ```
|
|
4071
|
+
// 4. `placeholder` attribute (e.g. `<input placeholder="06/03/1990"/>`)
|
|
4072
|
+
// 5. `title` attribute (e.g. `<input title="Check-In"/>`)
|
|
4073
|
+
// 6. text content
|
|
4074
|
+
// ```
|
|
4075
|
+
// <!-- example using text content -->
|
|
4076
|
+
// <label for="current-node"><span>Departure</span> Date</label>
|
|
4077
|
+
// <input id="current-node"/>
|
|
4078
|
+
// ```
|
|
4079
|
+
/**
|
|
4080
|
+
* Computes the *expected* ARIA accessible name for argument element based on [accname-1.2
|
|
4081
|
+
* specification](https://www.w3.org/TR/accname-1.2/). Implements a subset of accname-1.2,
|
|
4082
|
+
* and should only be used for the Datepicker's specific use case.
|
|
4083
|
+
*
|
|
4084
|
+
* Intended use:
|
|
4085
|
+
* This is not a general use implementation. Only implements the parts of accname-1.2 that are
|
|
4086
|
+
* required for the Datepicker's specific use case. This function is not intended for any other
|
|
4087
|
+
* use.
|
|
4088
|
+
*
|
|
4089
|
+
* Limitations:
|
|
4090
|
+
* - Only covers the needs of `matStartDate` and `matEndDate`. Does not support other use cases.
|
|
4091
|
+
* - See NOTES's in implementation for specific details on what parts of the accname-1.2
|
|
4092
|
+
* specification are not implemented.
|
|
4093
|
+
*
|
|
4094
|
+
* @param element {HTMLInputElement} native <input/> element of `matStartDate` or
|
|
4095
|
+
* `matEndDate` component. Corresponds to the 'Root Element' from accname-1.2
|
|
4096
|
+
*
|
|
4097
|
+
* @return expected ARIA accessible name of argument <input/>
|
|
4098
|
+
*/
|
|
4099
|
+
function _computeAriaAccessibleName(element) {
|
|
4100
|
+
return _computeAriaAccessibleNameInternal(element, true);
|
|
4101
|
+
}
|
|
4102
|
+
/**
|
|
4103
|
+
* Determine if argument node is an Element based on `nodeType` property. This function is safe to
|
|
4104
|
+
* use with server-side rendering.
|
|
4105
|
+
*/
|
|
4106
|
+
function ssrSafeIsElement(node) {
|
|
4107
|
+
return node.nodeType === Node.ELEMENT_NODE;
|
|
4108
|
+
}
|
|
4109
|
+
/**
|
|
4110
|
+
* Determine if argument node is an HTMLInputElement based on `nodeName` property. This funciton is
|
|
4111
|
+
* safe to use with server-side rendering.
|
|
4112
|
+
*/
|
|
4113
|
+
function ssrSafeIsHTMLInputElement(node) {
|
|
4114
|
+
return node.nodeName === 'INPUT';
|
|
4115
|
+
}
|
|
4116
|
+
/**
|
|
4117
|
+
* Determine if argument node is an HTMLTextAreaElement based on `nodeName` property. This
|
|
4118
|
+
* funciton is safe to use with server-side rendering.
|
|
4119
|
+
*/
|
|
4120
|
+
function ssrSafeIsHTMLTextAreaElement(node) {
|
|
4121
|
+
return node.nodeName === 'TEXTAREA';
|
|
4122
|
+
}
|
|
4123
|
+
/**
|
|
4124
|
+
* Calculate the expected ARIA accessible name for given DOM Node. Given DOM Node may be either the
|
|
4125
|
+
* "Root node" passed to `_computeAriaAccessibleName` or "Current node" as result of recursion.
|
|
4126
|
+
*
|
|
4127
|
+
* @return the accessible name of argument DOM Node
|
|
4128
|
+
*
|
|
4129
|
+
* @param currentNode node to determine accessible name of
|
|
4130
|
+
* @param isDirectlyReferenced true if `currentNode` is the root node to calculate ARIA accessible
|
|
4131
|
+
* name of. False if it is a result of recursion.
|
|
4132
|
+
*/
|
|
4133
|
+
function _computeAriaAccessibleNameInternal(currentNode, isDirectlyReferenced) {
|
|
4134
|
+
// NOTE: this differs from accname-1.2 specification.
|
|
4135
|
+
// - Does not implement Step 1. of accname-1.2: '''If `currentNode`'s role prohibits naming,
|
|
4136
|
+
// return the empty string ("")'''.
|
|
4137
|
+
// - Does not implement Step 2.A. of accname-1.2: '''if current node is hidden and not directly
|
|
4138
|
+
// referenced by aria-labelledby... return the empty string.'''
|
|
4139
|
+
// acc-name-1.2 Step 2.B.: aria-labelledby
|
|
4140
|
+
if (ssrSafeIsElement(currentNode) && isDirectlyReferenced) {
|
|
4141
|
+
const labelledbyIds = currentNode.getAttribute?.('aria-labelledby')?.split(/\s+/g) || [];
|
|
4142
|
+
const validIdRefs = labelledbyIds.reduce((validIds, id) => {
|
|
4143
|
+
const elem = document.getElementById(id);
|
|
4144
|
+
if (elem) {
|
|
4145
|
+
validIds.push(elem);
|
|
4146
|
+
}
|
|
4147
|
+
return validIds;
|
|
4148
|
+
}, []);
|
|
4149
|
+
if (validIdRefs.length) {
|
|
4150
|
+
return validIdRefs
|
|
4151
|
+
.map(idRef => {
|
|
4152
|
+
return _computeAriaAccessibleNameInternal(idRef, false);
|
|
4153
|
+
})
|
|
4154
|
+
.join(' ');
|
|
4278
4155
|
}
|
|
4279
4156
|
}
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
: this._groupDisabled;
|
|
4286
|
-
}
|
|
4287
|
-
set disabled(value) {
|
|
4288
|
-
if (value !== this._groupDisabled) {
|
|
4289
|
-
this._groupDisabled = value;
|
|
4290
|
-
this.stateChanges.next(undefined);
|
|
4157
|
+
// acc-name-1.2 Step 2.C.: aria-label
|
|
4158
|
+
if (ssrSafeIsElement(currentNode)) {
|
|
4159
|
+
const ariaLabel = currentNode.getAttribute('aria-label')?.trim();
|
|
4160
|
+
if (ariaLabel) {
|
|
4161
|
+
return ariaLabel;
|
|
4291
4162
|
}
|
|
4292
4163
|
}
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4164
|
+
// acc-name-1.2 Step 2.D. attribute or element that defines a text alternative
|
|
4165
|
+
//
|
|
4166
|
+
// NOTE: this differs from accname-1.2 specification.
|
|
4167
|
+
// Only implements Step 2.D. for `<label>`,`<input/>`, and `<textarea/>` element. Does not
|
|
4168
|
+
// implement other elements that have an attribute or element that defines a text alternative.
|
|
4169
|
+
if (ssrSafeIsHTMLInputElement(currentNode) || ssrSafeIsHTMLTextAreaElement(currentNode)) {
|
|
4170
|
+
// use label with a `for` attribute referencing the current node
|
|
4171
|
+
if (currentNode.labels?.length) {
|
|
4172
|
+
return Array.from(currentNode.labels)
|
|
4173
|
+
.map(x => _computeAriaAccessibleNameInternal(x, false))
|
|
4174
|
+
.join(' ');
|
|
4298
4175
|
}
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
const startEmpty = this._startInput ? this._startInput.isEmpty() : false;
|
|
4304
|
-
const endEmpty = this._endInput ? this._endInput.isEmpty() : false;
|
|
4305
|
-
return startEmpty && endEmpty;
|
|
4306
|
-
}
|
|
4307
|
-
/** Value for the `aria-describedby` attribute of the inputs. */
|
|
4308
|
-
_ariaDescribedBy = null;
|
|
4309
|
-
/** Date selection model currently registered with the input. */
|
|
4310
|
-
_model;
|
|
4311
|
-
/** Separator text to be shown between the inputs. */
|
|
4312
|
-
separator = '–';
|
|
4313
|
-
/** Start of the comparison range that should be shown in the calendar. */
|
|
4314
|
-
comparisonStart = null;
|
|
4315
|
-
/** End of the comparison range that should be shown in the calendar. */
|
|
4316
|
-
comparisonEnd = null;
|
|
4317
|
-
_startInput;
|
|
4318
|
-
_endInput;
|
|
4319
|
-
/**
|
|
4320
|
-
* Implemented as a part of `MatFormFieldControl`.
|
|
4321
|
-
* TODO(crisbeto): change type to `AbstractControlDirective` after #18206 lands.
|
|
4322
|
-
* @docs-private
|
|
4323
|
-
*/
|
|
4324
|
-
ngControl;
|
|
4325
|
-
/** Emits when the input's state has changed. */
|
|
4326
|
-
stateChanges = new Subject();
|
|
4327
|
-
/**
|
|
4328
|
-
* Disable the automatic labeling to avoid issues like #27241.
|
|
4329
|
-
* @docs-private
|
|
4330
|
-
*/
|
|
4331
|
-
disableAutomaticLabeling = true;
|
|
4332
|
-
constructor() {
|
|
4333
|
-
if (!this._dateAdapter && (typeof ngDevMode === 'undefined' || ngDevMode)) {
|
|
4334
|
-
throw createMissingDateImplError('DateAdapter');
|
|
4176
|
+
// use placeholder if available
|
|
4177
|
+
const placeholder = currentNode.getAttribute('placeholder')?.trim();
|
|
4178
|
+
if (placeholder) {
|
|
4179
|
+
return placeholder;
|
|
4335
4180
|
}
|
|
4336
|
-
//
|
|
4337
|
-
|
|
4338
|
-
if (
|
|
4339
|
-
|
|
4181
|
+
// use title if available
|
|
4182
|
+
const title = currentNode.getAttribute('title')?.trim();
|
|
4183
|
+
if (title) {
|
|
4184
|
+
return title;
|
|
4340
4185
|
}
|
|
4341
|
-
// TODO(crisbeto): remove `as any` after #18206 lands.
|
|
4342
|
-
this.ngControl = inject(ControlContainer, { optional: true, self: true });
|
|
4343
4186
|
}
|
|
4187
|
+
// NOTE: this differs from accname-1.2 specification.
|
|
4188
|
+
// - does not implement acc-name-1.2 Step 2.E.: '''if the current node is a control embedded
|
|
4189
|
+
// within the label... then include the embedded control as part of the text alternative in
|
|
4190
|
+
// the following manner...'''. Step 2E applies to embedded controls such as textbox, listbox,
|
|
4191
|
+
// range, etc.
|
|
4192
|
+
// - does not implement acc-name-1.2 step 2.F.: check that '''role allows name from content''',
|
|
4193
|
+
// which applies to `currentNode` and its children.
|
|
4194
|
+
// - does not implement acc-name-1.2 Step 2.F.ii.: '''Check for CSS generated textual content'''
|
|
4195
|
+
// (e.g. :before and :after).
|
|
4196
|
+
// - does not implement acc-name-1.2 Step 2.I.: '''if the current node has a Tooltip attribute,
|
|
4197
|
+
// return its value'''
|
|
4198
|
+
// Return text content with whitespace collapsed into a single space character. Accomplish
|
|
4199
|
+
// acc-name-1.2 steps 2F, 2G, and 2H.
|
|
4200
|
+
return (currentNode.textContent || '').replace(/\s+/g, ' ').trim();
|
|
4201
|
+
}
|
|
4202
|
+
|
|
4203
|
+
/**
|
|
4204
|
+
* Base class for the individual inputs that can be projected inside a `mat-date-range-input`.
|
|
4205
|
+
*/
|
|
4206
|
+
class MatDateRangeInputPartBase extends MatDatepickerInputBase {
|
|
4207
|
+
_rangeInput = inject(MatDateRangeInput);
|
|
4208
|
+
_elementRef = inject(ElementRef);
|
|
4209
|
+
_defaultErrorStateMatcher = inject(ErrorStateMatcher);
|
|
4210
|
+
_injector = inject(Injector);
|
|
4211
|
+
_parentForm = inject(NgForm, { optional: true });
|
|
4212
|
+
_parentFormGroup = inject(FormGroupDirective, { optional: true });
|
|
4344
4213
|
/**
|
|
4345
|
-
*
|
|
4214
|
+
* Form control bound to this input part.
|
|
4346
4215
|
* @docs-private
|
|
4347
4216
|
*/
|
|
4348
|
-
|
|
4349
|
-
|
|
4217
|
+
ngControl;
|
|
4218
|
+
_dir = inject(Directionality, { optional: true });
|
|
4219
|
+
_errorStateTracker;
|
|
4220
|
+
/** Object used to control when error messages are shown. */
|
|
4221
|
+
get errorStateMatcher() {
|
|
4222
|
+
return this._errorStateTracker.matcher;
|
|
4350
4223
|
}
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
|
|
4362
|
-
|
|
4224
|
+
set errorStateMatcher(value) {
|
|
4225
|
+
this._errorStateTracker.matcher = value;
|
|
4226
|
+
}
|
|
4227
|
+
/** Whether the input is in an error state. */
|
|
4228
|
+
get errorState() {
|
|
4229
|
+
return this._errorStateTracker.errorState;
|
|
4230
|
+
}
|
|
4231
|
+
set errorState(value) {
|
|
4232
|
+
this._errorStateTracker.errorState = value;
|
|
4233
|
+
}
|
|
4234
|
+
constructor() {
|
|
4235
|
+
super();
|
|
4236
|
+
this._errorStateTracker = new _ErrorStateTracker(this._defaultErrorStateMatcher, null, this._parentFormGroup, this._parentForm, this.stateChanges);
|
|
4237
|
+
}
|
|
4238
|
+
ngOnInit() {
|
|
4239
|
+
// We need the date input to provide itself as a `ControlValueAccessor` and a `Validator`, while
|
|
4240
|
+
// injecting its `NgControl` so that the error state is handled correctly. This introduces a
|
|
4241
|
+
// circular dependency, because both `ControlValueAccessor` and `Validator` depend on the input
|
|
4242
|
+
// itself. Usually we can work around it for the CVA, but there's no API to do it for the
|
|
4243
|
+
// validator. We work around it here by injecting the `NgControl` in `ngOnInit`, after
|
|
4244
|
+
// everything has been resolved.
|
|
4245
|
+
const ngControl = this._injector.get(NgControl, null, { optional: true, self: true });
|
|
4246
|
+
if (ngControl) {
|
|
4247
|
+
this.ngControl = ngControl;
|
|
4248
|
+
this._errorStateTracker.ngControl = ngControl;
|
|
4363
4249
|
}
|
|
4364
4250
|
}
|
|
4365
4251
|
ngAfterContentInit() {
|
|
4366
|
-
|
|
4367
|
-
if (!this._startInput) {
|
|
4368
|
-
throw Error('mat-date-range-input must contain a matStartDate input');
|
|
4369
|
-
}
|
|
4370
|
-
if (!this._endInput) {
|
|
4371
|
-
throw Error('mat-date-range-input must contain a matEndDate input');
|
|
4372
|
-
}
|
|
4373
|
-
}
|
|
4374
|
-
if (this._model) {
|
|
4375
|
-
this._registerModel(this._model);
|
|
4376
|
-
}
|
|
4377
|
-
// We don't need to unsubscribe from this, because we
|
|
4378
|
-
// know that the input streams will be completed on destroy.
|
|
4379
|
-
merge(this._startInput.stateChanges, this._endInput.stateChanges).subscribe(() => {
|
|
4380
|
-
this.stateChanges.next(undefined);
|
|
4381
|
-
});
|
|
4252
|
+
this._register();
|
|
4382
4253
|
}
|
|
4383
|
-
|
|
4384
|
-
if (
|
|
4385
|
-
this
|
|
4254
|
+
ngDoCheck() {
|
|
4255
|
+
if (this.ngControl) {
|
|
4256
|
+
// We need to re-evaluate this on every change detection cycle, because there are some
|
|
4257
|
+
// error triggers that we can't subscribe to (e.g. parent form submissions). This means
|
|
4258
|
+
// that whatever logic is in here has to be super lean or we risk destroying the performance.
|
|
4259
|
+
this.updateErrorState();
|
|
4386
4260
|
}
|
|
4387
4261
|
}
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
this.
|
|
4391
|
-
this.stateChanges.complete();
|
|
4262
|
+
/** Gets whether the input is empty. */
|
|
4263
|
+
isEmpty() {
|
|
4264
|
+
return this._elementRef.nativeElement.value.length === 0;
|
|
4392
4265
|
}
|
|
4393
|
-
/** Gets the
|
|
4394
|
-
|
|
4395
|
-
return this.
|
|
4266
|
+
/** Gets the placeholder of the input. */
|
|
4267
|
+
_getPlaceholder() {
|
|
4268
|
+
return this._elementRef.nativeElement.placeholder;
|
|
4396
4269
|
}
|
|
4397
|
-
/**
|
|
4398
|
-
|
|
4399
|
-
|
|
4270
|
+
/** Focuses the input. */
|
|
4271
|
+
focus() {
|
|
4272
|
+
this._elementRef.nativeElement.focus();
|
|
4400
4273
|
}
|
|
4401
|
-
/** Gets the
|
|
4402
|
-
|
|
4403
|
-
|
|
4274
|
+
/** Gets the value that should be used when mirroring the input's size. */
|
|
4275
|
+
getMirrorValue() {
|
|
4276
|
+
const element = this._elementRef.nativeElement;
|
|
4277
|
+
const value = element.value;
|
|
4278
|
+
return value.length > 0 ? value : element.placeholder;
|
|
4404
4279
|
}
|
|
4405
|
-
/**
|
|
4406
|
-
|
|
4407
|
-
|
|
4280
|
+
/** Refreshes the error state of the input. */
|
|
4281
|
+
updateErrorState() {
|
|
4282
|
+
this._errorStateTracker.updateErrorState();
|
|
4408
4283
|
}
|
|
4409
|
-
/**
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4284
|
+
/** Handles `input` events on the input element. */
|
|
4285
|
+
_onInput(value) {
|
|
4286
|
+
super._onInput(value);
|
|
4287
|
+
this._rangeInput._handleChildValueChange();
|
|
4288
|
+
}
|
|
4289
|
+
/** Opens the datepicker associated with the input. */
|
|
4290
|
+
_openPopup() {
|
|
4291
|
+
this._rangeInput._openDatepicker();
|
|
4292
|
+
}
|
|
4293
|
+
/** Gets the minimum date from the range input. */
|
|
4294
|
+
_getMinDate() {
|
|
4295
|
+
return this._rangeInput.min;
|
|
4296
|
+
}
|
|
4297
|
+
/** Gets the maximum date from the range input. */
|
|
4298
|
+
_getMaxDate() {
|
|
4299
|
+
return this._rangeInput.max;
|
|
4300
|
+
}
|
|
4301
|
+
/** Gets the date filter function from the range input. */
|
|
4302
|
+
_getDateFilter() {
|
|
4303
|
+
return this._rangeInput.dateFilter;
|
|
4304
|
+
}
|
|
4305
|
+
_parentDisabled() {
|
|
4306
|
+
return this._rangeInput._groupDisabled;
|
|
4307
|
+
}
|
|
4308
|
+
_shouldHandleChangeEvent({ source }) {
|
|
4309
|
+
return source !== this._rangeInput._startInput && source !== this._rangeInput._endInput;
|
|
4310
|
+
}
|
|
4311
|
+
_assignValueProgrammatically(value) {
|
|
4312
|
+
super._assignValueProgrammatically(value);
|
|
4313
|
+
const opposite = (this === this._rangeInput._startInput
|
|
4314
|
+
? this._rangeInput._endInput
|
|
4315
|
+
: this._rangeInput._startInput);
|
|
4316
|
+
opposite?._validatorOnChange();
|
|
4413
4317
|
}
|
|
4414
|
-
/**
|
|
4415
|
-
|
|
4416
|
-
return this.
|
|
4318
|
+
/** return the ARIA accessible name of the input element */
|
|
4319
|
+
_getAccessibleName() {
|
|
4320
|
+
return _computeAriaAccessibleName(this._elementRef.nativeElement);
|
|
4417
4321
|
}
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4322
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatDateRangeInputPartBase, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
4323
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.0", type: MatDateRangeInputPartBase, isStandalone: true, inputs: { errorStateMatcher: "errorStateMatcher" }, usesInheritance: true, ngImport: i0 });
|
|
4324
|
+
}
|
|
4325
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatDateRangeInputPartBase, decorators: [{
|
|
4326
|
+
type: Directive
|
|
4327
|
+
}], ctorParameters: () => [], propDecorators: { errorStateMatcher: [{
|
|
4328
|
+
type: Input
|
|
4329
|
+
}] } });
|
|
4330
|
+
/** Input for entering the start date in a `mat-date-range-input`. */
|
|
4331
|
+
class MatStartDate extends MatDateRangeInputPartBase {
|
|
4332
|
+
/** Validator that checks that the start date isn't after the end date. */
|
|
4333
|
+
_startValidator = (control) => {
|
|
4334
|
+
const start = this._dateAdapter.getValidDateOrNull(this._dateAdapter.deserialize(control.value));
|
|
4335
|
+
const end = this._model ? this._model.selection.end : null;
|
|
4336
|
+
return !start || !end || this._dateAdapter.compareDate(start, end) <= 0
|
|
4337
|
+
? null
|
|
4338
|
+
: { 'matStartDateInvalid': { 'end': end, 'actual': start } };
|
|
4339
|
+
};
|
|
4340
|
+
_validator = Validators.compose([...super._getValidators(), this._startValidator]);
|
|
4341
|
+
_register() {
|
|
4342
|
+
this._rangeInput._startInput = this;
|
|
4422
4343
|
}
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4344
|
+
_getValueFromModel(modelValue) {
|
|
4345
|
+
return modelValue.start;
|
|
4346
|
+
}
|
|
4347
|
+
_shouldHandleChangeEvent(change) {
|
|
4348
|
+
if (!super._shouldHandleChangeEvent(change)) {
|
|
4349
|
+
return false;
|
|
4350
|
+
}
|
|
4351
|
+
else {
|
|
4352
|
+
return !change.oldValue?.start
|
|
4353
|
+
? !!change.selection.start
|
|
4354
|
+
: !change.selection.start ||
|
|
4355
|
+
!!this._dateAdapter.compareDate(change.oldValue.start, change.selection.start);
|
|
4427
4356
|
}
|
|
4428
4357
|
}
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4358
|
+
_assignValueToModel(value) {
|
|
4359
|
+
if (this._model) {
|
|
4360
|
+
const range = new DateRange(value, this._model.selection.end);
|
|
4361
|
+
this._model.updateSelection(range, this);
|
|
4362
|
+
}
|
|
4434
4363
|
}
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4364
|
+
_formatValue(value) {
|
|
4365
|
+
super._formatValue(value);
|
|
4366
|
+
// Any time the input value is reformatted we need to tell the parent.
|
|
4367
|
+
this._rangeInput._handleChildValueChange();
|
|
4439
4368
|
}
|
|
4440
|
-
|
|
4441
|
-
|
|
4369
|
+
_onKeydown(event) {
|
|
4370
|
+
const endInput = this._rangeInput._endInput;
|
|
4371
|
+
const element = this._elementRef.nativeElement;
|
|
4372
|
+
const isLtr = this._dir?.value !== 'rtl';
|
|
4373
|
+
// If the user hits RIGHT (LTR) when at the end of the input (and no
|
|
4374
|
+
// selection), move the cursor to the start of the end input.
|
|
4375
|
+
if (((event.keyCode === RIGHT_ARROW && isLtr) || (event.keyCode === LEFT_ARROW && !isLtr)) &&
|
|
4376
|
+
element.selectionStart === element.value.length &&
|
|
4377
|
+
element.selectionEnd === element.value.length) {
|
|
4378
|
+
event.preventDefault();
|
|
4379
|
+
endInput._elementRef.nativeElement.setSelectionRange(0, 0);
|
|
4380
|
+
endInput.focus();
|
|
4381
|
+
}
|
|
4382
|
+
else {
|
|
4383
|
+
super._onKeydown(event);
|
|
4384
|
+
}
|
|
4442
4385
|
}
|
|
4443
|
-
|
|
4444
|
-
|
|
4386
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatStartDate, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
4387
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.0", type: MatStartDate, isStandalone: true, selector: "input[matStartDate]", outputs: { dateChange: "dateChange", dateInput: "dateInput" }, host: { attributes: { "type": "text" }, listeners: { "input": "_onInput($event.target.value)", "change": "_onChange()", "keydown": "_onKeydown($event)", "blur": "_onBlur()" }, properties: { "disabled": "disabled", "attr.aria-haspopup": "_rangeInput.rangePicker ? \"dialog\" : null", "attr.aria-owns": "_rangeInput._ariaOwns\n ? _rangeInput._ariaOwns()\n : (_rangeInput.rangePicker?.opened && _rangeInput.rangePicker.id) || null", "attr.min": "_getMinDate() ? _dateAdapter.toIso8601(_getMinDate()) : null", "attr.max": "_getMaxDate() ? _dateAdapter.toIso8601(_getMaxDate()) : null" }, classAttribute: "mat-start-date mat-date-range-input-inner" }, providers: [
|
|
4388
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: MatStartDate, multi: true },
|
|
4389
|
+
{ provide: NG_VALIDATORS, useExisting: MatStartDate, multi: true },
|
|
4390
|
+
], usesInheritance: true, ngImport: i0 });
|
|
4391
|
+
}
|
|
4392
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatStartDate, decorators: [{
|
|
4393
|
+
type: Directive,
|
|
4394
|
+
args: [{
|
|
4395
|
+
selector: 'input[matStartDate]',
|
|
4396
|
+
host: {
|
|
4397
|
+
'class': 'mat-start-date mat-date-range-input-inner',
|
|
4398
|
+
'[disabled]': 'disabled',
|
|
4399
|
+
'(input)': '_onInput($event.target.value)',
|
|
4400
|
+
'(change)': '_onChange()',
|
|
4401
|
+
'(keydown)': '_onKeydown($event)',
|
|
4402
|
+
'[attr.aria-haspopup]': '_rangeInput.rangePicker ? "dialog" : null',
|
|
4403
|
+
'[attr.aria-owns]': `_rangeInput._ariaOwns
|
|
4404
|
+
? _rangeInput._ariaOwns()
|
|
4405
|
+
: (_rangeInput.rangePicker?.opened && _rangeInput.rangePicker.id) || null`,
|
|
4406
|
+
'[attr.min]': '_getMinDate() ? _dateAdapter.toIso8601(_getMinDate()) : null',
|
|
4407
|
+
'[attr.max]': '_getMaxDate() ? _dateAdapter.toIso8601(_getMaxDate()) : null',
|
|
4408
|
+
'(blur)': '_onBlur()',
|
|
4409
|
+
'type': 'text',
|
|
4410
|
+
},
|
|
4411
|
+
providers: [
|
|
4412
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: MatStartDate, multi: true },
|
|
4413
|
+
{ provide: NG_VALIDATORS, useExisting: MatStartDate, multi: true },
|
|
4414
|
+
],
|
|
4415
|
+
// These need to be specified explicitly, because some tooling doesn't
|
|
4416
|
+
// seem to pick them up from the base class. See #20932.
|
|
4417
|
+
outputs: ['dateChange', 'dateInput'],
|
|
4418
|
+
}]
|
|
4419
|
+
}] });
|
|
4420
|
+
/** Input for entering the end date in a `mat-date-range-input`. */
|
|
4421
|
+
class MatEndDate extends MatDateRangeInputPartBase {
|
|
4422
|
+
/** Validator that checks that the end date isn't before the start date. */
|
|
4423
|
+
_endValidator = (control) => {
|
|
4424
|
+
const end = this._dateAdapter.getValidDateOrNull(this._dateAdapter.deserialize(control.value));
|
|
4425
|
+
const start = this._model ? this._model.selection.start : null;
|
|
4426
|
+
return !end || !start || this._dateAdapter.compareDate(end, start) >= 0
|
|
4427
|
+
? null
|
|
4428
|
+
: { 'matEndDateInvalid': { 'start': start, 'actual': end } };
|
|
4429
|
+
};
|
|
4430
|
+
_register() {
|
|
4431
|
+
this._rangeInput._endInput = this;
|
|
4445
4432
|
}
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
this.stateChanges.next();
|
|
4433
|
+
_validator = Validators.compose([...super._getValidators(), this._endValidator]);
|
|
4434
|
+
_getValueFromModel(modelValue) {
|
|
4435
|
+
return modelValue.end;
|
|
4450
4436
|
}
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
this._startInput._validatorOnChange();
|
|
4437
|
+
_shouldHandleChangeEvent(change) {
|
|
4438
|
+
if (!super._shouldHandleChangeEvent(change)) {
|
|
4439
|
+
return false;
|
|
4455
4440
|
}
|
|
4456
|
-
|
|
4457
|
-
|
|
4441
|
+
else {
|
|
4442
|
+
return !change.oldValue?.end
|
|
4443
|
+
? !!change.selection.end
|
|
4444
|
+
: !change.selection.end ||
|
|
4445
|
+
!!this._dateAdapter.compareDate(change.oldValue.end, change.selection.end);
|
|
4458
4446
|
}
|
|
4459
4447
|
}
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
this.
|
|
4448
|
+
_assignValueToModel(value) {
|
|
4449
|
+
if (this._model) {
|
|
4450
|
+
const range = new DateRange(this._model.selection.start, value);
|
|
4451
|
+
this._model.updateSelection(range, this);
|
|
4464
4452
|
}
|
|
4465
|
-
|
|
4466
|
-
|
|
4453
|
+
}
|
|
4454
|
+
_moveCaretToEndOfStartInput() {
|
|
4455
|
+
const startInput = this._rangeInput._startInput._elementRef.nativeElement;
|
|
4456
|
+
const value = startInput.value;
|
|
4457
|
+
if (value.length > 0) {
|
|
4458
|
+
startInput.setSelectionRange(value.length, value.length);
|
|
4467
4459
|
}
|
|
4460
|
+
startInput.focus();
|
|
4468
4461
|
}
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4462
|
+
_onKeydown(event) {
|
|
4463
|
+
const element = this._elementRef.nativeElement;
|
|
4464
|
+
const isLtr = this._dir?.value !== 'rtl';
|
|
4465
|
+
// If the user is pressing backspace on an empty end input, move focus back to the start.
|
|
4466
|
+
if (event.keyCode === BACKSPACE && !element.value) {
|
|
4467
|
+
this._moveCaretToEndOfStartInput();
|
|
4468
|
+
}
|
|
4469
|
+
// If the user hits LEFT (LTR) when at the start of the input (and no
|
|
4470
|
+
// selection), move the cursor to the end of the start input.
|
|
4471
|
+
else if (((event.keyCode === LEFT_ARROW && isLtr) || (event.keyCode === RIGHT_ARROW && !isLtr)) &&
|
|
4472
|
+
element.selectionStart === 0 &&
|
|
4473
|
+
element.selectionEnd === 0) {
|
|
4474
|
+
event.preventDefault();
|
|
4475
|
+
this._moveCaretToEndOfStartInput();
|
|
4476
|
+
}
|
|
4477
|
+
else {
|
|
4478
|
+
super._onKeydown(event);
|
|
4479
|
+
}
|
|
4472
4480
|
}
|
|
4473
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type:
|
|
4474
|
-
static
|
|
4475
|
-
{ provide:
|
|
4476
|
-
{ provide:
|
|
4477
|
-
],
|
|
4481
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatEndDate, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
4482
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.0", type: MatEndDate, isStandalone: true, selector: "input[matEndDate]", outputs: { dateChange: "dateChange", dateInput: "dateInput" }, host: { attributes: { "type": "text" }, listeners: { "input": "_onInput($event.target.value)", "change": "_onChange()", "keydown": "_onKeydown($event)", "blur": "_onBlur()" }, properties: { "disabled": "disabled", "attr.aria-haspopup": "_rangeInput.rangePicker ? \"dialog\" : null", "attr.aria-owns": "_rangeInput._ariaOwns\n ? _rangeInput._ariaOwns()\n : (_rangeInput.rangePicker?.opened && _rangeInput.rangePicker.id) || null", "attr.min": "_getMinDate() ? _dateAdapter.toIso8601(_getMinDate()) : null", "attr.max": "_getMaxDate() ? _dateAdapter.toIso8601(_getMaxDate()) : null" }, classAttribute: "mat-end-date mat-date-range-input-inner" }, providers: [
|
|
4483
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: MatEndDate, multi: true },
|
|
4484
|
+
{ provide: NG_VALIDATORS, useExisting: MatEndDate, multi: true },
|
|
4485
|
+
], usesInheritance: true, ngImport: i0 });
|
|
4478
4486
|
}
|
|
4479
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type:
|
|
4480
|
-
type:
|
|
4481
|
-
args: [{
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
'
|
|
4485
|
-
'[
|
|
4486
|
-
'
|
|
4487
|
-
'
|
|
4488
|
-
'
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
}], disabled: [{
|
|
4508
|
-
type: Input,
|
|
4509
|
-
args: [{ transform: booleanAttribute }]
|
|
4510
|
-
}], separator: [{
|
|
4511
|
-
type: Input
|
|
4512
|
-
}], comparisonStart: [{
|
|
4513
|
-
type: Input
|
|
4514
|
-
}], comparisonEnd: [{
|
|
4515
|
-
type: Input
|
|
4516
|
-
}], _startInput: [{
|
|
4517
|
-
type: ContentChild,
|
|
4518
|
-
args: [MatStartDate]
|
|
4519
|
-
}], _endInput: [{
|
|
4520
|
-
type: ContentChild,
|
|
4521
|
-
args: [MatEndDate]
|
|
4522
|
-
}] } });
|
|
4487
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.0", ngImport: i0, type: MatEndDate, decorators: [{
|
|
4488
|
+
type: Directive,
|
|
4489
|
+
args: [{
|
|
4490
|
+
selector: 'input[matEndDate]',
|
|
4491
|
+
host: {
|
|
4492
|
+
'class': 'mat-end-date mat-date-range-input-inner',
|
|
4493
|
+
'[disabled]': 'disabled',
|
|
4494
|
+
'(input)': '_onInput($event.target.value)',
|
|
4495
|
+
'(change)': '_onChange()',
|
|
4496
|
+
'(keydown)': '_onKeydown($event)',
|
|
4497
|
+
'[attr.aria-haspopup]': '_rangeInput.rangePicker ? "dialog" : null',
|
|
4498
|
+
'[attr.aria-owns]': `_rangeInput._ariaOwns
|
|
4499
|
+
? _rangeInput._ariaOwns()
|
|
4500
|
+
: (_rangeInput.rangePicker?.opened && _rangeInput.rangePicker.id) || null`,
|
|
4501
|
+
'[attr.min]': '_getMinDate() ? _dateAdapter.toIso8601(_getMinDate()) : null',
|
|
4502
|
+
'[attr.max]': '_getMaxDate() ? _dateAdapter.toIso8601(_getMaxDate()) : null',
|
|
4503
|
+
'(blur)': '_onBlur()',
|
|
4504
|
+
'type': 'text',
|
|
4505
|
+
},
|
|
4506
|
+
providers: [
|
|
4507
|
+
{ provide: NG_VALUE_ACCESSOR, useExisting: MatEndDate, multi: true },
|
|
4508
|
+
{ provide: NG_VALIDATORS, useExisting: MatEndDate, multi: true },
|
|
4509
|
+
],
|
|
4510
|
+
// These need to be specified explicitly, because some tooling doesn't
|
|
4511
|
+
// seem to pick them up from the base class. See #20932.
|
|
4512
|
+
outputs: ['dateChange', 'dateInput'],
|
|
4513
|
+
}]
|
|
4514
|
+
}] });
|
|
4523
4515
|
|
|
4524
4516
|
// TODO(mmalerba): We use a component instead of a directive here so the user can use implicit
|
|
4525
4517
|
// template reference variables (e.g. #d vs #d="matDateRangePicker"). We can change this to a
|