diff --git a/packages/mdc-base/component.ts b/packages/mdc-base/component.ts index 5fadb3cc080..d39a498f570 100644 --- a/packages/mdc-base/component.ts +++ b/packages/mdc-base/component.ts @@ -51,6 +51,7 @@ class MDCComponent { this.initialSyncWithDOM(); } + /* istanbul ignore next: method param only exists for typing purposes; it does not need to be unit tested */ // tslint:disable-next-line:no-any a component can pass in anything it needs to initialize initialize(..._args: any[]) { // Subclasses can override this to do any additional setup work that would be considered part of a diff --git a/packages/mdc-checkbox/foundation.ts b/packages/mdc-checkbox/foundation.ts index 8b2245af849..f99d745e833 100644 --- a/packages/mdc-checkbox/foundation.ts +++ b/packages/mdc-checkbox/foundation.ts @@ -58,8 +58,8 @@ class MDCCheckboxFoundation extends MDCFoundation { private animEndLatchTimer_ = 0; private enableAnimationEndHandler_ = false; - constructor(adapter: MDCCheckboxAdapter) { - super(Object.assign(MDCCheckboxFoundation.defaultAdapter, adapter)); + constructor(adapter?: Partial) { + super({...MDCCheckboxFoundation.defaultAdapter, ...adapter}); } init() { diff --git a/packages/mdc-checkbox/index.ts b/packages/mdc-checkbox/index.ts index 17635809cf0..61d378e0d6e 100644 --- a/packages/mdc-checkbox/index.ts +++ b/packages/mdc-checkbox/index.ts @@ -24,11 +24,11 @@ import {getCorrectEventName} from '@material/animation/index'; import {MDCComponent} from '@material/base/component'; import {EventType, SpecificEventListener} from '@material/base/index'; -import {MDCRipple, MDCRippleFoundation, RippleCapableSurface, util} from '@material/ripple/index'; +import {ponyfill} from '@material/dom/index'; +import {MDCRipple, MDCRippleFoundation, RippleCapableSurface} from '@material/ripple/index'; import {MDCSelectionControl} from '@material/selection-control/index'; import {MDCCheckboxFoundation} from './foundation'; -const {getMatchesProperty} = util; const CB_PROTO_PROPS = ['checked', 'indeterminate']; class MDCCheckbox extends MDCComponent implements MDCSelectionControl, RippleCapableSurface { @@ -87,18 +87,15 @@ class MDCCheckbox extends MDCComponent implements MDCSele } private initRipple_(): MDCRipple { - const MATCHES = getMatchesProperty(HTMLElement.prototype); - const adapter = Object.assign(MDCRipple.createAdapter(this), { - deregisterInteractionHandler: - (type: K, handler: SpecificEventListener) => - this.nativeCb_.removeEventListener(type, handler), - isSurfaceActive: () => this.nativeCb_[MATCHES as 'matches'](':active'), + const foundation = new MDCRippleFoundation({ + ...MDCRipple.createAdapter(this), + deregisterInteractionHandler: (evtType: K, handler: SpecificEventListener) => + this.nativeCb_.removeEventListener(evtType, handler), + isSurfaceActive: () => ponyfill.matches(this.nativeCb_, ':active'), isUnbounded: () => true, - registerInteractionHandler: - (type: K, handler: SpecificEventListener) => - this.nativeCb_.addEventListener(type, handler), + registerInteractionHandler: (evtType: K, handler: SpecificEventListener) => + this.nativeCb_.addEventListener(evtType, handler), }); - const foundation = new MDCRippleFoundation(adapter); return new MDCRipple(this.root_, foundation); } diff --git a/packages/mdc-checkbox/package.json b/packages/mdc-checkbox/package.json index 6903bd632af..87e2ed16d4c 100644 --- a/packages/mdc-checkbox/package.json +++ b/packages/mdc-checkbox/package.json @@ -16,6 +16,7 @@ "dependencies": { "@material/animation": "^0.41.0", "@material/base": "^0.41.0", + "@material/dom": "^0.41.0", "@material/feature-targeting": "^0.44.0", "@material/ripple": "^0.44.0", "@material/rtl": "^0.42.0", diff --git a/packages/mdc-chips/chip-set/foundation.ts b/packages/mdc-chips/chip-set/foundation.ts index aa833fa1321..b0106e386a9 100644 --- a/packages/mdc-chips/chip-set/foundation.ts +++ b/packages/mdc-chips/chip-set/foundation.ts @@ -47,8 +47,8 @@ class MDCChipSetFoundation extends MDCFoundation { */ private selectedChipIds_: string[] = []; - constructor(adapter: MDCChipSetAdapter) { - super(Object.assign(MDCChipSetFoundation.defaultAdapter, adapter)); + constructor(adapter?: Partial) { + super({...MDCChipSetFoundation.defaultAdapter, ...adapter}); } /** diff --git a/packages/mdc-chips/chip/foundation.ts b/packages/mdc-chips/chip/foundation.ts index 4808be5f83d..6d4e2e905c8 100644 --- a/packages/mdc-chips/chip/foundation.ts +++ b/packages/mdc-chips/chip/foundation.ts @@ -68,8 +68,8 @@ class MDCChipFoundation extends MDCFoundation { */ private shouldRemoveOnTrailingIconClick_ = true; - constructor(adapter: MDCChipAdapter) { - super(Object.assign(MDCChipFoundation.defaultAdapter, adapter)); + constructor(adapter?: Partial) { + super({...MDCChipFoundation.defaultAdapter, ...adapter}); } isSelected() { @@ -103,7 +103,7 @@ class MDCChipFoundation extends MDCFoundation { // The checkmark's width is initially set to 0, so use the checkmark's height as a proxy since the checkmark // should always be square. const width = rootRect.width + checkmarkRect.height; - return Object.assign({}, rootRect, {width}); + return {...rootRect, width}; } else { return rootRect; } @@ -172,7 +172,6 @@ class MDCChipFoundation extends MDCFoundation { /** * Handles an interaction event on the trailing icon element. This is used to * prevent the ripple from activating on interaction with the trailing icon. - * @param {!Event} evt */ handleTrailingIconInteraction(evt: MouseEvent | KeyboardEvent) { const isEnter = (evt as KeyboardEvent).key === 'Enter' || (evt as KeyboardEvent).keyCode === 13; diff --git a/packages/mdc-chips/chip/index.ts b/packages/mdc-chips/chip/index.ts index e4b2195e27f..26239c5c258 100644 --- a/packages/mdc-chips/chip/index.ts +++ b/packages/mdc-chips/chip/index.ts @@ -95,10 +95,10 @@ class MDCChip extends MDCComponent implements RippleCapableSu this.trailingIcon_ = this.root_.querySelector(strings.TRAILING_ICON_SELECTOR); this.checkmark_ = this.root_.querySelector(strings.CHECKMARK_SELECTOR); - const adapter = Object.assign(MDCRipple.createAdapter(this), { + this.ripple_ = rippleFactory(this.root_, new MDCRippleFoundation({ + ...MDCRipple.createAdapter(this), computeBoundingRect: () => this.foundation_.getDimensions(), - }); - this.ripple_ = rippleFactory(this.root_, new MDCRippleFoundation(adapter)); + })); } initialSyncWithDOM() { diff --git a/packages/mdc-dialog/adapter.ts b/packages/mdc-dialog/adapter.ts index a407c912fc3..fcb5be36963 100644 --- a/packages/mdc-dialog/adapter.ts +++ b/packages/mdc-dialog/adapter.ts @@ -38,7 +38,7 @@ interface MDCDialogAdapter { isContentScrollable(): boolean; areButtonsStacked(): boolean; - getActionFromEvent(event: Event): string | null; + getActionFromEvent(evt: Event): string | null; trapFocus(): void; releaseFocus(): void; diff --git a/packages/mdc-dialog/foundation.ts b/packages/mdc-dialog/foundation.ts index 6cc0c790b3a..db36b5e5765 100644 --- a/packages/mdc-dialog/foundation.ts +++ b/packages/mdc-dialog/foundation.ts @@ -69,8 +69,8 @@ class MDCDialogFoundation extends MDCFoundation { private autoStackButtons_ = true; private areButtonsStacked_ = false; - constructor(adapter: MDCDialogAdapter) { - super(Object.assign(MDCDialogFoundation.defaultAdapter, adapter)); + constructor(adapter?: Partial) { + super({...MDCDialogFoundation.defaultAdapter, ...adapter}); } init() { diff --git a/packages/mdc-dialog/index.ts b/packages/mdc-dialog/index.ts index 52666100ac4..41456697a32 100644 --- a/packages/mdc-dialog/index.ts +++ b/packages/mdc-dialog/index.ts @@ -110,11 +110,11 @@ class MDCDialog extends MDCComponent { const LAYOUT_EVENTS = ['resize', 'orientationchange']; this.handleOpening_ = () => { - LAYOUT_EVENTS.forEach((type) => window.addEventListener(type, this.handleLayout_)); + LAYOUT_EVENTS.forEach((evtType) => window.addEventListener(evtType, this.handleLayout_)); document.addEventListener('keydown', this.handleDocumentKeydown_); }; this.handleClosing_ = () => { - LAYOUT_EVENTS.forEach((type) => window.removeEventListener(type, this.handleLayout_)); + LAYOUT_EVENTS.forEach((evtType) => window.removeEventListener(evtType, this.handleLayout_)); document.removeEventListener('keydown', this.handleDocumentKeydown_); }; @@ -154,11 +154,11 @@ class MDCDialog extends MDCComponent { areButtonsStacked: () => util.areTopsMisaligned(this.buttons_), clickDefaultButton: () => this.defaultButton_ && this.defaultButton_.click(), eventTargetMatches: (target, selector) => target ? matches(target as Element, selector) : false, - getActionFromEvent: (event: Event) => { - if (!event.target) { + getActionFromEvent: (evt: Event) => { + if (!evt.target) { return ''; } - const element = closest(event.target as Element, `[${strings.ACTION_ATTRIBUTE}]`); + const element = closest(evt.target as Element, `[${strings.ACTION_ATTRIBUTE}]`); return element && element.getAttribute(strings.ACTION_ATTRIBUTE); }, hasClass: (className) => this.root_.classList.contains(className), diff --git a/packages/mdc-floating-label/adapter.ts b/packages/mdc-floating-label/adapter.ts index 5203820b780..06427d70a8a 100644 --- a/packages/mdc-floating-label/adapter.ts +++ b/packages/mdc-floating-label/adapter.ts @@ -21,7 +21,7 @@ * THE SOFTWARE. */ -import {EventType, SpecificEventListener} from '@material/base'; +import {EventType, SpecificEventListener} from '@material/base/index'; /** * Defines the shape of the adapter expected by the foundation. @@ -49,12 +49,12 @@ interface MDCFloatingLabelAdapter { /** * Registers an event listener on the root element for a given event. */ - registerInteractionHandler(evtType: E, handler: SpecificEventListener): void; + registerInteractionHandler(evtType: K, handler: SpecificEventListener): void; /** * Deregisters an event listener on the root element for a given event. */ - deregisterInteractionHandler(evtType: E, handler: SpecificEventListener): void; + deregisterInteractionHandler(evtType: K, handler: SpecificEventListener): void; } export {MDCFloatingLabelAdapter as default, MDCFloatingLabelAdapter}; diff --git a/packages/mdc-floating-label/foundation.ts b/packages/mdc-floating-label/foundation.ts index 0450c136b1c..e6782d8d853 100644 --- a/packages/mdc-floating-label/foundation.ts +++ b/packages/mdc-floating-label/foundation.ts @@ -21,8 +21,8 @@ * THE SOFTWARE. */ -import {SpecificEventListener} from '@material/base'; import {MDCFoundation} from '@material/base/foundation'; +import {SpecificEventListener} from '@material/base/index'; import {MDCFloatingLabelAdapter} from './adapter'; import {cssClasses} from './constants'; @@ -48,7 +48,7 @@ class MDCFloatingLabelFoundation extends MDCFoundation private readonly shakeAnimationEndHandler_: SpecificEventListener<'animationend'>; - constructor(adapter: Partial = {}) { + constructor(adapter?: Partial) { super({...MDCFloatingLabelFoundation.defaultAdapter, ...adapter}); this.shakeAnimationEndHandler_ = () => this.handleShakeAnimationEnd_(); diff --git a/packages/mdc-form-field/adapter.ts b/packages/mdc-form-field/adapter.ts index a62c5e8947f..fa47c6908fd 100644 --- a/packages/mdc-form-field/adapter.ts +++ b/packages/mdc-form-field/adapter.ts @@ -21,11 +21,10 @@ * THE SOFTWARE. */ +import {EventType, SpecificEventListener} from '@material/base/index'; + /** - * Adapter for MDC Form Field. Provides an interface for managing - * - event handlers - * - ripple activation - * + * Defines the shape of the adapter expected by the foundation. * Implement this adapter for your framework of choice to delegate updates to * the component in your framework of choice. See architecture documentation * for more details. @@ -34,12 +33,8 @@ interface MDCFormFieldAdapter { activateInputRipple(): void; deactivateInputRipple(): void; - deregisterInteractionHandler( - type: K, handler: (evt: GlobalEventHandlersEventMap[K], - ) => void): void; - registerInteractionHandler( - type: K, handler: (evt: GlobalEventHandlersEventMap[K], - ) => void): void; + deregisterInteractionHandler(evtType: K, handler: SpecificEventListener): void; + registerInteractionHandler(evtType: K, handler: SpecificEventListener): void; } export {MDCFormFieldAdapter as default, MDCFormFieldAdapter}; diff --git a/packages/mdc-form-field/foundation.ts b/packages/mdc-form-field/foundation.ts index bdd6cd3c5ea..5ebe2553c29 100644 --- a/packages/mdc-form-field/foundation.ts +++ b/packages/mdc-form-field/foundation.ts @@ -43,12 +43,11 @@ class MDCFormFieldFoundation extends MDCFoundation { }; } - private clickHandler_: () => void; + private readonly clickHandler_: () => void; - constructor(adapter: MDCFormFieldAdapter) { - super(Object.assign(MDCFormFieldFoundation.defaultAdapter, adapter)); + constructor(adapter?: Partial) { + super({...MDCFormFieldFoundation.defaultAdapter, ...adapter}); - /** @private {!EventListener} */ this.clickHandler_ = () => this.handleClick_(); } diff --git a/packages/mdc-form-field/index.ts b/packages/mdc-form-field/index.ts index e558c1b3ee9..b64e2366ace 100644 --- a/packages/mdc-form-field/index.ts +++ b/packages/mdc-form-field/index.ts @@ -57,8 +57,16 @@ class MDCFormField extends MDCComponent { this.input_.ripple.deactivate(); } }, - deregisterInteractionHandler: (type, handler) => this.label_ && this.label_.removeEventListener(type, handler), - registerInteractionHandler: (type, handler) => this.label_ && this.label_.addEventListener(type, handler), + deregisterInteractionHandler: (evtType, handler) => { + if (this.label_) { + this.label_.removeEventListener(evtType, handler); + } + }, + registerInteractionHandler: (evtType, handler) => { + if (this.label_) { + this.label_.addEventListener(evtType, handler); + } + }, }); } } diff --git a/packages/mdc-grid-list/foundation.ts b/packages/mdc-grid-list/foundation.ts index 0b512a64fc7..c76cf37b1e6 100644 --- a/packages/mdc-grid-list/foundation.ts +++ b/packages/mdc-grid-list/foundation.ts @@ -44,8 +44,10 @@ class MDCGridListFoundation extends MDCFoundation { private readonly resizeHandler_: EventListener; private resizeFrame_ = 0; - constructor(adapter: MDCGridListAdapter) { - super(Object.assign(MDCGridListFoundation.defaultAdapter, adapter)); + /* istanbul ignore next: optional argument is not a branch statement */ + constructor(adapter?: Partial) { + super({...MDCGridListFoundation.defaultAdapter, ...adapter}); + this.resizeHandler_ = this.alignCenter.bind(this); } diff --git a/packages/mdc-icon-button/foundation.ts b/packages/mdc-icon-button/foundation.ts index 9f4a39996f5..10d2de9aac3 100644 --- a/packages/mdc-icon-button/foundation.ts +++ b/packages/mdc-icon-button/foundation.ts @@ -44,8 +44,8 @@ class MDCIconButtonToggleFoundation extends MDCFoundation) { + super({...MDCIconButtonToggleFoundation.defaultAdapter, ...adapter}); } init() { diff --git a/packages/mdc-line-ripple/adapter.ts b/packages/mdc-line-ripple/adapter.ts index cf462a4f8d0..fad35980e40 100644 --- a/packages/mdc-line-ripple/adapter.ts +++ b/packages/mdc-line-ripple/adapter.ts @@ -51,12 +51,12 @@ interface MDCLineRippleAdapter { /** * Registers an event listener on the line ripple element for a given event. */ - registerEventHandler(evtType: E, handler: SpecificEventListener): void; + registerEventHandler(evtType: K, handler: SpecificEventListener): void; /** * Deregisters an event listener on the line ripple element for a given event. */ - deregisterEventHandler(evtType: E, handler: SpecificEventListener): void; + deregisterEventHandler(evtType: K, handler: SpecificEventListener): void; } export {MDCLineRippleAdapter as default, MDCLineRippleAdapter}; diff --git a/packages/mdc-line-ripple/foundation.ts b/packages/mdc-line-ripple/foundation.ts index 8e9c0de1961..c9430d4a268 100644 --- a/packages/mdc-line-ripple/foundation.ts +++ b/packages/mdc-line-ripple/foundation.ts @@ -21,8 +21,8 @@ * THE SOFTWARE. */ -import {SpecificEventListener} from '@material/base'; import {MDCFoundation} from '@material/base/foundation'; +import {SpecificEventListener} from '@material/base/index'; import {MDCLineRippleAdapter} from './adapter'; import {cssClasses} from './constants'; @@ -49,7 +49,7 @@ class MDCLineRippleFoundation extends MDCFoundation { private readonly transitionEndHandler_: SpecificEventListener<'transitionend'>; - constructor(adapter: Partial = {}) { + constructor(adapter?: Partial) { super({...MDCLineRippleFoundation.defaultAdapter, ...adapter}); this.transitionEndHandler_ = (evt) => this.handleTransitionEnd(evt); diff --git a/packages/mdc-list/foundation.ts b/packages/mdc-list/foundation.ts index 81e8ec1a52b..3b4f4f7d37e 100644 --- a/packages/mdc-list/foundation.ts +++ b/packages/mdc-list/foundation.ts @@ -69,8 +69,8 @@ class MDCListFoundation extends MDCFoundation { private isCheckboxList_ = false; private isRadioList_ = false; - constructor(adapter: MDCListAdapter) { - super(Object.assign(MDCListFoundation.defaultAdapter, adapter)); + constructor(adapter?: Partial) { + super({...MDCListFoundation.defaultAdapter, ...adapter}); } layout() { diff --git a/packages/mdc-list/index.ts b/packages/mdc-list/index.ts index e5035b99143..cf2379589fd 100644 --- a/packages/mdc-list/index.ts +++ b/packages/mdc-list/index.ts @@ -23,7 +23,7 @@ import {MDCComponent} from '@material/base/component'; import {SpecificEventListener} from '@material/base/index'; -import * as ponyfill from '@material/dom/ponyfill'; +import {ponyfill} from '@material/dom/index'; import {cssClasses, strings} from './constants'; import {MDCListFoundation} from './foundation'; import {ListActionEventDetail, ListIndex} from './types'; diff --git a/packages/mdc-menu-surface/foundation.ts b/packages/mdc-menu-surface/foundation.ts index 6198ec39b32..e6f7f727a8d 100644 --- a/packages/mdc-menu-surface/foundation.ts +++ b/packages/mdc-menu-surface/foundation.ts @@ -105,8 +105,8 @@ class MDCMenuSurfaceFoundation extends MDCFoundation { private dimensions_!: MenuDimensions; // assigned in open() private measurements_!: AutoLayoutMeasurements; // assigned in open() - constructor(adapter: MDCMenuSurfaceAdapter) { - super(Object.assign(MDCMenuSurfaceFoundation.defaultAdapter, adapter)); + constructor(adapter?: Partial) { + super({...MDCMenuSurfaceFoundation.defaultAdapter, ...adapter}); } init() { diff --git a/packages/mdc-menu-surface/index.ts b/packages/mdc-menu-surface/index.ts index 720ee444e3b..b9c3771b592 100644 --- a/packages/mdc-menu-surface/index.ts +++ b/packages/mdc-menu-surface/index.ts @@ -132,7 +132,9 @@ class MDCMenuSurface extends MDCComponent { this.setIsHoisted(true); } - /** @param corner Default anchor corner alignment of top-left surface corner. */ + /** + * @param corner Default anchor corner alignment of top-left surface corner. + */ setAnchorCorner(corner: Corner) { this.foundation_.setAnchorCorner(corner); } diff --git a/packages/mdc-menu/foundation.ts b/packages/mdc-menu/foundation.ts index 3349a9c9a52..41443ef1ae2 100644 --- a/packages/mdc-menu/foundation.ts +++ b/packages/mdc-menu/foundation.ts @@ -58,8 +58,8 @@ class MDCMenuFoundation extends MDCFoundation { // tslint:enable:object-literal-sort-keys } - constructor(adapter: MDCMenuAdapter) { - super(Object.assign(MDCMenuFoundation.defaultAdapter, adapter)); + constructor(adapter?: Partial) { + super({...MDCMenuFoundation.defaultAdapter, ...adapter}); } destroy() { diff --git a/packages/mdc-notched-outline/foundation.ts b/packages/mdc-notched-outline/foundation.ts index c345a993c2a..e8793e4a3c4 100644 --- a/packages/mdc-notched-outline/foundation.ts +++ b/packages/mdc-notched-outline/foundation.ts @@ -52,7 +52,7 @@ class MDCNotchedOutlineFoundation extends MDCFoundation = {}) { + constructor(adapter?: Partial) { super({...MDCNotchedOutlineFoundation.defaultAdapter, ...adapter}); } diff --git a/packages/mdc-radio/index.ts b/packages/mdc-radio/index.ts index 6b78b0aa908..280ad4508a5 100644 --- a/packages/mdc-radio/index.ts +++ b/packages/mdc-radio/index.ts @@ -23,8 +23,7 @@ import {MDCComponent} from '@material/base/component'; import {EventType, SpecificEventListener} from '@material/base/index'; -import {RippleCapableSurface} from '@material/ripple/index'; -import {MDCRipple, MDCRippleFoundation} from '@material/ripple/index'; +import {MDCRipple, MDCRippleFoundation, RippleCapableSurface} from '@material/ripple/index'; import {MDCSelectionControl} from '@material/selection-control/index'; import {MDCRadioFoundation} from './foundation'; @@ -81,18 +80,17 @@ class MDCRadio extends MDCComponent implements RippleCapable } private initRipple_(): MDCRipple { - const adapter = Object.assign(MDCRipple.createAdapter(this), { - deregisterInteractionHandler: - (type: K, handler: SpecificEventListener) => - this.nativeControl_.removeEventListener(type, handler), + const foundation = new MDCRippleFoundation({ + ...MDCRipple.createAdapter(this), + deregisterInteractionHandler: (evtType: K, handler: SpecificEventListener) => + this.nativeControl_.removeEventListener(evtType, handler), // Radio buttons technically go "active" whenever there is *any* keyboard interaction. This is not the // UI we desire. isSurfaceActive: () => false, isUnbounded: () => true, - registerInteractionHandler: (type: K, handler: SpecificEventListener) => - this.nativeControl_.addEventListener(type, handler), + registerInteractionHandler: (evtType: K, handler: SpecificEventListener) => + this.nativeControl_.addEventListener(evtType, handler), }); - const foundation = new MDCRippleFoundation(adapter); return new MDCRipple(this.root_, foundation); } diff --git a/packages/mdc-ripple/foundation.ts b/packages/mdc-ripple/foundation.ts index 7aca9313e64..e855ee4010d 100644 --- a/packages/mdc-ripple/foundation.ts +++ b/packages/mdc-ripple/foundation.ts @@ -60,7 +60,7 @@ const POINTER_DEACTIVATION_EVENT_TYPES: DeactivationEventType[] = [ ]; // simultaneous nested activations -let activatedTargets: Array = []; +let activatedTargets: Array = []; class MDCRippleFoundation extends MDCFoundation { static get cssClasses(): {[key: string]: string} { @@ -75,11 +75,11 @@ class MDCRippleFoundation extends MDCFoundation { return numbers; } - static get defaultAdapter() { + static get defaultAdapter(): MDCRippleAdapter { return { addClass: () => undefined, browserSupportsCssVars: () => true, - computeBoundingRect: () => undefined, + computeBoundingRect: () => ({top: 0, right: 0, bottom: 0, left: 0, width: 0, height: 0}), containsEventTarget: () => true, deregisterDocumentInteractionHandler: () => undefined, deregisterInteractionHandler: () => undefined, @@ -96,53 +96,40 @@ class MDCRippleFoundation extends MDCFoundation { }; } - private layoutFrame_: number; - private frame_: { - width: number, - height: number, - }; + private activationAnimationHasEnded_ = false; private activationState_: ActivationStateType; - private initialSize_: number; - private maxRadius_: number; - private activateHandler_: EventHandlerNonNull; - private deactivateHandler_: EventHandlerNonNull; - private focusHandler_: EventHandlerNonNull; - private blurHandler_: EventHandlerNonNull; - private resizeHandler_: EventHandlerNonNull; - - private unboundedCoords_: Coordinates; - private fgScale_: string; - private activationTimer_: number; - private fgDeactivationRemovalTimer_: number; - private activationAnimationHasEnded_: boolean; - private activationTimerCallback_: () => void; + private activationTimer_ = 0; + private fgDeactivationRemovalTimer_ = 0; + private fgScale_ = '0'; + private frame_ = {width: 0, height: 0}; + private initialSize_ = 0; + private layoutFrame_ = 0; + private maxRadius_ = 0; + private unboundedCoords_: Coordinates = {left: 0, top: 0}; + + private readonly activationTimerCallback_: () => void; + private readonly activateHandler_: EventHandlerNonNull; + private readonly deactivateHandler_: EventHandlerNonNull; + private readonly focusHandler_: EventHandlerNonNull; + private readonly blurHandler_: EventHandlerNonNull; + private readonly resizeHandler_: EventHandlerNonNull; + private previousActivationEvent_?: Event; - constructor(adapter: MDCRippleAdapter) { - super(Object.assign(MDCRippleFoundation.defaultAdapter, adapter)); + constructor(adapter?: Partial) { + super({...MDCRippleFoundation.defaultAdapter, ...adapter}); - this.layoutFrame_ = 0; - this.frame_ = ({width: 0, height: 0}); this.activationState_ = this.defaultActivationState_(); - this.initialSize_ = 0; - this.maxRadius_ = 0; + + this.activationTimerCallback_ = () => { + this.activationAnimationHasEnded_ = true; + this.runDeactivationUXLogicIfReady_(); + }; this.activateHandler_ = (e) => this.activate_(e); this.deactivateHandler_ = () => this.deactivate_(); this.focusHandler_ = () => this.handleFocus(); this.blurHandler_ = () => this.handleBlur(); this.resizeHandler_ = () => this.layout(); - this.unboundedCoords_ = { - left: 0, - top: 0, - }; - this.fgScale_ = '0'; - this.activationTimer_ = 0; - this.fgDeactivationRemovalTimer_ = 0; - this.activationAnimationHasEnded_ = false; - this.activationTimerCallback_ = () => { - this.activationAnimationHasEnded_ = true; - this.runDeactivationUXLogicIfReady_(); - }; } init() { @@ -163,7 +150,6 @@ class MDCRippleFoundation extends MDCFoundation { } } - /** @override */ destroy() { if (this.supportsPressRipple_()) { if (this.activationTimer_) { @@ -189,11 +175,12 @@ class MDCRippleFoundation extends MDCFoundation { this.deregisterRootHandlers_(); this.deregisterDeactivationHandlers_(); } + /** - * event Optional event containing position information. + * @param evt Optional event containing position information. */ - activate(event?: Event): void { - this.activate_(event); + activate(evt?: Event): void { + this.activate_(evt); } deactivate(): void { @@ -255,8 +242,8 @@ class MDCRippleFoundation extends MDCFoundation { */ private registerRootHandlers_(supportsPressRipple: boolean) { if (supportsPressRipple) { - ACTIVATION_EVENT_TYPES.forEach((type) => { - this.adapter_.registerInteractionHandler(type, this.activateHandler_); + ACTIVATION_EVENT_TYPES.forEach((evtType) => { + this.adapter_.registerInteractionHandler(evtType, this.activateHandler_); }); if (this.adapter_.isUnbounded()) { this.adapter_.registerResizeHandler(this.resizeHandler_); @@ -267,19 +254,19 @@ class MDCRippleFoundation extends MDCFoundation { this.adapter_.registerInteractionHandler('blur', this.blurHandler_); } - private registerDeactivationHandlers_(e: Event) { - if (e.type === 'keydown') { + private registerDeactivationHandlers_(evt: Event) { + if (evt.type === 'keydown') { this.adapter_.registerInteractionHandler('keyup', this.deactivateHandler_); } else { - POINTER_DEACTIVATION_EVENT_TYPES.forEach((type) => { - this.adapter_.registerDocumentInteractionHandler(type, this.deactivateHandler_); + POINTER_DEACTIVATION_EVENT_TYPES.forEach((evtType) => { + this.adapter_.registerDocumentInteractionHandler(evtType, this.deactivateHandler_); }); } } private deregisterRootHandlers_() { - ACTIVATION_EVENT_TYPES.forEach((type) => { - this.adapter_.deregisterInteractionHandler(type, this.activateHandler_); + ACTIVATION_EVENT_TYPES.forEach((evtType) => { + this.adapter_.deregisterInteractionHandler(evtType, this.activateHandler_); }); this.adapter_.deregisterInteractionHandler('focus', this.focusHandler_); this.adapter_.deregisterInteractionHandler('blur', this.blurHandler_); @@ -291,21 +278,21 @@ class MDCRippleFoundation extends MDCFoundation { private deregisterDeactivationHandlers_() { this.adapter_.deregisterInteractionHandler('keyup', this.deactivateHandler_); - POINTER_DEACTIVATION_EVENT_TYPES.forEach((type) => { - this.adapter_.deregisterDocumentInteractionHandler(type, this.deactivateHandler_); + POINTER_DEACTIVATION_EVENT_TYPES.forEach((evtType) => { + this.adapter_.deregisterDocumentInteractionHandler(evtType, this.deactivateHandler_); }); } private removeCssVars_() { const rippleStrings = MDCRippleFoundation.strings; - Object.keys(rippleStrings).forEach((k) => { - if (k.indexOf('VAR_') === 0) { - this.adapter_.updateCssVariable(rippleStrings[k], null); + Object.keys(rippleStrings).forEach((key) => { + if (key.indexOf('VAR_') === 0) { + this.adapter_.updateCssVariable(rippleStrings[key], null); } }); } - private activate_(e?: Event) { + private activate_(evt?: Event) { if (this.adapter_.isSurfaceDisabled()) { return; } @@ -317,19 +304,19 @@ class MDCRippleFoundation extends MDCFoundation { // Avoid reacting to follow-on events fired by touch device after an already-processed user interaction const previousActivationEvent = this.previousActivationEvent_; - const isSameInteraction = previousActivationEvent && e !== undefined && previousActivationEvent.type !== e.type; + const isSameInteraction = previousActivationEvent && evt !== undefined && previousActivationEvent.type !== evt.type; if (isSameInteraction) { return; } activationState.isActivated = true; - activationState.isProgrammatic = e === undefined; - activationState.activationEvent = e; - activationState.wasActivatedByPointer = activationState.isProgrammatic ? false : e !== undefined && ( - e.type === 'mousedown' || e.type === 'touchstart' || e.type === 'pointerdown' + activationState.isProgrammatic = evt === undefined; + activationState.activationEvent = evt; + activationState.wasActivatedByPointer = activationState.isProgrammatic ? false : evt !== undefined && ( + evt.type === 'mousedown' || evt.type === 'touchstart' || evt.type === 'pointerdown' ); - const hasActivatedChild = e !== undefined && activatedTargets.length > 0 && activatedTargets.some( + const hasActivatedChild = evt !== undefined && activatedTargets.length > 0 && activatedTargets.some( (target) => this.adapter_.containsEventTarget(target)); if (hasActivatedChild) { // Immediately reset activation state, while preserving logic that prevents touch follow-on events @@ -337,12 +324,12 @@ class MDCRippleFoundation extends MDCFoundation { return; } - if (e !== undefined) { - activatedTargets.push(e.target); - this.registerDeactivationHandlers_(e); + if (evt !== undefined) { + activatedTargets.push(evt.target); + this.registerDeactivationHandlers_(evt); } - activationState.wasElementMadeActive = this.checkElementMadeActive_(e); + activationState.wasElementMadeActive = this.checkElementMadeActive_(evt); if (activationState.wasElementMadeActive) { this.animateActivation_(); } @@ -352,15 +339,15 @@ class MDCRippleFoundation extends MDCFoundation { activatedTargets = []; if (!activationState.wasElementMadeActive - && e !== undefined - && ((e as KeyboardEvent).key === ' ' || (e as KeyboardEvent).keyCode === 32)) { + && evt !== undefined + && ((evt as KeyboardEvent).key === ' ' || (evt as KeyboardEvent).keyCode === 32)) { // If space was pressed, try again within an rAF call to detect :active, because different UAs report // active states inconsistently when they're called within event handling code: // - https://bugs.chromium.org/p/chromium/issues/detail?id=635971 // - https://bugzilla.mozilla.org/show_bug.cgi?id=1293741 // We try first outside rAF to support Edge, which does not exhibit this problem, but will crash if a CSS // variable is set within a rAF callback for a submit button interaction (#2241). - activationState.wasElementMadeActive = this.checkElementMadeActive_(e); + activationState.wasElementMadeActive = this.checkElementMadeActive_(evt); if (activationState.wasElementMadeActive) { this.animateActivation_(); } @@ -373,8 +360,8 @@ class MDCRippleFoundation extends MDCFoundation { }); } - private checkElementMadeActive_(e?: Event) { - return (e !== undefined && e.type === 'keydown') ? this.adapter_.isSurfaceActive() : true; + private checkElementMadeActive_(evt?: Event) { + return (evt !== undefined && evt.type === 'keydown') ? this.adapter_.isSurfaceActive() : true; } private animateActivation_() { @@ -475,7 +462,7 @@ class MDCRippleFoundation extends MDCFoundation { return; } - const state = /** @type {!ActivationStateType} */ (Object.assign({}, activationState)); + const state: ActivationStateType = {...activationState}; if (activationState.isProgrammatic) { requestAnimationFrame(() => this.animateDeactivation_(state)); diff --git a/packages/mdc-ripple/index.ts b/packages/mdc-ripple/index.ts index 84bd962dc73..d0c51d010f8 100644 --- a/packages/mdc-ripple/index.ts +++ b/packages/mdc-ripple/index.ts @@ -22,6 +22,7 @@ */ import {MDCComponent} from '@material/base/component'; +import {ponyfill} from '@material/dom/index'; import {MDCRippleAdapter} from './adapter'; import {MDCRippleFoundation} from './foundation'; import {RippleAttachOpts, RippleCapableSurface} from './types'; @@ -38,8 +39,6 @@ class MDCRipple extends MDCComponent implements RippleCapab } static createAdapter(instance: RippleCapableSurface): MDCRippleAdapter { - const MATCHES = util.getMatchesProperty(HTMLElement.prototype); - return { addClass: (className) => instance.root_.classList.add(className), browserSupportsCssVars: () => util.supportsCssVariables(window), @@ -51,10 +50,7 @@ class MDCRipple extends MDCComponent implements RippleCapab instance.root_.removeEventListener(evtType, handler, util.applyPassive()), deregisterResizeHandler: (handler) => window.removeEventListener('resize', handler), getWindowPageOffset: () => ({x: window.pageXOffset, y: window.pageYOffset}), - isSurfaceActive: () => { - const root = instance.root_; - return root[MATCHES as 'matches'](':active'); - }, + isSurfaceActive: () => ponyfill.matches(instance.root_, ':active'), isSurfaceDisabled: () => Boolean(instance.disabled), isUnbounded: () => Boolean(instance.unbounded), registerDocumentInteractionHandler: (evtType, handler) => @@ -67,12 +63,11 @@ class MDCRipple extends MDCComponent implements RippleCapab }; } + // Public visibility for this property is required by RippleCapableSurface. + root_!: Element; // assigned in MDCComponent constructor + disabled = false; - /** - * this line may seem redundent, but without this the TS compiler does not - * think that `this` is of type RippleCapableSurface - */ - root_!: Element; + private unbounded_?: boolean; get unbounded(): boolean { @@ -114,7 +109,6 @@ class MDCRipple extends MDCComponent implements RippleCapab private setUnbounded_() { this.foundation_.setUnbounded(Boolean(this.unbounded_)); } - } export {MDCRipple as default, MDCRipple, util}; diff --git a/packages/mdc-ripple/package.json b/packages/mdc-ripple/package.json index d6c1e5b34d5..a560887b24e 100644 --- a/packages/mdc-ripple/package.json +++ b/packages/mdc-ripple/package.json @@ -16,6 +16,7 @@ "dependencies": { "@material/animation": "^0.41.0", "@material/base": "^0.41.0", + "@material/dom": "^0.41.0", "@material/feature-targeting": "^0.44.0", "@material/theme": "^0.43.0" } diff --git a/packages/mdc-ripple/util.ts b/packages/mdc-ripple/util.ts index dcf88d08af5..279e25f7abd 100644 --- a/packages/mdc-ripple/util.ts +++ b/packages/mdc-ripple/util.ts @@ -111,11 +111,8 @@ export type VendorMatchesFunctionName = 'webkitMatchesSelector' | 'msMatchesSele export type MatchesFunctionName = VendorMatchesFunctionName | 'matches'; export function getMatchesProperty(htmlElementPrototype: {}): MatchesFunctionName { - /** - * Order is important because we return the first existing method we find. - * Do not change the order of the items in the below array. - */ - + // Order is important because we return the first existing method we find. + // Do not change the order of the items in the below array. const matchesMethods: MatchesFunctionName[] = ['matches', 'webkitMatchesSelector', 'msMatchesSelector']; let method: MatchesFunctionName = 'matches'; for (const matchesMethod of matchesMethods) { @@ -128,9 +125,8 @@ export function getMatchesProperty(htmlElementPrototype: {}): MatchesFunctionNam return method; } -export function getNormalizedEventCoords( - ev: Event | undefined, pageOffset: Point, clientRect: ClientRect): Point { - if (!ev) { +export function getNormalizedEventCoords(evt: Event | undefined, pageOffset: Point, clientRect: ClientRect): Point { + if (!evt) { return {x: 0, y: 0}; } const {x, y} = pageOffset; @@ -140,12 +136,12 @@ export function getNormalizedEventCoords( let normalizedX; let normalizedY; // Determine touch point relative to the ripple container. - if (ev.type === 'touchstart') { - const touchEvent = ev as TouchEvent; + if (evt.type === 'touchstart') { + const touchEvent = evt as TouchEvent; normalizedX = touchEvent.changedTouches[0].pageX - documentX; normalizedY = touchEvent.changedTouches[0].pageY - documentY; } else { - const mouseEvent = ev as MouseEvent; + const mouseEvent = evt as MouseEvent; normalizedX = mouseEvent.pageX - documentX; normalizedY = mouseEvent.pageY - documentY; } diff --git a/packages/mdc-slider/adapter.ts b/packages/mdc-slider/adapter.ts index 5d95ec7f3a7..797abef5ad8 100644 --- a/packages/mdc-slider/adapter.ts +++ b/packages/mdc-slider/adapter.ts @@ -21,7 +21,7 @@ * THE SOFTWARE. */ -import {EventType, SpecificEventListener} from '@material/base'; +import {EventType, SpecificEventListener} from '@material/base/index'; /** * Defines the shape of the adapter expected by the foundation. @@ -74,32 +74,32 @@ interface MDCSliderAdapter { /** * Registers an event handler on the root element for a given event. */ - registerInteractionHandler(type: E, handler: SpecificEventListener): void; + registerInteractionHandler(evtType: K, handler: SpecificEventListener): void; /** * Deregisters an event handler on the root element for a given event. */ - deregisterInteractionHandler(type: E, handler: SpecificEventListener): void; + deregisterInteractionHandler(evtType: K, handler: SpecificEventListener): void; /** * Registers an event handler on the thumb container element for a given event. */ - registerThumbContainerInteractionHandler(type: E, handler: SpecificEventListener): void; + registerThumbContainerInteractionHandler(evtType: K, handler: SpecificEventListener): void; /** * Deregisters an event handler on the thumb container element for a given event. */ - deregisterThumbContainerInteractionHandler(type: E, handler: SpecificEventListener): void; + deregisterThumbContainerInteractionHandler(evtType: K, handler: SpecificEventListener): void; /** * Registers an event handler on the body for a given event. */ - registerBodyInteractionHandler(type: E, handler: SpecificEventListener): void; + registerBodyInteractionHandler(evtType: K, handler: SpecificEventListener): void; /** * Deregisters an event handler on the body for a given event. */ - deregisterBodyInteractionHandler(type: E, handler: SpecificEventListener): void; + deregisterBodyInteractionHandler(evtType: K, handler: SpecificEventListener): void; /** * Registers an event handler for the window resize event diff --git a/packages/mdc-slider/foundation.ts b/packages/mdc-slider/foundation.ts index 29e98cedab5..85509fa064d 100644 --- a/packages/mdc-slider/foundation.ts +++ b/packages/mdc-slider/foundation.ts @@ -128,7 +128,7 @@ class MDCSliderFoundation extends MDCFoundation { private readonly blurHandler_: SpecificEventListener<'blur'>; private readonly resizeHandler_: SpecificEventListener<'resize'>; - constructor(adapter: Partial = {}) { + constructor(adapter?: Partial) { super({...MDCSliderFoundation.defaultAdapter, ...adapter}); this.thumbContainerPointerHandler_ = () => this.handlingThumbTargetEvt_ = true; diff --git a/packages/mdc-slider/index.ts b/packages/mdc-slider/index.ts index 3fbf3ab2644..f991880180a 100644 --- a/packages/mdc-slider/index.ts +++ b/packages/mdc-slider/index.ts @@ -95,16 +95,16 @@ class MDCSlider extends MDCComponent { removeAttribute: (name) => this.root_.removeAttribute(name), computeBoundingRect: () => this.root_.getBoundingClientRect(), getTabIndex: () => this.root_.tabIndex, - registerInteractionHandler: (type, handler) => this.root_.addEventListener(type, handler), - deregisterInteractionHandler: (type, handler) => this.root_.removeEventListener(type, handler), - registerThumbContainerInteractionHandler: (type, handler) => { - this.thumbContainer_.addEventListener(type, handler); + registerInteractionHandler: (evtType, handler) => this.root_.addEventListener(evtType, handler), + deregisterInteractionHandler: (evtType, handler) => this.root_.removeEventListener(evtType, handler), + registerThumbContainerInteractionHandler: (evtType, handler) => { + this.thumbContainer_.addEventListener(evtType, handler); }, - deregisterThumbContainerInteractionHandler: (type, handler) => { - this.thumbContainer_.removeEventListener(type, handler); + deregisterThumbContainerInteractionHandler: (evtType, handler) => { + this.thumbContainer_.removeEventListener(evtType, handler); }, - registerBodyInteractionHandler: (type, handler) => document.body.addEventListener(type, handler), - deregisterBodyInteractionHandler: (type, handler) => document.body.removeEventListener(type, handler), + registerBodyInteractionHandler: (evtType, handler) => document.body.addEventListener(evtType, handler), + deregisterBodyInteractionHandler: (evtType, handler) => document.body.removeEventListener(evtType, handler), registerResizeHandler: (handler) => window.addEventListener('resize', handler), deregisterResizeHandler: (handler) => window.removeEventListener('resize', handler), notifyInput: () => this.emit(strings.INPUT_EVENT, this), diff --git a/packages/mdc-snackbar/foundation.ts b/packages/mdc-snackbar/foundation.ts index adf3c7cff12..e2d9931ce5c 100644 --- a/packages/mdc-snackbar/foundation.ts +++ b/packages/mdc-snackbar/foundation.ts @@ -60,8 +60,8 @@ class MDCSnackbarFoundation extends MDCFoundation { private autoDismissTimeoutMs_ = numbers.DEFAULT_AUTO_DISMISS_TIMEOUT_MS; private closeOnEscape_ = true; - constructor(adapter?: MDCSnackbarAdapter) { - super(Object.assign(MDCSnackbarFoundation.defaultAdapter, adapter)); + constructor(adapter?: Partial) { + super({...MDCSnackbarFoundation.defaultAdapter, ...adapter}); } destroy() { diff --git a/packages/mdc-snackbar/index.ts b/packages/mdc-snackbar/index.ts index 204ab5b9041..78875bea30c 100644 --- a/packages/mdc-snackbar/index.ts +++ b/packages/mdc-snackbar/index.ts @@ -21,9 +21,9 @@ * THE SOFTWARE. */ -import {SpecificEventListener} from '@material/base'; import {MDCComponent} from '@material/base/component'; -import * as ponyfill from '@material/dom/ponyfill'; +import {SpecificEventListener} from '@material/base/index'; +import {ponyfill} from '@material/dom/index'; import {strings} from './constants'; import {MDCSnackbarFoundation} from './foundation'; import {Announcer, AnnouncerFactory} from './types'; diff --git a/packages/mdc-switch/foundation.ts b/packages/mdc-switch/foundation.ts index c46e9e4b856..19bdd92e842 100644 --- a/packages/mdc-switch/foundation.ts +++ b/packages/mdc-switch/foundation.ts @@ -52,8 +52,8 @@ class MDCSwitchFoundation extends MDCFoundation { }; } - constructor(adapter: MDCSwitchAdapter) { - super(Object.assign(MDCSwitchFoundation.defaultAdapter, adapter)); + constructor(adapter?: Partial) { + super({...MDCSwitchFoundation.defaultAdapter, ...adapter}); } /** Sets the checked state of the switch. */ diff --git a/packages/mdc-switch/index.ts b/packages/mdc-switch/index.ts index a0627d2cd9d..593a666b2d1 100644 --- a/packages/mdc-switch/index.ts +++ b/packages/mdc-switch/index.ts @@ -22,8 +22,9 @@ */ import {MDCComponent} from '@material/base/component'; +import {EventType} from '@material/base/index'; +import {ponyfill} from '@material/dom/index'; import {MDCRipple, MDCRippleFoundation, RippleCapableSurface} from '@material/ripple/index'; -import {getMatchesProperty} from '@material/ripple/util'; import {MDCSelectionControl} from '@material/selection-control/index'; import {MDCSwitchFoundation} from './foundation'; @@ -33,13 +34,12 @@ import {MDCSwitchFoundation} from './foundation'; * https://material.io/design/components/selection-controls.html#switches */ class MDCSwitch extends MDCComponent implements MDCSelectionControl, RippleCapableSurface { - /** Creates an instance of MDCSwitch bound to the given root element. */ static attachTo(root: HTMLElement) { return new MDCSwitch(root); } - // Initialized in super class constructor, re-declared as public to fulfill to the `RippleCapableSurface` interface. - root_!: Element; + // Public visibility for this property is required by RippleCapableSurface. + root_!: Element; // assigned in MDCComponent constructor private ripple_ = this.initRipple_(); @@ -62,7 +62,6 @@ class MDCSwitch extends MDCComponent implements MDCSelectio this.checked = this.checked; } - /** Gets the default Foundation for this switch. */ getDefaultFoundation() { return new MDCSwitchFoundation({ addClass: (className: string) => this.root_.classList.add(className), @@ -72,23 +71,22 @@ class MDCSwitch extends MDCComponent implements MDCSelectio }); } - /** The MDCRipple associated with this switch. */ get ripple() { return this.ripple_; } - /** The checked state of this switch. */ get checked() { return this.nativeControl_.checked; } + set checked(checked) { this.foundation_.setChecked(checked); } - /** The disabled state of this switch. */ get disabled() { return this.nativeControl_.disabled; } + set disabled(disabled) { this.foundation_.setDisabled(disabled); } @@ -97,25 +95,25 @@ class MDCSwitch extends MDCComponent implements MDCSelectio const {RIPPLE_SURFACE_SELECTOR} = MDCSwitchFoundation.strings; const rippleSurface = this.root_.querySelector(RIPPLE_SURFACE_SELECTOR) as HTMLElement; - const MATCHES = getMatchesProperty(HTMLElement.prototype); - const adapter = Object.assign(MDCRipple.createAdapter(this), { + return new MDCRipple(this.root_, new MDCRippleFoundation({ + ...MDCRipple.createAdapter(this), addClass: (className: string) => rippleSurface.classList.add(className), computeBoundingRect: () => rippleSurface.getBoundingClientRect(), - deregisterInteractionHandler: (type: string, handler: EventListener) => - this.nativeControl_.removeEventListener(type, handler), - isSurfaceActive: () => this.nativeControl_[MATCHES]!(':active'), + deregisterInteractionHandler: (evtType: EventType, handler: EventListener) => { + this.nativeControl_.removeEventListener(evtType, handler); + }, + isSurfaceActive: () => ponyfill.matches(this.nativeControl_, ':active'), isUnbounded: () => true, - registerInteractionHandler: (type: string, handler: EventListener) => - this.nativeControl_.addEventListener(type, handler), + registerInteractionHandler: (evtType: EventType, handler: EventListener) => { + this.nativeControl_.addEventListener(evtType, handler); + }, removeClass: (className: string) => rippleSurface.classList.remove(className), - updateCssVariable: (varName: string, value: string) => - rippleSurface.style.setProperty(varName, value), - }); - const foundation = new MDCRippleFoundation(adapter); - return new MDCRipple(this.root_, foundation); + updateCssVariable: (varName: string, value: string) => { + rippleSurface.style.setProperty(varName, value); + }, + })); } - /** Returns the state of the native control element. */ private get nativeControl_() { const {NATIVE_CONTROL_SELECTOR} = MDCSwitchFoundation.strings; return this.root_.querySelector(NATIVE_CONTROL_SELECTOR) as HTMLInputElement; diff --git a/packages/mdc-switch/package.json b/packages/mdc-switch/package.json index a222557bf83..87045e1e1e3 100644 --- a/packages/mdc-switch/package.json +++ b/packages/mdc-switch/package.json @@ -16,6 +16,7 @@ "dependencies": { "@material/animation": "^0.41.0", "@material/base": "^0.41.0", + "@material/dom": "^0.41.0", "@material/elevation": "^0.44.0", "@material/feature-targeting": "^0.44.0", "@material/ripple": "^0.44.0", diff --git a/test/unit/mdc-checkbox/mdc-checkbox.test.js b/test/unit/mdc-checkbox/mdc-checkbox.test.js index 0e8c33ff7bc..cc5cf206a99 100644 --- a/test/unit/mdc-checkbox/mdc-checkbox.test.js +++ b/test/unit/mdc-checkbox/mdc-checkbox.test.js @@ -31,7 +31,7 @@ import {supportsCssVariables} from '../../../packages/mdc-ripple/util'; import {MDCCheckbox, MDCCheckboxFoundation} from '../../../packages/mdc-checkbox/index'; import {MDCRipple} from '../../../packages/mdc-ripple/index'; import {strings} from '../../../packages/mdc-checkbox/constants'; -import {getMatchesProperty} from '../../../packages/mdc-ripple/util'; +import {ponyfill} from '../../../packages/mdc-dom/index'; function getFixture() { return bel` @@ -95,15 +95,20 @@ if (supportsCssVariables(window)) { const input = root.querySelector('input'); clock.runToFrame(); + const realMatches = ponyfill.matches; const fakeMatches = td.func('.matches'); - td.when(fakeMatches(':active')).thenReturn(true); - input[getMatchesProperty(HTMLElement.prototype)] = fakeMatches; - - assert.isTrue(root.classList.contains('mdc-ripple-upgraded')); - domEvents.emit(input, 'keydown'); - clock.runToFrame(); - - assert.isTrue(root.classList.contains('mdc-ripple-upgraded--foreground-activation')); + td.when(fakeMatches(td.matchers.isA(Element), ':active')).thenReturn(true); + ponyfill.matches = fakeMatches; + + try { + assert.isTrue(root.classList.contains('mdc-ripple-upgraded')); + domEvents.emit(input, 'keydown'); + clock.runToFrame(); + + assert.isTrue(root.classList.contains('mdc-ripple-upgraded--foreground-activation')); + } finally { + ponyfill.matches = realMatches; + } }); } diff --git a/test/unit/mdc-ripple/mdc-ripple.test.js b/test/unit/mdc-ripple/mdc-ripple.test.js index e8d32b6f967..8bb6d157e5d 100644 --- a/test/unit/mdc-ripple/mdc-ripple.test.js +++ b/test/unit/mdc-ripple/mdc-ripple.test.js @@ -30,6 +30,7 @@ import {MDCRipple} from '../../../packages/mdc-ripple/index'; import {cssClasses} from '../../../packages/mdc-ripple/constants'; import * as util from '../../../packages/mdc-ripple/util'; import {install as installClock} from '../helpers/clock'; +import {ponyfill} from '../../../packages/mdc-dom/index'; suite('MDCRipple'); @@ -114,16 +115,21 @@ test('adapter#browserSupportsCssVars delegates to util', () => { test('adapter#isUnbounded delegates to unbounded getter', () => { const {component} = setupTest(); component.unbounded = true; - assert.isOk(component.getDefaultFoundation().adapter_.isUnbounded()); + assert.isTrue(component.getDefaultFoundation().adapter_.isUnbounded()); }); test('adapter#isSurfaceActive calls the correct :matches API method on the root element', () => { - const {root, component} = setupTest(); - const MATCHES = util.getMatchesProperty(HTMLElement.prototype); - const matches = td.func('root.'); - td.when(matches(':active')).thenReturn(true); - root[MATCHES] = matches; - assert.isOk(component.getDefaultFoundation().adapter_.isSurfaceActive()); + const {component} = setupTest(); + const realMatches = ponyfill.matches; + const fakeMatches = td.func('.matches'); + td.when(fakeMatches(td.matchers.isA(Element), ':active')).thenReturn(true); + ponyfill.matches = fakeMatches; + + try { + assert.isTrue(component.getDefaultFoundation().adapter_.isSurfaceActive()); + } finally { + ponyfill.matches = realMatches; + } }); test('adapter#isSurfaceDisabled delegates to component\'s disabled getter', () => { @@ -135,14 +141,14 @@ test('adapter#isSurfaceDisabled delegates to component\'s disabled getter', () = test('adapter#addClass adds a class to the root', () => { const {root, component} = setupTest(); component.getDefaultFoundation().adapter_.addClass('foo'); - assert.isOk(root.classList.contains('foo')); + assert.isTrue(root.classList.contains('foo')); }); test('adapter#removeClass removes a class from the root', () => { const {root, component} = setupTest(); root.classList.add('foo'); component.getDefaultFoundation().adapter_.removeClass('foo'); - assert.isNotOk(root.classList.contains('foo')); + assert.isFalse(root.classList.contains('foo')); }); test('adapter#containsEventTarget returns true if the passed element is a descendant of the root element', () => {