Skip to content

Commit fe65d5b

Browse files
asynclizcopybara-github
authored andcommitted
feat(field): add field component
PiperOrigin-RevId: 401868371
1 parent 5145af8 commit fe65d5b

File tree

8 files changed

+229
-22
lines changed

8 files changed

+229
-22
lines changed

components/field/filled-field.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,24 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
// TODO(b/177366329): Import and export filled field web component
7+
import {customElement} from 'lit/decorators';
8+
9+
import {FilledField} from './lib/filled-field';
10+
import {styles as filledStyles} from './lib/filled-styles.css';
11+
import {styles as sharedStyles} from './lib/shared-styles.css';
12+
13+
declare global {
14+
interface HTMLElementTagNameMap {
15+
'md-filled-field': MdFilledField;
16+
}
17+
}
18+
19+
/**
20+
* @soyCompatible
21+
* @final
22+
* @suppress {const}
23+
*/
24+
@customElement('md-filled-field')
25+
export class MdFilledField extends FilledField {
26+
static styles = [sharedStyles, filledStyles];
27+
}

components/field/lib/constants.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.

components/field/lib/field.ts

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/**
2+
* @license
3+
* Copyright 2021 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import {html, LitElement, TemplateResult} from 'lit';
8+
import {property, state} from 'lit/decorators';
9+
import {ClassInfo, classMap} from 'lit/directives/class-map';
10+
11+
import {FieldFoundation} from './foundation';
12+
import {FieldState, LabelType} from './state';
13+
14+
/** @soyCompatible */
15+
export class Field extends LitElement implements FieldState {
16+
// FieldState
17+
@property({type: Boolean}) disabled = false;
18+
@property({type: Boolean}) error = false;
19+
@property({type: Boolean}) focused = false;
20+
@property({type: String}) label?: string;
21+
@state() labelText = '';
22+
@property({type: Boolean}) populated = false;
23+
@property({type: Boolean}) required = false;
24+
@state() visibleLabelType = LabelType.RESTING;
25+
26+
protected foundation = new FieldFoundation({state: this});
27+
28+
/** @soyTemplate */
29+
render(): TemplateResult {
30+
return html`
31+
<span class="mdc-field ${classMap(this.getRenderClasses())}">
32+
<span class="mdc-field__container">
33+
${this.renderContainerContents()}
34+
</span>
35+
</span>
36+
`;
37+
}
38+
39+
/** @soyTemplate */
40+
protected getRenderClasses(): ClassInfo {
41+
return {
42+
'mdc-field--disabled': this.disabled,
43+
'mdc-field--error': this.error,
44+
'mdc-field--focused': this.focused,
45+
'mdc-field--populated': this.populated,
46+
'mdc-field--required': this.required,
47+
};
48+
}
49+
50+
/** @soyTemplate */
51+
protected renderContainerContents(): TemplateResult {
52+
return html`
53+
<span class="mdc-field__start">
54+
<slot name="start"></slot>
55+
</span>
56+
<span class="mdc-field__middle">${this.renderMiddleContents()}</span>
57+
<span class="mdc-field__end">
58+
<slot name="end"></slot>
59+
</span>
60+
`;
61+
}
62+
63+
/** @soyTemplate */
64+
protected renderMiddleContents(): TemplateResult {
65+
return html`
66+
<span class="mdc-field__content"><slot></slot></span>
67+
`;
68+
}
69+
70+
/** @soyTemplate */
71+
protected renderLabel(labelType: LabelType): TemplateResult {
72+
return html`
73+
<span class="mdc-field__label
74+
${classMap(this.getRenderLabelClasses(labelType))}"
75+
>${this.labelText}</span>
76+
`;
77+
}
78+
79+
/** @soyTemplate */
80+
protected getRenderLabelClasses(labelType: LabelType): ClassInfo {
81+
return {
82+
'mdc-field__label--floating': labelType === LabelType.FLOATING,
83+
'mdc-field__label--resting': labelType === LabelType.RESTING,
84+
'mdc-field__label--hidden': labelType !== this.visibleLabelType,
85+
};
86+
}
87+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* @license
3+
* Copyright 2021 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import {html, TemplateResult} from 'lit';
8+
import {ClassInfo} from 'lit/directives/class-map';
9+
10+
import {Field} from './field';
11+
import {LabelType} from './state';
12+
13+
/** @soyCompatible */
14+
export class FilledField extends Field {
15+
/** @soyTemplate */
16+
protected override getRenderClasses(): ClassInfo {
17+
return {
18+
...super.getRenderClasses(),
19+
'mdc-field--filled': true,
20+
};
21+
}
22+
23+
/** @soyTemplate */
24+
protected override renderContainerContents(): TemplateResult {
25+
return html`
26+
${super.renderContainerContents()}
27+
<span class="mdc-field__stroke"></span>
28+
`;
29+
}
30+
31+
/** @soyTemplate */
32+
protected renderMiddleContents(): TemplateResult {
33+
return html`
34+
${this.renderLabel(LabelType.FLOATING)}
35+
${this.renderLabel(LabelType.RESTING)}
36+
${super.renderMiddleContents()}
37+
`;
38+
}
39+
}

components/field/lib/foundation.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,11 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
import {MDCObserverFoundation} from '@material/base/observer-foundation';
7+
import {ObserverFoundation} from '../../controller/observer-foundation';
88

9-
import {FieldAdapter} from './adapter';
10-
import {LabelType} from './constants';
11-
12-
export class FieldFoundation extends MDCObserverFoundation<FieldAdapter> {
13-
constructor(adapter: FieldAdapter) {
14-
super(adapter);
15-
}
9+
import {FieldAdapter, LabelType} from './state';
1610

11+
export class FieldFoundation extends ObserverFoundation<FieldAdapter> {
1712
override init() {
1813
this.observe(this.adapter.state, {
1914
disabled: this.onDisabledChange,
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* @license
3+
* Copyright 2021 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import {html, TemplateResult} from 'lit';
8+
import {ClassInfo} from 'lit/directives/class-map';
9+
10+
import {Field} from './field';
11+
import {LabelType} from './state';
12+
13+
/** @soyCompatible */
14+
export class OutlinedField extends Field {
15+
/** @soyTemplate */
16+
protected override getRenderClasses(): ClassInfo {
17+
return {
18+
...super.getRenderClasses(),
19+
'mdc-field--outlined': true,
20+
};
21+
}
22+
23+
/** @soyTemplate */
24+
protected override renderContainerContents(): TemplateResult {
25+
return html`
26+
${this.renderOutline()}
27+
${super.renderContainerContents()}
28+
`;
29+
}
30+
31+
/** @soyTemplate */
32+
protected renderOutline(): TemplateResult {
33+
return html`
34+
<span class="mdc-field__outline">
35+
<span class="mdc-field__outline-start"></span>
36+
<span class="mdc-field__outline-notch">
37+
<span class="mdc-field__outline-panel-inactive"></span>
38+
<span class="mdc-field__outline-panel-active"></span>
39+
${this.renderLabel(LabelType.FLOATING)}
40+
</span>
41+
<span class="mdc-field__outline-end"></span>
42+
</span>
43+
`;
44+
}
45+
46+
/** @soyTemplate */
47+
protected override renderMiddleContents(): TemplateResult {
48+
return html`
49+
${this.renderLabel(LabelType.RESTING)}
50+
${super.renderMiddleContents()}
51+
`;
52+
}
53+
}
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
import {LabelType} from './constants';
8-
97
export interface FieldState {
108
disabled: boolean;
119
error: boolean;
@@ -17,6 +15,11 @@ export interface FieldState {
1715
visibleLabelType: LabelType;
1816
}
1917

18+
export enum LabelType {
19+
FLOATING = 'floating',
20+
RESTING = 'resting',
21+
}
22+
2023
export interface FieldAdapter {
2124
state: FieldState;
2225
}

components/field/outlined-field.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,24 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
// TODO(b/177366329): Import and export outlined field web component
7+
import {customElement} from 'lit/decorators';
8+
9+
import {OutlinedField} from './lib/outlined-field';
10+
import {styles as outlinedStyles} from './lib/outlined-styles.css';
11+
import {styles as sharedStyles} from './lib/shared-styles.css';
12+
13+
declare global {
14+
interface HTMLElementTagNameMap {
15+
'md-outlined-field': MdOutlinedField;
16+
}
17+
}
18+
19+
/**
20+
* @soyCompatible
21+
* @final
22+
* @suppress {const}
23+
*/
24+
@customElement('md-outlined-field')
25+
export class MdOutlinedField extends OutlinedField {
26+
static styles = [sharedStyles, outlinedStyles];
27+
}

0 commit comments

Comments
 (0)