@blox/material
Version:
Material Components for Angular
732 lines • 103 kB
JavaScript
import { ContentChildren, Directive, ElementRef, forwardRef, HostBinding, HostListener, Input, Optional, Renderer2, Self, Output, EventEmitter, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { NgControl } from '@angular/forms';
import { MDCTextFieldFoundation } from '@material/textfield';
import { MDCLineRippleFoundation } from '@material/line-ripple';
import { MDCTextFieldHelperTextFoundation } from '@material/textfield';
import { MDCTextFieldIconFoundation } from '@material/textfield';
import { MdcFloatingLabelDirective } from '../floating-label/mdc.floating-label.directive';
import { AbstractMdcInput } from '../abstract/abstract.mdc.input';
import { asBoolean, asNumberOrNull } from '../../utils/value.utils';
import { AbstractMdcRipple } from '../ripple/abstract.mdc.ripple';
import { MdcNotchedOutlineDirective } from '../notched-outline/mdc.notched-outline.directive';
import { MdcEventRegistry } from '../../utils/mdc.event.registry';
import { Subject, merge } from 'rxjs';
import { takeUntil, debounceTime } from 'rxjs/operators';
import { HasId } from '../abstract/mixin.mdc.hasid';
import { applyMixins } from '../../utils/mixins';
let nextId = 1;
/**
* Directive for the native input of an `mdcTextField`.
*/
export class MdcTextFieldInputDirective extends AbstractMdcInput {
constructor(_elm, renderer, _cntr) {
super();
this._elm = _elm;
this.renderer = renderer;
this._cntr = _cntr;
/** @internal */
this._cls = true;
/** @internal */
this._labeledBy = null;
/** @internal */
this._controls = null;
/** @internal */
this._describedBy = null;
/** @internal */
this._valueChange = new EventEmitter();
this.onDestroy$ = new Subject();
this._id = null;
this._type = 'text';
this._value = '';
this._disabled = false;
this.cachedId = null;
}
ngOnInit() {
var _a;
// Force setter to be called in case id was not specified.
this.id = this.id;
(_a = this._cntr) === null || _a === void 0 ? void 0 : _a.valueChanges.pipe(takeUntil(this.onDestroy$)).subscribe(() => {
// (using the value of the elemnt, because the value of the control might be of another type,
// e.g. the ngModel for type=number inputs is a number)
this.updateValue(this._elm.nativeElement.value, true);
});
}
ngOnDestroy() {
this.onDestroy$.next();
this.onDestroy$.complete();
}
/**
* Mirrors the <code>id</code> attribute. If no id is assigned, this directive will
* assign a unique id by itself. If an <code>mdcFloatingLabel</code> for this text-field
* is available, the <code>mdcFloatingLabel</code> will automatically be associated
* (either by a `for` attribute on the label, or by an `aria-labelledby` attribute
* on this input element).
*/
get id() {
return this._id;
}
set id(value) {
this._id = value || this._newId();
}
/**
* If set to a value other than false, the text-field will be in disabled state.
*/
get disabled() {
return this._cntr ? !!this._cntr.disabled : this._disabled;
}
set disabled(value) {
this._disabled = asBoolean(value);
}
/** @internal */
get type() {
return this._type;
}
set type(value) {
this._type = value || 'text';
// Angular Input is not automatically set on the native input element:
if (!this._isTextarea()) {
try {
this.renderer.setProperty(this._elm.nativeElement, 'type', this._type);
}
catch (e) {
this.renderer.setAttribute(this._elm.nativeElement, 'type', this._type);
}
}
}
/** @internal */
get value() {
return this._value;
}
/** @internal */
set value(value) {
this.updateValue(value, false);
}
updateValue(value, fromControl) {
const newVal = (value ? `${value}` : '');
if (newVal !== this._value) {
this._value = this._elm.nativeElement.value = newVal;
this._valueChange.emit(this._elm.nativeElement.value);
}
if (!fromControl && this._cntr && newVal !== this._cntr.value) {
this._cntr.control.setValue(newVal); // TODO how to convert to the type of value the controlpects?
}
}
/** @internal */
_onInput() {
if (!this._cntr)
this.updateValue(this._elm.nativeElement.value, false);
}
/** @internal */
get valid() {
return this._cntr ? !!this._cntr.valid : this._elm.nativeElement.validity.valid;
}
/** @internal */
_isBadInput() {
return this._elm.nativeElement.validity.badInput;
}
/** @internal */
_isTextarea() {
return this._elm.nativeElement.nodeName.toLowerCase() === 'textarea';
}
/** @internal */
_newId() {
this.cachedId = this.cachedId || `mdc-input-${nextId++}`;
return this.cachedId;
}
}
MdcTextFieldInputDirective.decorators = [
{ type: Directive, args: [{
selector: 'input[mdcTextFieldInput], textarea[mdcTextFieldInput]',
providers: [{ provide: AbstractMdcInput, useExisting: forwardRef(() => MdcTextFieldInputDirective) }]
},] }
];
MdcTextFieldInputDirective.ctorParameters = () => [
{ type: ElementRef },
{ type: Renderer2 },
{ type: NgControl, decorators: [{ type: Optional }, { type: Self }] }
];
MdcTextFieldInputDirective.propDecorators = {
_cls: [{ type: HostBinding, args: ['class.mdc-text-field__input',] }],
_labeledBy: [{ type: HostBinding, args: ['attr.aria-labelledby',] }],
_controls: [{ type: HostBinding, args: ['attr.aria-controls',] }],
_describedBy: [{ type: HostBinding, args: ['attr.aria-describedby',] }],
_valueChange: [{ type: Output }],
id: [{ type: HostBinding }, { type: Input }],
disabled: [{ type: HostBinding }, { type: Input }],
type: [{ type: Input }],
value: [{ type: Input }],
_onInput: [{ type: HostListener, args: ['input',] }]
};
/**
* Directive for an optional leading or trailing icon on the text-field (see
* `MdcTextFieldDirective`). An icon before the `mdcTextFieldInput` will be styled
* as a leading icon. An icon after the `mdcTextFieldInput` will be styles as a
* trailing icon.
*/
export class MdcTextFieldIconDirective {
constructor(_rndr, _el, _reg) {
this._rndr = _rndr;
this._el = _el;
this._reg = _reg;
/** @internal */
this._cls = true;
/**
* Event emitted for icon interactions (a click or an 'enter' keypress). When this output is assigned,
* the icon will also set the `role=button` and `tabindex=0` attributes, unless you give them another
* explicit value.
*/
this.interact = new EventEmitter();
/** @internal */
this._leading = false;
/** @internal */
this._trailing = false;
this._tabIndex = null;
this._role = null;
/** @internal */
this._textField = null;
/** @internal */
this._mdcAdapter = {
// by returning null for 'tabindex', the foundation will not set tabindex/role attributes when
// disabled state changes. We want that, because we handle tabindex/role ourselves:
getAttr: (name) => name === 'tabindex' ? null : this._el.nativeElement.getAttribute(name),
setAttr: (name, value) => this._rndr.setAttribute(this._el.nativeElement, name, value),
removeAttr: (name) => this._rndr.removeAttribute(this._el.nativeElement, name),
setContent: (content) => this._el.nativeElement.textContent = content,
registerInteractionHandler: (evtType, handler) => this._reg.listen(this._rndr, evtType, handler, this._el),
deregisterInteractionHandler: (evtType, handler) => this._reg.unlisten(evtType, handler),
notifyIconAction: () => { var _a; return !((_a = this._textField) === null || _a === void 0 ? void 0 : _a._disabled) && this.interact.emit(); }
};
/** @internal */
this._foundation = new MDCTextFieldIconFoundation(this._mdcAdapter);
}
ngAfterContentInit() {
this._foundation.init();
}
ngOnDestroy() {
var _a;
(_a = this._foundation) === null || _a === void 0 ? void 0 : _a.destroy();
this._foundation = null;
}
/**
* The `tabindex` for icons defaults to `null` (no tabindex set) for icons without
* subscriptions to the `interact` output, and to `0` for icons that have an `interact`
* binding. You can override this default, by setting a non-null value for this property.
*/
get tabindex() {
var _a;
if (this.interact.observers.length > 0 && this._tabIndex == null && !((_a = this._textField) === null || _a === void 0 ? void 0 : _a._disabled))
return 0;
return this._tabIndex;
}
set tabindex(value) {
this._tabIndex = asNumberOrNull(value);
}
/**
* The `role` attribute for icons defaults to `null` (no role set) for icons without
* subscriptions to the `interact` output, and to `button` for icons that have an `interact`
* binding. You can override this default, by setting a non-null value for this property.
*/
get role() {
var _a;
if (this.interact.observers.length > 0 && this._role == null && !((_a = this._textField) === null || _a === void 0 ? void 0 : _a._disabled))
return 'button';
return this._role;
}
set role(value) {
this._role = value;
}
}
MdcTextFieldIconDirective.decorators = [
{ type: Directive, args: [{
selector: '[mdcTextFieldIcon]'
},] }
];
MdcTextFieldIconDirective.ctorParameters = () => [
{ type: Renderer2 },
{ type: ElementRef },
{ type: MdcEventRegistry }
];
MdcTextFieldIconDirective.propDecorators = {
_cls: [{ type: HostBinding, args: ['class.mdc-text-field__icon',] }],
interact: [{ type: Output }],
_leading: [{ type: HostBinding, args: ['class.mdc-text-field__icon--leading',] }],
_trailing: [{ type: HostBinding, args: ['class.mdc-text-field__icon--trailing',] }],
tabindex: [{ type: HostBinding, args: ['attr.tabindex',] }, { type: Input }],
role: [{ type: HostBinding, args: ['attr.role',] }, { type: Input }]
};
/**
* This directive wraps an optional `mdcTextFieldHelperText`. It should be the next sibling of the
* associated `mdcTextField` if used. See `mdcTextFieldHelperText` for more info.
*/
export class MdcTextFieldHelperLineDirective {
constructor() {
/** @internal */
this._cls = true;
}
}
MdcTextFieldHelperLineDirective.decorators = [
{ type: Directive, args: [{
selector: '[mdcTextFieldHelperLine]',
},] }
];
MdcTextFieldHelperLineDirective.propDecorators = {
_cls: [{ type: HostBinding, args: ['class.mdc-text-field-helper-line',] }]
};
class MdcTextFieldHelperTextDirectiveBase {
}
MdcTextFieldHelperTextDirectiveBase.decorators = [
{ type: Directive }
];
applyMixins(MdcTextFieldHelperTextDirectiveBase, [HasId]);
/**
* Directive for an optional helper-text to show supplemental information or validation
* messages for an <code>mdcTextField</code>. This directive should be wrapped inside an
* `mdcTextFieldHelperLine` that comes directly after the `mdcTextField` it belongs to.
* Additionally, you must export it as an <code>mdcHelperText</code>, and
* assign the exported object to the <code>helperText</code> property of the
* <code>mdcHelperText</code>. See the examples for hints on how to do this.
*
* The `mdcTextFieldInput` of the textfield will get `aria-controls` and `aria-describedby`
* accessibility attributes that point to the `id` of this helpertext element. If no `id` has
* been assigned, a unique `id` attribute will automatically be assigned. If the `id` attribute
* is changed, the aria attributes on the `mdcTextFieldInput` will be updated accordingly.
*/
export class MdcTextFieldHelperTextDirective extends MdcTextFieldHelperTextDirectiveBase {
constructor(_rndr, _elm) {
super();
this._rndr = _rndr;
this._elm = _elm;
/** @internal */
this._cls = true;
this._validation = false;
this._persistent = false;
/** @internal */
this._mdcAdapter = {
addClass: (className) => this._rndr.addClass(this._elm.nativeElement, className),
removeClass: (className) => this._rndr.removeClass(this._elm.nativeElement, className),
hasClass: (className) => this._elm.nativeElement.classList.contains(className),
setAttr: (name, value) => this._rndr.setAttribute(this._elm.nativeElement, name, value),
removeAttr: (name) => this._rndr.removeAttribute(this._elm.nativeElement, name),
setContent: () => {
// helperText content can be set by simply wrapping (dynamic) content in the directive.
// this is much more powerful than setContent, because it can also include html markup
// therefore there is no reason to do anything with setContent
throw new Error("MdcTextFieldHelperTextAdapter.setContent not supported");
}
};
/** @internal */
this._foundation = null;
}
ngOnInit() {
this.initId();
}
ngAfterContentInit() {
this._foundation = new MDCTextFieldHelperTextFoundation(this._mdcAdapter);
this._foundation.setPersistent(this._persistent);
this._foundation.setValidation(this._validation);
}
ngOnDestroy() {
var _a;
(_a = this._foundation) === null || _a === void 0 ? void 0 : _a.destroy();
this._foundation = null;
}
/**
* If set to a value other than false, the helper text is treated as a
* validation message, and only shown when the input is invalid.
*/
set validation(value) {
this._validation = asBoolean(value);
if (this._foundation)
this._foundation.setValidation(this._validation);
}
/**
* If set to a value other than false, the helper text is always visible.
* Otherwise the helper text will only be shown when the input has focus
* (or if `validation` is set, when the input is invalid).
*/
set persistent(value) {
this._persistent = asBoolean(value);
if (this._foundation)
this._foundation.setPersistent(this._persistent);
}
}
MdcTextFieldHelperTextDirective.decorators = [
{ type: Directive, args: [{
selector: '[mdcTextFieldHelperText]',
exportAs: 'mdcHelperText'
},] }
];
MdcTextFieldHelperTextDirective.ctorParameters = () => [
{ type: Renderer2 },
{ type: ElementRef }
];
MdcTextFieldHelperTextDirective.propDecorators = {
_cls: [{ type: HostBinding, args: ['class.mdc-text-field-helper-text',] }],
validation: [{ type: Input }],
persistent: [{ type: Input }]
};
/**
* Material design text-field. Text fields can be filled or outlined.
*
* Filled text-fields should have the following child directives:
* * `mdcTextFieldIcon` (optional leading icon)
* * `mdcTextFieldInput` (required, the native input)
* * `mdcTextFieldIcon` (optional trailing icon)
* * `mdcFloatingLabel` (optional floating label)
*
* Outlined text-fields should have the following child directives:
* * `mdcTextFieldIcon` (optional leading icon)
* * `mdcTextFieldInput` (required, the native input)
* * `mdcTextFieldIcon` (optional trailing icon)
* * `mdcNotchedOutline` (the outline, which can also contain an optional `mdcFloatingLabel`)
*
* Addditionally the text-field can be followed by an `mdcTextFieldHelperLine` containing an
* `mdcHelperText`.
*/
export class MdcTextFieldDirective extends AbstractMdcRipple {
constructor(renderer, root, registry, doc) {
super(root, renderer, registry, doc);
this.renderer = renderer;
this.root = root;
this.registry = registry;
this.onDestroy$ = new Subject();
this.onInputChange$ = new Subject();
this.onHelperTextChange$ = new Subject();
/** @internal */
this._cls = true;
this._leadingIcon = null;
this._trailingIcon = null;
this._helperText = null;
this._bottomLineElm = null;
this._valid = null;
this.mdcLineRippleAdapter = {
addClass: (className) => this.renderer.addClass(this._bottomLineElm, className),
removeClass: (className) => this.renderer.removeClass(this._bottomLineElm, className),
hasClass: (className) => this._bottomLineElm.classList.contains(className),
setStyle: (name, value) => this.renderer.setStyle(this._bottomLineElm, name, value),
registerEventHandler: (evtType, handler) => this.registry.listenElm(this.renderer, evtType, handler, this._bottomLineElm),
deregisterEventHandler: (evtType, handler) => this.registry.unlisten(evtType, handler)
};
this.mdcAdapter = {
addClass: (className) => this.renderer.addClass(this.root.nativeElement, className),
removeClass: (className) => this.renderer.removeClass(this.root.nativeElement, className),
hasClass: (className) => this.root.nativeElement.classList.contains(className),
registerTextFieldInteractionHandler: (evtType, handler) => {
this.registry.listen(this.renderer, evtType, handler, this.root);
},
deregisterTextFieldInteractionHandler: (evtType, handler) => {
this.registry.unlisten(evtType, handler);
},
registerInputInteractionHandler: (evtType, handler) => this._input && this.registry.listen(this.renderer, evtType, handler, this._input._elm),
deregisterInputInteractionHandler: (evtType, handler) => this.registry.unlisten(evtType, handler),
registerValidationAttributeChangeHandler: (handler) => {
const getAttributesList = (mutationsList) => mutationsList
.map((mutation) => mutation.attributeName)
.filter((attrName) => attrName);
const observer = new MutationObserver((mutationsList) => handler(getAttributesList(mutationsList)));
observer.observe(this._input._elm.nativeElement, { attributes: true });
return observer;
},
deregisterValidationAttributeChangeHandler: (observer) => observer.disconnect(),
getNativeInput: () => ({
value: this._input.value,
disabled: this._input.disabled,
maxLength: this._input._elm.nativeElement.maxLength,
type: this._input.type,
validity: {
valid: this._valid == null ? this._input.valid : !!this._valid,
badInput: this._input._isBadInput()
}
}),
isFocused: () => !!this._input && document.activeElement === this._input._elm.nativeElement,
shakeLabel: (shouldShake) => { var _a; return (_a = this._floatingLabel) === null || _a === void 0 ? void 0 : _a.shake(shouldShake); },
floatLabel: (shouldFloat) => { var _a; return (_a = this._floatingLabel) === null || _a === void 0 ? void 0 : _a.float(shouldFloat); },
hasLabel: () => !!this._floatingLabel,
getLabelWidth: () => this._floatingLabel ? this._floatingLabel.getWidth() : 0,
activateLineRipple: () => { var _a; return (_a = this.bottomLineFoundation) === null || _a === void 0 ? void 0 : _a.activate(); },
deactivateLineRipple: () => { var _a; return (_a = this.bottomLineFoundation) === null || _a === void 0 ? void 0 : _a.deactivate(); },
setLineRippleTransformOrigin: (normalizedX) => { var _a; return (_a = this.bottomLineFoundation) === null || _a === void 0 ? void 0 : _a.setRippleCenter(normalizedX); },
hasOutline: () => !!this._outline,
notchOutline: (labelWidth) => { var _a; return (_a = this._outline) === null || _a === void 0 ? void 0 : _a.open(labelWidth); },
closeOutline: () => { var _a; return (_a = this._outline) === null || _a === void 0 ? void 0 : _a.close(); }
};
this.bottomLineFoundation = null;
this.foundation = null;
}
ngAfterContentInit() {
merge(this._floatingLabels.changes, this._icons.changes, this._inputs.changes, this._outlines.changes, this.onHelperTextChange$).pipe(takeUntil(this.onDestroy$), debounceTime(1)).subscribe(() => {
this.reconstructComponent();
});
this.initComponent();
}
ngOnDestroy() {
this.onInputChange$.next();
this.onInputChange$.complete();
this.onDestroy$.next();
this.onDestroy$.complete();
this.onHelperTextChange$.complete();
this.destroyComponent();
}
initComponent() {
var _a, _b, _c;
if (this._input && !this._outline && !this._input._isTextarea()) {
this.addRippleSurface('mdc-text-field__ripple', true);
this.initRipple();
this.initLineRipple();
}
this.attachLabelToInput();
this.attachHelperTextToInput();
this.initIcons();
this.foundation = new MDCTextFieldFoundation(this.mdcAdapter, {
helperText: ((_a = this.helperText) === null || _a === void 0 ? void 0 : _a._foundation) ? this.helperText._foundation : undefined,
leadingIcon: ((_b = this._leadingIcon) === null || _b === void 0 ? void 0 : _b._foundation) ? this._leadingIcon._foundation : undefined,
trailingIcon: ((_c = this._trailingIcon) === null || _c === void 0 ? void 0 : _c._foundation) ? this._trailingIcon._foundation : undefined
});
this.foundation.init();
this.subscribeInputChanges();
if (this._helperText) {
this._helperText.idChange().pipe(takeUntil(this.onDestroy$), takeUntil(this.onHelperTextChange$)).subscribe(() => this.attachHelperTextToInput());
}
}
destroyComponent() {
var _a;
this.destroyRippleSurface();
this.destroyRipple();
this.destroyLineRipple();
(_a = this.foundation) === null || _a === void 0 ? void 0 : _a.destroy();
this.foundation = null;
}
reconstructComponent() {
this.destroyComponent();
this.initComponent();
this.recomputeOutline(); // TODO check if we still need this with latest material-components-web
}
initLineRipple() {
if (!this._outline) {
this._bottomLineElm = this.renderer.createElement('div');
this.renderer.addClass(this._bottomLineElm, 'mdc-line-ripple');
this.renderer.appendChild(this.root.nativeElement, this._bottomLineElm);
this.bottomLineFoundation = new MDCLineRippleFoundation(this.mdcLineRippleAdapter);
this.bottomLineFoundation.init();
}
}
destroyLineRipple() {
var _a;
if (this._bottomLineElm) {
(_a = this.bottomLineFoundation) === null || _a === void 0 ? void 0 : _a.destroy();
this.bottomLineFoundation = null;
this.renderer.removeChild(this.root.nativeElement, this._bottomLineElm);
this._bottomLineElm = null;
}
}
recomputeOutline() {
if (this._outline) {
// the outline may not be valid after re-initialisation, recompute outline when all
// style/structural changes have been employed:
setTimeout(() => { var _a; (_a = this.foundation) === null || _a === void 0 ? void 0 : _a.notchOutline(this.foundation.shouldFloat); }, 0);
}
}
initIcons() {
this._leadingIcon = this.computeLeadingIcon();
this._trailingIcon = this.computeTrailingIcon(this._leadingIcon);
this._icons.forEach(icon => {
icon._textField = this;
icon._leading = icon === this._leadingIcon;
icon._trailing = icon === this._trailingIcon;
});
}
computeLeadingIcon() {
if (this._icons.length > 0) {
let icon = this._icons.first;
let prev = this.previousElement(icon._el.nativeElement);
let last = icon._el.nativeElement;
while (true) {
// if it is contained in another element, check the siblings of the container too:
if (prev == null && last != null && last.parentElement !== this.root.nativeElement)
prev = last.parentElement;
// no more elements before, must be the leading icon:
if (prev == null)
return icon;
// comes after the text, so it's not the leading icon:
if (this._input && (prev === this._input._elm.nativeElement || prev.contains(this._input._elm.nativeElement)))
return null;
last = prev;
prev = this.previousElement(prev);
}
}
return null;
}
computeTrailingIcon(leading) {
if (this._icons.length > 0) {
let icon = this._icons.last;
if (icon === leading)
return null;
// if not the leading icon, it must be the trailing icon:
return icon;
}
return null;
}
previousElement(el) {
let result = el.previousSibling;
while (result != null && !(result instanceof Element))
result = result.previousSibling;
return result;
}
attachLabelToInput() {
var _a, _b;
// if the mdcTextField is a LABEL element wrapping the input OR the floatingLabel is NOT a LABEL element,
// the input gets an aria-labelledby attaching it to the floatingLabel;
// otherwise the floatingLabel gets a 'for' attribute, attaching it to the input:
let first = true;
const needLabeledBy = this.root.nativeElement.nodeName.toLowerCase() === 'label' || !((_a = this._floatingLabel) === null || _a === void 0 ? void 0 : _a.isLabelElement());
this._inputs.forEach(input => {
var _a;
input._labeledBy = (first && needLabeledBy) ? ((_a = this._floatingLabel) === null || _a === void 0 ? void 0 : _a.id) || null : null;
first = false;
});
first = true;
(_b = this._floatingLabels) === null || _b === void 0 ? void 0 : _b.forEach(label => {
var _a, _b;
label.for = (first && !needLabeledBy && ((_a = this._floatingLabel) === null || _a === void 0 ? void 0 : _a.isLabelElement())) ? ((_b = this._input) === null || _b === void 0 ? void 0 : _b.id) || null : null;
first = false;
});
}
attachHelperTextToInput() {
let first = true;
this._inputs.forEach(input => {
var _a;
const assign = first ? ((_a = this._helperText) === null || _a === void 0 ? void 0 : _a.id) || null : null;
input._controls = assign;
input._describedBy = assign;
first = false;
});
}
subscribeInputChanges() {
var _a;
this.onInputChange$.next();
(_a = this._input) === null || _a === void 0 ? void 0 : _a._valueChange.asObservable().pipe(takeUntil(this.onInputChange$)).subscribe((value) => {
var _a;
(_a = this.foundation) === null || _a === void 0 ? void 0 : _a.setValue(value); // value can be null, but null should be accepted by foundation
});
}
/** @internal */
getRippleInteractionElement() {
return this._input._elm;
}
/**
* The <code>valid</code> property provides a way to override the validity checking of the
* underlying angular form control or native input. A value of true or false will make the
* text-field validity styling based on this value. A value of <code>null</code>, or
* <code>undefined</code> will reset the validity styling to the state of the underlying
* angular form control or native input.
*
* For most use cases messing with this input is not be needed.
* When the input/textarea is an ngControl, the mdcTextField is already aware of that,
* and is already using the 'valid' property of that control.
* However, in some specific cases, binding to <code>valid</code> can help. Example:
* When you want the mdcTextField to go to 'invalid' state only when the underlying
* control is invalid AND that control's value is changed, you can bind as follows:
* <code>valid="myControl.valid || !myControl.dirty"</code>.
*/
set valid(value) {
var _a, _b, _c;
if (value == null) {
this._valid = null; // reset to null, validity now managed by the input control.
(_a = this.foundation) === null || _a === void 0 ? void 0 : _a.setUseNativeValidation(true);
// foundation doesn't change style when we switch to native validation;
// trigger possible new style:
this.foundation && this.foundation['styleValidity_']((_b = this.mdcAdapter.getNativeInput()) === null || _b === void 0 ? void 0 : _b.validity.valid);
}
else if (value !== this._valid) {
this._valid = asBoolean(value);
(_c = this.foundation) === null || _c === void 0 ? void 0 : _c.setValid(this._valid);
}
}
/** @internal */
get _textArea() {
return this._input._isTextarea();
}
/** @internal */
get outlined() {
return !!this._outline;
}
/** @internal */
get noLabel() {
return !this._floatingLabel;
}
/** @internal */
get _leading() {
return !!this._leadingIcon;
}
/** @internal */
get _trailing() {
return !!this._trailingIcon;
}
/**
* Assign an <code>mdcTextFieldHelperText</code> (exported as <code>mdcHelperText</code>) to this
* input to add a helper-text or validation message to the text-field. See the examples for hints
* on how to do this.
*/
get helperText() {
return this._helperText;
}
set helperText(helperText) {
this._helperText = helperText;
this.onHelperTextChange$.next();
}
/** @internal */
get _disabled() {
// TODO: this mirrors what the text-field can update itself from adapter.getNativeInput
// is there a way to trigger the textfield to re-read that when the disabled state of
// the input changes?
return this._input ? this._input.disabled : false;
}
get _input() {
var _a;
return (_a = this._inputs) === null || _a === void 0 ? void 0 : _a.first;
}
get _floatingLabel() {
var _a;
return (_a = this._floatingLabels) === null || _a === void 0 ? void 0 : _a.first;
}
get _outline() {
var _a;
return (_a = this._outlines) === null || _a === void 0 ? void 0 : _a.first;
}
}
MdcTextFieldDirective.decorators = [
{ type: Directive, args: [{
selector: '[mdcTextField]',
providers: [{ provide: AbstractMdcRipple, useExisting: forwardRef(() => MdcTextFieldDirective) }]
},] }
];
MdcTextFieldDirective.ctorParameters = () => [
{ type: Renderer2 },
{ type: ElementRef },
{ type: MdcEventRegistry },
{ type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] }
];
MdcTextFieldDirective.propDecorators = {
_cls: [{ type: HostBinding, args: ['class.mdc-text-field',] }],
_icons: [{ type: ContentChildren, args: [MdcTextFieldIconDirective,] }],
_inputs: [{ type: ContentChildren, args: [MdcTextFieldInputDirective,] }],
_floatingLabels: [{ type: ContentChildren, args: [MdcFloatingLabelDirective, { descendants: true },] }],
_outlines: [{ type: ContentChildren, args: [MdcNotchedOutlineDirective,] }],
valid: [{ type: Input }],
_textArea: [{ type: HostBinding, args: ['class.mdc-text-field--textarea',] }],
outlined: [{ type: HostBinding, args: ['class.mdc-text-field--outlined',] }],
noLabel: [{ type: HostBinding, args: ['class.mdc-text-field--no-label',] }],
_leading: [{ type: HostBinding, args: ['class.mdc-text-field--with-leading-icon',] }],
_trailing: [{ type: HostBinding, args: ['class.mdc-text-field--with-trailing-icon',] }],
helperText: [{ type: Input }],
_disabled: [{ type: HostBinding, args: ['class.mdc-text-field--disabled',] }]
};
export const TEXT_FIELD_DIRECTIVES = [
MdcTextFieldInputDirective,
MdcTextFieldIconDirective,
MdcTextFieldHelperLineDirective,
MdcTextFieldHelperTextDirective,
MdcTextFieldDirective
];
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWRjLnRleHQtZmllbGQuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2NvbXBvbmVudHMvdGV4dC1maWVsZC9tZGMudGV4dC1maWVsZC5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFvQixlQUFlLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsV0FBVyxFQUN4RixZQUFZLEVBQUUsS0FBSyxFQUFxQixRQUFRLEVBQWEsU0FBUyxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNwSSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzNDLE9BQU8sRUFBRSxzQkFBc0IsRUFBdUIsTUFBTSxxQkFBcUIsQ0FBQztBQUNsRixPQUFPLEVBQUUsdUJBQXVCLEVBQXdCLE1BQU0sdUJBQXVCLENBQUM7QUFDdEYsT0FBTyxFQUFFLGdDQUFnQyxFQUFpQyxNQUFNLHFCQUFxQixDQUFDO0FBQ3RHLE9BQU8sRUFBRSwwQkFBMEIsRUFBMkIsTUFBTSxxQkFBcUIsQ0FBQztBQUMxRixPQUFPLEVBQUUseUJBQXlCLEVBQUUsTUFBTSxnREFBZ0QsQ0FBQztBQUMzRixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNsRSxPQUFPLEVBQUUsU0FBUyxFQUFFLGNBQWMsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3BFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2xFLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLGtEQUFrRCxDQUFDO0FBQzlGLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ2xFLE9BQU8sRUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3RDLE9BQU8sRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDekQsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ3BELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUVqRCxJQUFJLE1BQU0sR0FBRyxDQUFDLENBQUM7QUFFZjs7R0FFRztBQUtILE1BQU0sT0FBTywwQkFBMkIsU0FBUSxnQkFBZ0I7SUFrQjVELFlBQW1CLElBQWdCLEVBQVUsUUFBbUIsRUFBNkIsS0FBZ0I7UUFDekcsS0FBSyxFQUFFLENBQUM7UUFETyxTQUFJLEdBQUosSUFBSSxDQUFZO1FBQVUsYUFBUSxHQUFSLFFBQVEsQ0FBVztRQUE2QixVQUFLLEdBQUwsS0FBSyxDQUFXO1FBakI3RyxnQkFBZ0I7UUFDcUMsU0FBSSxHQUFHLElBQUksQ0FBQztRQUNqRSxnQkFBZ0I7UUFDcUIsZUFBVSxHQUFrQixJQUFJLENBQUM7UUFDdEUsZ0JBQWdCO1FBQ21CLGNBQVMsR0FBa0IsSUFBSSxDQUFDO1FBQ25FLGdCQUFnQjtRQUNzQixpQkFBWSxHQUFrQixJQUFJLENBQUM7UUFDekUsZ0JBQWdCO1FBQ0csaUJBQVksR0FBZ0MsSUFBSSxZQUFZLEVBQWlCLENBQUM7UUFDekYsZUFBVSxHQUFpQixJQUFJLE9BQU8sRUFBRSxDQUFDO1FBQ3pDLFFBQUcsR0FBa0IsSUFBSSxDQUFDO1FBQzFCLFVBQUssR0FBRyxNQUFNLENBQUM7UUFDZixXQUFNLEdBQUcsRUFBRSxDQUFDO1FBQ1osY0FBUyxHQUFHLEtBQUssQ0FBQztRQUNsQixhQUFRLEdBQWtCLElBQUksQ0FBQztJQUl2QyxDQUFDO0lBRUQsUUFBUTs7UUFDSiwwREFBMEQ7UUFDMUQsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDO1FBRWxCLE1BQUEsSUFBSSxDQUFDLEtBQUssMENBQUUsWUFBWSxDQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxHQUFHLEVBQUU7WUFDdEUsNkZBQTZGO1lBQzdGLHVEQUF1RDtZQUN2RCxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQztRQUMxRCxDQUFDLEVBQUU7SUFDUCxDQUFDO0lBRUQsV0FBVztRQUNQLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDdkIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUMvQixDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsSUFDYSxFQUFFO1FBQ1gsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDO0lBQ3BCLENBQUM7SUFFRCxJQUFJLEVBQUUsQ0FBQyxLQUFvQjtRQUN2QixJQUFJLENBQUMsR0FBRyxHQUFHLEtBQUssSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7SUFDdEMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsSUFDYSxRQUFRO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQy9ELENBQUM7SUFFRCxJQUFJLFFBQVEsQ0FBQyxLQUFjO1FBQ3ZCLElBQUksQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3RDLENBQUM7SUFJRCxnQkFBZ0I7SUFDaEIsSUFBYSxJQUFJO1FBQ2IsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ3RCLENBQUM7SUFFRCxJQUFJLElBQUksQ0FBQyxLQUFhO1FBQ2xCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxJQUFJLE1BQU0sQ0FBQztRQUU3QixzRUFBc0U7UUFDdEUsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsRUFBRTtZQUNyQixJQUFJO2dCQUNBLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7YUFDMUU7WUFBQyxPQUFPLENBQUMsRUFBRTtnQkFDUixJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO2FBQzNFO1NBQ0o7SUFDTCxDQUFDO0lBRUQsZ0JBQWdCO0lBQ2hCLElBQWEsS0FBSztRQUNkLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQztJQUN2QixDQUFDO0lBRUQsZ0JBQWdCO0lBQ2hCLElBQUksS0FBSyxDQUFDLEtBQWE7UUFDbkIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVPLFdBQVcsQ0FBQyxLQUFVLEVBQUUsV0FBb0I7UUFDaEQsTUFBTSxNQUFNLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3pDLElBQUksTUFBTSxLQUFLLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDeEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDO1lBQ3JELElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO1NBQ3pEO1FBQ0QsSUFBSSxDQUFDLFdBQVcsSUFBSSxJQUFJLENBQUMsS0FBSyxJQUFJLE1BQU0sS0FBSyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRTtZQUMzRCxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQVEsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyw2REFBNkQ7U0FDdEc7SUFDTCxDQUFDO0lBRUQsZ0JBQWdCO0lBQ08sUUFBUTtRQUMzQixJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUs7WUFDWCxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztJQUMvRCxDQUFDO0lBRUQsZ0JBQWdCO0lBQ2hCLElBQUksS0FBSztRQUNMLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBRSxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWtDLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQztJQUMxRyxDQUFDO0lBRUQsZ0JBQWdCO0lBQ2hCLFdBQVc7UUFDUCxPQUFRLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBa0MsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDO0lBQzNFLENBQUM7SUFFRCxnQkFBZ0I7SUFDaEIsV0FBVztRQUNQLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxLQUFLLFVBQVUsQ0FBQztJQUN6RSxDQUFDO0lBRUQsZ0JBQWdCO0lBQ2hCLE1BQU07UUFDRixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLElBQUksYUFBYSxNQUFNLEVBQUUsRUFBRSxDQUFDO1FBQ3pELE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQztJQUN6QixDQUFDOzs7WUF4SUosU0FBUyxTQUFDO2dCQUNQLFFBQVEsRUFBRSx1REFBdUQ7Z0JBQ2pFLFNBQVMsRUFBRSxDQUFDLEVBQUMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLFdBQVcsRUFBRSxVQUFVLENBQUMsR0FBRyxFQUFFLENBQUMsMEJBQTBCLENBQUMsRUFBRSxDQUFDO2FBQ3ZHOzs7WUEzQnNELFVBQVU7WUFDRixTQUFTO1lBRS9ELFNBQVMsdUJBMkNxRCxRQUFRLFlBQUksSUFBSTs7O21CQWhCbEYsV0FBVyxTQUFDLDZCQUE2Qjt5QkFFekMsV0FBVyxTQUFDLHNCQUFzQjt3QkFFbEMsV0FBVyxTQUFDLG9CQUFvQjsyQkFFaEMsV0FBVyxTQUFDLHVCQUF1QjsyQkFFbkMsTUFBTTtpQkFtQ04sV0FBVyxZQUNYLEtBQUs7dUJBV0wsV0FBVyxZQUNYLEtBQUs7bUJBV0wsS0FBSztvQkFrQkwsS0FBSzt1QkFxQkwsWUFBWSxTQUFDLE9BQU87O0FBMkJ6Qjs7Ozs7R0FLRztBQUlILE1BQU0sT0FBTyx5QkFBeUI7SUFpQ2xDLFlBQW9CLEtBQWdCLEVBQVMsR0FBZSxFQUFVLElBQXNCO1FBQXhFLFVBQUssR0FBTCxLQUFLLENBQVc7UUFBUyxRQUFHLEdBQUgsR0FBRyxDQUFZO1FBQVUsU0FBSSxHQUFKLElBQUksQ0FBa0I7UUFoQzVGLGdCQUFnQjtRQUNvQyxTQUFJLEdBQUcsSUFBSSxDQUFDO1FBQ2hFOzs7O1dBSUc7UUFDZ0IsYUFBUSxHQUF1QixJQUFJLFlBQVksRUFBRSxDQUFDO1FBQ3JFLGdCQUFnQjtRQUNvQyxhQUFRLEdBQUcsS0FBSyxDQUFDO1FBQ3JFLGdCQUFnQjtRQUNxQyxjQUFTLEdBQUcsS0FBSyxDQUFDO1FBQy9ELGNBQVMsR0FBa0IsSUFBSSxDQUFDO1FBQ2hDLFVBQUssR0FBa0IsSUFBSSxDQUFDO1FBQ3BDLGdCQUFnQjtRQUNoQixlQUFVLEdBQWlDLElBQUksQ0FBQztRQUVoRCxnQkFBZ0I7UUFDaEIsZ0JBQVcsR0FBNEI7WUFDbkMsOEZBQThGO1lBQzlGLG1GQUFtRjtZQUNuRixPQUFPLEVBQUUsQ0FBQyxJQUFZLEVBQUUsRUFBRSxDQUFDLElBQUksS0FBSyxVQUFVLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQztZQUNqRyxPQUFPLEVBQUUsQ0FBQyxJQUFZLEVBQUUsS0FBYSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLGFBQWEsRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDO1lBQ3RHLFVBQVUsRUFBRSxDQUFDLElBQVksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLEVBQUUsSUFBSSxDQUFDO1lBQ3RGLFVBQVUsRUFBRSxDQUFDLE9BQWUsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsV0FBVyxHQUFHLE9BQU87WUFDN0UsMEJBQTBCLEVBQUUsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQztZQUMxRyw0QkFBNEIsRUFBRSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUM7WUFDeEYsZ0JBQWdCLEVBQUUsR0FBRyxFQUFFLFdBQUMsT0FBQSxRQUFDLElBQUksQ0FBQyxVQUFVLDBDQUFFLFNBQVMsQ0FBQSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUEsRUFBQTtTQUM5RSxDQUFDO1FBQ0YsZ0JBQWdCO1FBQ2hCLGdCQUFXLEdBQXNDLElBQUksMEJBQTBCLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBR2xHLENBQUM7SUFFRCxrQkFBa0I7UUFDZCxJQUFJLENBQUMsV0FBWSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQzdCLENBQUM7SUFFRCxXQUFXOztRQUNQLE1BQUEsSUFBSSxDQUFDLFdBQVcsMENBQUUsT0FBTyxHQUFHO1FBQzVCLElBQUksQ0FBQyxXQUFXLEdBQUcsSUFBSSxDQUFDO0lBQzVCLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsSUFBMkMsUUFBUTs7UUFDL0MsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxTQUFTLElBQUksSUFBSSxJQUFJLFFBQUMsSUFBSSxDQUFDLFVBQVUsMENBQUUsU0FBUyxDQUFBO1lBQzNGLE9BQU8sQ0FBQyxDQUFDO1FBQ2IsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDO0lBQzFCLENBQUM7SUFFRCxJQUFJLFFBQVEsQ0FBQyxLQUFLO1FBQ2QsSUFBSSxDQUFDLFNBQVMsR0FBRyxjQUFjLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUlEOzs7O09BSUc7SUFDSCxJQUF1QyxJQUFJOztRQUN2QyxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUssSUFBSSxJQUFJLElBQUksUUFBQyxJQUFJLENBQUMsVUFBVSwwQ0FBRSxTQUFTLENBQUE7WUFDdkYsT0FBTyxRQUFRLENBQUM7UUFDcEIsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDO0lBQ3RCLENBQUM7SUFFRCxJQUFJLElBQUksQ0FBQyxLQUFLO1FBQ1YsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUM7SUFDdkIsQ0FBQzs7O1lBOUVKLFNBQVMsU0FBQztnQkFDUCxRQUFRLEVBQUUsb0JBQW9CO2FBQ2pDOzs7WUExSzhELFNBQVM7WUFEakIsVUFBVTtZQWF4RCxnQkFBZ0I7OzttQkFpS3BCLFdBQVcsU0FBQyw0QkFBNEI7dUJBTXhDLE1BQU07dUJBRU4sV0FBVyxTQUFDLHFDQUFxQzt3QkFFakQsV0FBVyxTQUFDLHNDQUFzQzt1QkFzQ2xELFdBQVcsU0FBQyxlQUFlLGNBQUcsS0FBSzttQkFpQm5DLFdBQVcsU0FBQyxXQUFXLGNBQUcsS0FBSzs7QUFXcEM7OztHQUdHO0FBSUgsTUFBTSxPQUFPLCtCQUErQjtJQUg1QztRQUlJLGdCQUFnQjtRQUMwQyxTQUFJLEdBQUcsSUFBSSxDQUFDO0lBQzFFLENBQUM7OztZQU5BLFNBQVMsU0FBQztnQkFDUCxRQUFRLEVBQUUsMEJBQTBCO2FBQ3ZDOzs7bUJBR0ksV0FBVyxTQUFDLGtDQUFrQzs7QUFHbkQsTUFDTSxtQ0FBbUM7OztZQUR4QyxTQUFTOztBQUdWLFdBQVcsQ0FBQyxtQ0FBbUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7QUFDMUQ7Ozs7Ozs7Ozs7OztHQVlHO0FBS0gsTUFBTSxPQUFPLCtCQUFnQyxTQUFRLG1DQUFtQztJQXNCcEYsWUFBb0IsS0FBZ0IsRUFBUyxJQUFnQjtRQUN6RCxLQUFLLEVBQUUsQ0FBQztRQURRLFVBQUssR0FBTCxLQUFLLENBQVc7UUFBUyxTQUFJLEdBQUosSUFBSSxDQUFZO1FBckI3RCxnQkFBZ0I7UUFDMEMsU0FBSSxHQUFHLElBQUksQ0FBQztRQUM5RCxnQkFBVyxHQUFHLEtBQUssQ0FBQztRQUNwQixnQkFBVyxHQUFHLEtBQUssQ0FBQztRQUM1QixnQkFBZ0I7UUFDaEIsZ0JBQVcsR0FBa0M7WUFDekMsUUFBUSxFQUFFLENBQUMsU0FBaUIsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsU0FBUyxDQUFDO1lBQ3hGLFdBQVcsRUFBRSxDQUFDLFNBQWlCLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLFNBQVMsQ0FBQztZQUM5RixRQUFRLEVBQUUsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDO1lBQzlFLE9BQU8sRUFBRSxDQUFDLElBQVksRUFBRSxLQUFhLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLElBQUksRUFBRSxLQUFLLENBQUM7WUFDdkcsVUFBVSxFQUFFLENBQUMsSUFBWSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUM7WUFDdkYsVUFBVSxFQUFFLEdBQUcsRUFBRTtnQkFDYix1RkFBdUY7Z0JBQ3ZGLHNGQUFzRjtnQkFDdEYsOERBQThEO2dCQUM5RCxNQUFNLElBQUksS0FBSyxDQUFDLHdEQUF3RCxDQUFDLENBQUM7WUFDOUUsQ0FBQztTQUNKLENBQUM7UUFDRixnQkFBZ0I7UUFDaEIsZ0JBQVcsR0FBNEMsSUFBSSxDQUFDO0lBSTVELENBQUM7SUFFRCxRQUFRO1FBQ0osSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ2xCLENBQUM7SUFFRCxrQkFBa0I7UUFDZCxJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksZ0NBQWdDLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO1FBQzFFLElBQUksQ0FBQyxXQUFXLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNqRCxJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDckQsQ0FBQztJQUVELFdBQVc7O1FBQ1AsTUFBQSxJQUFJLENBQUMsV0FBVywwQ0FBRSxPQUFPLEdBQUc7UUFDNUIsSUFBSSxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUM7SUFDNUIsQ0FBQztJQUVEOzs7T0FHRztJQUNILElBQWEsVUFBVSxDQUFDLEtBQWM7UUFDbEMsSUFBSSxDQUFDLFdBQVcsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDcEMsSUFBSSxJQUFJLENBQUMsV0FBVztZQUNoQixJQUFJLENBQUMsV0FBVyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDekQsQ0FBQztJQUlEOzs7O09BSUc7SUFDSCxJQUFhLFVBQVUsQ0FBQyxLQUFjO1FBQ2xDLElBQUksQ0FBQyxXQUFXLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3BDLElBQUksSUFBSSxDQUFDLFdBQVc7WUFDaEIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ3pELENBQUM7OztZQWxFSixTQUFTLFNBQUM7Z0JBQ1AsUUFBUSxFQUFFLDBCQUEwQjtnQkFDcEMsUUFBUSxFQUFFLGVBQWU7YUFDNUI7OztZQXpSOEQsU0FBUztZQURqQixVQUFVOzs7bUJBNlI1RCxXQUFXLFNBQUMsa0NBQWtDO3lCQTJDOUMsS0FBSzt5QkFhTCxLQUFLOztBQVNWOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQUtILE1BQU0sT0FBTyxxQkFBc0IsU0FBUSxpQkFBaUI7SUF5RXhELFlBQW9CLFFBQW1CLEVBQVUsSUFBZ0IsRUFBVSxRQUEwQixFQUFvQixHQUFRO1FBQzdILEtBQUssQ0FBQyxJQUFJLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxHQUFlLENBQUMsQ0FBQztRQURqQyxhQUFRLEdBQVIsUUFBUSxDQUFXO1FBQVUsU0FBSSxHQUFKLElBQUksQ0FBWTtRQUFVLGFBQVEsR0FBUixRQUFRLENBQWtCO1FBeEU3RixlQUFVLEdBQWlCLElBQUksT0FBTyxFQUFFLENBQUM7UUFDekMsbUJBQWMsR0FBaUIsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUM3Qyx3QkFBbUIsR0FBaUIsSUFBSSxPQUFPLEVBQUUsQ0FBQztRQUMxRCxnQkFBZ0I7UUFDOEIsU0FBSSxHQUFHLElBQUksQ0FBQztRQVNsRCxpQkFBWSxHQUFxQyxJQUFJLENBQUM7UUFDdEQsa0JBQWEsR0FBcUMsSUFBSSxDQUFDO1FBQ3ZELGdCQUFXLEdBQTJDLElBQUksQ0FBQztRQUMzRCxtQkFBYyxHQUF1QixJQUFJLENBQUM7UUFDMUMsV0FBTSxHQUFtQixJQUFJLENBQUM7UUFDOUIseUJBQW9CLEdBQXlCO1lBQ2pELFFBQVEsRUFBRSxDQUFDLFNBQWlCLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsU0FBUyxDQUFDO1lBQ3ZGLFdBQVcsRUFBRSxDQUFDLFNBQWlCLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxjQUFjLEVBQUUsU0FBUyxDQUFDO1lBQzdGLFFBQVEsRUFBRSxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWUsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQztZQUMzRSxRQUFRLEVBQUUsQ0FBQyxJQUFZLEVBQUUsS0FBYSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsY0FBYyxFQUFFLElBQUksRUFBRSxLQUFLLENBQUM7WUFDbkcsb0JBQW9CLEVBQUUsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLGNBQWUsQ0FBQztZQUMxSCxzQkFBc0IsRUFBRSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUM7U0FDekYsQ0FBQztRQUNNLGVBQVUsR0FBd0I7WUFDdEMsUUFBUSxFQUFFLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxTQUFTLENBQUM7WUFDbkYsV0FBVyxFQUFFLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxTQUFTLENBQUM7WUFDekYsUUFBUSxFQUFFLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQztZQUM5RSxtQ0FBbUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRTtnQkFDdEQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNyRSxDQUFDO1lBQ0QscUNBQXFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUU7Z0JBQ3hELElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztZQUM3QyxDQUFDO1lBQ0QsK0JBQStCLEVBQUUsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQztZQUM3SSxpQ0FBaUMsRUFBRSxDQUFDLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUM7WUFDakcsd0NBQXdDLEVBQUUsQ0FBQyxPQUFrQyxFQUFFLEVBQUU7Z0JBQzdFLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxhQUFrQixFQUFFLEVBQUUsQ0FBQyxhQUFhO3FCQUMxRCxHQUFHLENBQUMsQ0FBQyxRQUFhLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUM7cUJBQzlDLE1BQU0sQ0FBQyxDQUFDLFFBQWdCLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxDQUFDO2dCQUM1QyxNQUFNLFFBQVEsR0FBRyxJQUFJLGdCQUFnQixDQUFDLENBQUMsYUFBYSxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUNwRyxRQUFRLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFPLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxFQUFDLFVBQVUsRUFBRSxJQUFJLEVBQUMsQ0FBQyxDQUFDO2dCQUN0RSxPQUFPLFFBQVEsQ0FBQztZQUNwQixDQUFDO1lBQ0QsMENBQTBDLEVBQUUsQ0FBQyxRQUEwQixFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsVUFBVSxFQUFFO1lBQ2pHLGNBQWMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO2dCQUNuQixLQUFLLEVBQUUsSUFBSSxDQUFDLE1BQU8sQ0FBQyxLQUFLO2dCQUN6QixRQUFRLEVBQUUsSUFBSSxDQUFDLE1BQU8sQ0FBQyxRQUFRO2dCQUMvQixTQUFTLEVBQUUsSUFBSSxDQUFDLE1BQU8sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLFNBQVM7Z0JBQ3BELElBQUksRUFBRSxJQUFJLENBQUMsTUFBTyxDQUFDLElBQUk7Z0JBQ3ZCLFFBQVEsRUFBRTtvQkFDTixLQUFLLEVBQUUsSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU07b0JBQy9ELFFBQVEsRUFBRSxJQUFJLENBQUMsTUFBTyxDQUFDLFdBQVcsRUFBRTtpQkFDdkM7YUFDSixDQUFDO1lBQ0YsU0FBUyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLFFBQVEsQ0FBQyxhQUFhLEtBQUssSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYTtZQUMzRixVQUFVLEVBQUUsQ0FBQyxXQUFvQixFQUFFLEVBQUUsd0JBQUMsSUFBSSxDQUFDLGNBQWMsMENBQUUsS0FBSyxDQUFDLFdBQVcsSUFBQztZQUM3RSxVQUFVLEVBQUUsQ0FBQyxXQUFvQixFQUFFLEVBQUUsd0JBQUMsSUFBSSxDQUFDLGNBQWMsMENBQUUsS0FBSyxDQUFDLFdBQVcsSUFBQztZQUM3RSxRQUFRLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxjQUFjO1lBQ3JDLGFBQWEsRUFBRSxHQUFHLEV