Skip to content
This repository was archived by the owner on Jan 13, 2025. It is now read-only.

Commit 13d169d

Browse files
mmalerbakfranqueiro
authored andcommitted
feat(switch): Convert JS to TypeScript (#4320)
1 parent 8abbb53 commit 13d169d

File tree

10 files changed

+103
-124
lines changed

10 files changed

+103
-124
lines changed

packages/material-components-web/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ import * as select from '@material/select/index';
4545
import * as selectionControl from '@material/selection-control/index.ts';
4646
import * as slider from '@material/slider/index';
4747
import * as snackbar from '@material/snackbar/index';
48-
import * as switchControl from '@material/switch/index';
48+
import * as switchControl from '@material/switch/index.ts';
4949
import * as tab from '@material/tab/index';
5050
import * as tabBar from '@material/tab-bar/index';
5151
import * as tabIndicator from '@material/tab-indicator/index';

packages/mdc-base/component.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,4 @@ class MDCComponent<FoundationType extends MDCFoundation> {
114114
}
115115
}
116116

117-
export default MDCComponent;
117+
export {MDCComponent as default, MDCComponent};

packages/mdc-base/foundation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,4 @@ class MDCFoundation<AdapterType extends {} = {}> {
6262
}
6363
}
6464

65-
export default MDCFoundation;
65+
export {MDCFoundation as default, MDCFoundation};

packages/mdc-switch/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ If you are using a JavaScript framework, such as React or Angular, you can creat
162162
| `handleChange(evt: Event) => void` | Handles a change event from the native control. |
163163

164164
### `MDCSwitchFoundation` Event Handlers
165-
If wrapping the switch component it is necessary to add an event handler for native control change events that calls the `handleChange` foundation method. For an example of this, see the [MDCSwitch](index.js) component `initialSyncWithDOM` method.
165+
If wrapping the switch component it is necessary to add an event handler for native control change events that calls the `handleChange` foundation method. For an example of this, see the [MDCSwitch](index.ts) component `initialSyncWithDOM` method.
166166

167167
| Event | Element Selector | Foundation Handler |
168168
| --- | --- | --- |

packages/mdc-switch/adapter.js renamed to packages/mdc-switch/adapter.ts

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,35 +21,28 @@
2121
* THE SOFTWARE.
2222
*/
2323

24-
/* eslint no-unused-vars: [2, {"args": "none"}] */
25-
2624
/**
2725
* Adapter for MDC Switch. Provides an interface for managing
2826
* - classes
2927
* - dom
3028
*
31-
* Additionally, provides type information for the adapter to the Closure
32-
* compiler.
33-
*
3429
* Implement this adapter for your framework of choice to delegate updates to
3530
* the component in your framework of choice. See architecture documentation
3631
* for more details.
3732
* https://github.com/material-components/material-components-web/blob/master/docs/code/architecture.md
38-
*
39-
* @record
4033
*/
41-
class MDCSwitchAdapter {
42-
/** @param {string} className */
43-
addClass(className) {}
34+
interface MDCSwitchAdapter {
35+
/** Adds a CSS class to the root element. */
36+
addClass(className: string): void;
4437

45-
/** @param {string} className */
46-
removeClass(className) {}
38+
/** Removes a CSS class from the root element. */
39+
removeClass(className: string): void;
4740

48-
/** @param {boolean} checked */
49-
setNativeControlChecked(checked) {}
41+
/** Sets checked state of the native HTML control underlying the switch. */
42+
setNativeControlChecked(checked: boolean): void;
5043

51-
/** @param {boolean} disabled */
52-
setNativeControlDisabled(disabled) {}
44+
/** Sets the disabled state of the native HTML control underlying the switch. */
45+
setNativeControlDisabled(disabled: boolean): void;
5346
}
5447

55-
export default MDCSwitchAdapter;
48+
export {MDCSwitchAdapter as default, MDCSwitchAdapter};

packages/mdc-switch/constants.js renamed to packages/mdc-switch/constants.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,20 @@
2121
* THE SOFTWARE.
2222
*/
2323

24-
/** @enum {string} */
24+
/** CSS classes used by the switch. */
2525
const cssClasses = {
26+
/** Class used for a switch that is in the "checked" (on) position. */
2627
CHECKED: 'mdc-switch--checked',
28+
/** Class used for a switch that is disabled. */
2729
DISABLED: 'mdc-switch--disabled',
2830
};
2931

30-
/** @enum {string} */
32+
/** String constants used by the switch. */
3133
const strings = {
34+
/** A CSS selector used to locate the native HTML control for the switch. */
3235
NATIVE_CONTROL_SELECTOR: '.mdc-switch__native-control',
36+
/** A CSS selector used to locate the ripple surface element for the switch. */
3337
RIPPLE_SURFACE_SELECTOR: '.mdc-switch__thumb-underlay',
3438
};
3539

36-
3740
export {cssClasses, strings};

packages/mdc-switch/foundation.js renamed to packages/mdc-switch/foundation.ts

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,47 +21,49 @@
2121
* THE SOFTWARE.
2222
*/
2323

24-
import MDCFoundation from '@material/base/foundation';
25-
import MDCSwitchAdapter from './adapter';
26-
/* eslint-enable no-unused-vars */
24+
import {MDCFoundation} from '@material/base/foundation';
25+
import {MDCSwitchAdapter} from './adapter';
2726
import {cssClasses, strings} from './constants';
2827

2928
/**
30-
* @extends {MDCFoundation<!MDCSwitchAdapter>}
29+
* Foundation for the MDC Switch. Encapsulates business logic for the switch.
30+
*
31+
* See architecture documentation for more details.
32+
* https://github.com/material-components/material-components-web/blob/master/docs/code/architecture.md
3133
*/
32-
class MDCSwitchFoundation extends MDCFoundation {
33-
/** @return enum {string} */
34+
class MDCSwitchFoundation extends MDCFoundation<MDCSwitchAdapter> {
35+
/** The string constants used by the switch. */
3436
static get strings() {
3537
return strings;
3638
}
3739

38-
/** @return enum {string} */
40+
/** The CSS classes used by the switch. */
3941
static get cssClasses() {
4042
return cssClasses;
4143
}
4244

43-
/** @return {!MDCSwitchAdapter} */
44-
static get defaultAdapter() {
45-
return /** @type {!MDCSwitchAdapter} */ ({
46-
addClass: (/* className: string */) => {},
47-
removeClass: (/* className: string */) => {},
48-
setNativeControlChecked: (/* checked: boolean */) => {},
49-
setNativeControlDisabled: (/* disabled: boolean */) => {},
50-
});
45+
/** The default Adapter for the switch. */
46+
static get defaultAdapter(): MDCSwitchAdapter {
47+
return {
48+
addClass: () => undefined,
49+
removeClass: () => undefined,
50+
setNativeControlChecked: () => undefined,
51+
setNativeControlDisabled: () => undefined,
52+
};
5153
}
5254

53-
constructor(adapter) {
55+
constructor(adapter: MDCSwitchAdapter) {
5456
super(Object.assign(MDCSwitchFoundation.defaultAdapter, adapter));
5557
}
5658

57-
/** @param {boolean} checked */
58-
setChecked(checked) {
59+
/** Sets the checked state of the switch. */
60+
setChecked(checked: boolean) {
5961
this.adapter_.setNativeControlChecked(checked);
6062
this.updateCheckedStyling_(checked);
6163
}
6264

63-
/** @param {boolean} disabled */
64-
setDisabled(disabled) {
65+
/** Sets the disabled state of the switch. */
66+
setDisabled(disabled: boolean) {
6567
this.adapter_.setNativeControlDisabled(disabled);
6668
if (disabled) {
6769
this.adapter_.addClass(cssClasses.DISABLED);
@@ -70,20 +72,14 @@ class MDCSwitchFoundation extends MDCFoundation {
7072
}
7173
}
7274

73-
/**
74-
* Handles the change event for the switch native control.
75-
* @param {!Event} evt
76-
*/
77-
handleChange(evt) {
78-
this.updateCheckedStyling_(evt.target.checked);
75+
/** Handles the change event for the switch native control. */
76+
handleChange(evt: Event) {
77+
const nativeControl = evt.target as HTMLInputElement;
78+
this.updateCheckedStyling_(nativeControl.checked);
7979
}
8080

81-
/**
82-
* Updates the styling of the switch based on its checked state.
83-
* @param {boolean} checked
84-
* @private
85-
*/
86-
updateCheckedStyling_(checked) {
81+
/** Updates the styling of the switch based on its checked state. */
82+
private updateCheckedStyling_(checked: boolean) {
8783
if (checked) {
8884
this.adapter_.addClass(cssClasses.CHECKED);
8985
} else {
@@ -92,4 +88,4 @@ class MDCSwitchFoundation extends MDCFoundation {
9288
}
9389
}
9490

95-
export default MDCSwitchFoundation;
91+
export {MDCSwitchFoundation as default, MDCSwitchFoundation};

packages/mdc-switch/index.js renamed to packages/mdc-switch/index.ts

Lines changed: 52 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -21,32 +21,30 @@
2121
* THE SOFTWARE.
2222
*/
2323

24-
import MDCComponent from '@material/base/component';
25-
/* eslint-disable no-unused-vars */
26-
import {MDCSelectionControlState, MDCSelectionControl} from '@material/selection-control/index';
27-
/* eslint-enable no-unused-vars */
28-
import MDCSwitchFoundation from './foundation';
29-
import {MDCRipple, MDCRippleFoundation} from '@material/ripple/index';
24+
import {MDCComponent} from '@material/base/component';
25+
import {MDCRipple, MDCRippleFoundation, RippleCapableSurface} from '@material/ripple/index';
3026
import {getMatchesProperty} from '@material/ripple/util';
27+
import {MDCSelectionControl} from '@material/selection-control/index';
28+
import {MDCSwitchFoundation} from './foundation';
3129

3230
/**
33-
* @extends MDCComponent<!MDCSwitchFoundation>
34-
* @implements {MDCSelectionControl}
31+
* An implementation of the switch component defined by the Material Design spec.
32+
*
33+
* https://material.io/design/components/selection-controls.html#switches
3534
*/
36-
class MDCSwitch extends MDCComponent {
37-
static attachTo(root) {
35+
class MDCSwitch extends MDCComponent<MDCSwitchFoundation> implements MDCSelectionControl, RippleCapableSurface {
36+
/** Creates an instance of MDCSwitch bound to the given root element. */
37+
static attachTo(root: HTMLElement) {
3838
return new MDCSwitch(root);
3939
}
4040

41-
constructor(...args) {
42-
super(...args);
41+
// Initialized in super class constructor, re-declared as public to fulfill to the `RippleCapableSurface` interface.
42+
root_!: Element;
4343

44-
/** @private {!MDCRipple} */
45-
this.ripple_ = this.initRipple_();
44+
private ripple_ = this.initRipple_();
4645

47-
/** @private {!Function} */
48-
this.changeHandler_;
49-
}
46+
// Initialized in `initialSyncWithDOM`.
47+
private changeHandler_!: EventListener;
5048

5149
destroy() {
5250
super.destroy();
@@ -55,7 +53,7 @@ class MDCSwitch extends MDCComponent {
5553
}
5654

5755
initialSyncWithDOM() {
58-
this.changeHandler_ = this.foundation_.handleChange.bind(this.foundation_);
56+
this.changeHandler_ = (...args) => this.foundation_.handleChange(...args);
5957
this.nativeControl_.addEventListener('change', this.changeHandler_);
6058

6159
// Sometimes the checked state of the input element is saved in the history.
@@ -64,75 +62,64 @@ class MDCSwitch extends MDCComponent {
6462
this.checked = this.checked;
6563
}
6664

67-
/**
68-
* Returns the state of the native control element, or null if the native control element is not present.
69-
* @return {?MDCSelectionControlState}
70-
* @private
71-
*/
72-
get nativeControl_() {
73-
const {NATIVE_CONTROL_SELECTOR} = MDCSwitchFoundation.strings;
74-
const el = /** @type {?MDCSelectionControlState} */ (
75-
this.root_.querySelector(NATIVE_CONTROL_SELECTOR));
76-
return el;
77-
}
78-
79-
/**
80-
* @return {!MDCRipple}
81-
* @private
82-
*/
83-
initRipple_() {
84-
const {RIPPLE_SURFACE_SELECTOR} = MDCSwitchFoundation.strings;
85-
const rippleSurface = /** @type {!Element} */ (this.root_.querySelector(RIPPLE_SURFACE_SELECTOR));
86-
87-
const MATCHES = getMatchesProperty(HTMLElement.prototype);
88-
const adapter = Object.assign(MDCRipple.createAdapter(this), {
89-
isUnbounded: () => true,
90-
isSurfaceActive: () => this.nativeControl_[MATCHES](':active'),
91-
addClass: (className) => rippleSurface.classList.add(className),
92-
removeClass: (className) => rippleSurface.classList.remove(className),
93-
registerInteractionHandler: (type, handler) => this.nativeControl_.addEventListener(type, handler),
94-
deregisterInteractionHandler: (type, handler) => this.nativeControl_.removeEventListener(type, handler),
95-
updateCssVariable: (varName, value) => rippleSurface.style.setProperty(varName, value),
96-
computeBoundingRect: () => rippleSurface.getBoundingClientRect(),
97-
});
98-
const foundation = new MDCRippleFoundation(adapter);
99-
return new MDCRipple(this.root_, foundation);
100-
}
101-
102-
/** @return {!MDCSwitchFoundation} */
65+
/** Gets the default Foundation for this switch. */
10366
getDefaultFoundation() {
10467
return new MDCSwitchFoundation({
105-
addClass: (className) => this.root_.classList.add(className),
106-
removeClass: (className) => this.root_.classList.remove(className),
107-
setNativeControlChecked: (checked) => this.nativeControl_.checked = checked,
108-
setNativeControlDisabled: (disabled) => this.nativeControl_.disabled = disabled,
68+
addClass: (className: string) => this.root_.classList.add(className),
69+
removeClass: (className: string) => this.root_.classList.remove(className),
70+
setNativeControlChecked: (checked: boolean) => this.nativeControl_.checked = checked,
71+
setNativeControlDisabled: (disabled: boolean) => this.nativeControl_.disabled = disabled,
10972
});
11073
}
11174

112-
/** @return {!MDCRipple} */
75+
/** The MDCRipple associated with this switch. */
11376
get ripple() {
11477
return this.ripple_;
11578
}
11679

117-
/** @return {boolean} */
80+
/** The checked state of this switch. */
11881
get checked() {
11982
return this.nativeControl_.checked;
12083
}
121-
122-
/** @param {boolean} checked */
12384
set checked(checked) {
12485
this.foundation_.setChecked(checked);
12586
}
12687

127-
/** @return {boolean} */
88+
/** The disabled state of this switch. */
12889
get disabled() {
12990
return this.nativeControl_.disabled;
13091
}
131-
132-
/** @param {boolean} disabled */
13392
set disabled(disabled) {
13493
this.foundation_.setDisabled(disabled);
13594
}
95+
96+
private initRipple_() {
97+
const {RIPPLE_SURFACE_SELECTOR} = MDCSwitchFoundation.strings;
98+
const rippleSurface = this.root_.querySelector(RIPPLE_SURFACE_SELECTOR) as HTMLElement;
99+
100+
const MATCHES = getMatchesProperty(HTMLElement.prototype);
101+
const adapter = Object.assign(MDCRipple.createAdapter(this), {
102+
addClass: (className: string) => rippleSurface.classList.add(className),
103+
computeBoundingRect: () => rippleSurface.getBoundingClientRect(),
104+
deregisterInteractionHandler: (type: string, handler: EventListener) =>
105+
this.nativeControl_.removeEventListener(type, handler),
106+
isSurfaceActive: () => this.nativeControl_[MATCHES]!(':active'),
107+
isUnbounded: () => true,
108+
registerInteractionHandler: (type: string, handler: EventListener) =>
109+
this.nativeControl_.addEventListener(type, handler),
110+
removeClass: (className: string) => rippleSurface.classList.remove(className),
111+
updateCssVariable: (varName: string, value: string) =>
112+
rippleSurface.style.setProperty(varName, value),
113+
});
114+
const foundation = new MDCRippleFoundation(adapter);
115+
return new MDCRipple(this.root_, foundation);
116+
}
117+
118+
/** Returns the state of the native control element. */
119+
private get nativeControl_() {
120+
const {NATIVE_CONTROL_SELECTOR} = MDCSwitchFoundation.strings;
121+
return this.root_.querySelector(NATIVE_CONTROL_SELECTOR) as HTMLInputElement;
122+
}
136123
}
137124

138125
export {MDCSwitchFoundation, MDCSwitch};

scripts/webpack/js-bundle-factory.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ class JsBundleFactory {
177177
selectionControl: getAbsolutePath('/packages/mdc-selection-control/index.ts'),
178178
slider: getAbsolutePath('/packages/mdc-slider/index.js'),
179179
snackbar: getAbsolutePath('/packages/mdc-snackbar/index.js'),
180-
switch: getAbsolutePath('/packages/mdc-switch/index.js'),
180+
switch: getAbsolutePath('/packages/mdc-switch/index.ts'),
181181
tab: getAbsolutePath('/packages/mdc-tab/index.js'),
182182
tabBar: getAbsolutePath('/packages/mdc-tab-bar/index.js'),
183183
tabIndicator: getAbsolutePath('/packages/mdc-tab-indicator/index.js'),

test/unit/mdc-switch/foundation.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import {assert} from 'chai';
2525
import td from 'testdouble';
2626

27-
import MDCSwitchFoundation from '../../../packages/mdc-switch/foundation';
27+
import {MDCSwitchFoundation} from '../../../packages/mdc-switch/foundation';
2828

2929
suite('MDCSwitchFoundation');
3030

0 commit comments

Comments
 (0)