Skip to content

Commit

Permalink
Add textfield style
Browse files Browse the repository at this point in the history
  • Loading branch information
piitaya committed Sep 25, 2023
1 parent d2851ac commit 8a17af6
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 170 deletions.
8 changes: 3 additions & 5 deletions src/auth/ha-auth-flow.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable lit/prefer-static-styles */
import "@material/mwc-button";
import { genClientId } from "home-assistant-js-websocket";
import { CSSResultGroup, html, LitElement, nothing, PropertyValues } from "lit";
import { html, LitElement, nothing, PropertyValues } from "lit";
import { customElement, property, state } from "lit/decorators";
import { LocalizeFunc } from "../common/translations/localize";
import "../components/ha-alert";
Expand Down Expand Up @@ -391,10 +391,8 @@ export class HaAuthFlow extends LitElement {
}
}

static get styles(): CSSResultGroup {
// No shadow dom, styles should be in <style> tag inside render
return [];
}
// No shadow dom, styles should be in <style> tag inside render
static styles = [];
}

declare global {
Expand Down
136 changes: 36 additions & 100 deletions src/auth/ha-auth-form-string.ts
Original file line number Diff line number Diff line change
@@ -1,59 +1,39 @@
import { mdiEye, mdiEyeOff } from "@mdi/js";
import {
CSSResultGroup,
LitElement,
PropertyValues,
TemplateResult,
html,
} from "lit";
import { customElement, property, query, state } from "lit/decorators";
import { fireEvent } from "../common/dom/fire_event";
import {
HaFormElement,
HaFormStringData,
HaFormStringSchema,
} from "../components/ha-form/types";
/* eslint-disable lit/prefer-static-styles */
import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators";
import { HaFormString } from "../components/ha-form/ha-form-string";
import "../components/ha-icon-button";

const MASKED_FIELDS = ["password", "secret", "token"];
import "./ha-auth-textfield";

@customElement("ha-auth-form-string")
export class HaAuthFormString extends LitElement implements HaFormElement {
@property() public schema!: HaFormStringSchema;

@property() public data!: HaFormStringData;

@property() public label!: string;

@property() public helper?: string;

@property({ type: Boolean }) public disabled = false;

@state() private _unmaskedPassword = false;

@query("input") private _input?: HTMLInputElement;

export class HaAuthFormString extends HaFormString {
protected createRenderRoot() {
return this;
}

public focus(): void {
if (this._input) {
this._input.focus();
}
}

protected render(): TemplateResult {
const isPassword = MASKED_FIELDS.some((field) =>
this.schema.name.includes(field)
);
return html`
<input
.type=${!isPassword
? this._stringType
: this._unmaskedPassword
? "text"
: "password"}
<style>
ha-auth-form-string {
display: block;
position: relative;
}
ha-auth-form-string[own-margin] {
margin-bottom: 5px;
}
ha-auth-textfield {
display: block !important;
}
${HaFormString.styles}
</style>
<ha-auth-textfield
.type=${
!this.isPassword
? this.stringType
: this.unmaskedPassword
? "text"
: "password"
}
.label=${this.label}
.value=${this.data || ""}
.helper=${this.helper}
Expand All @@ -63,63 +43,19 @@ export class HaAuthFormString extends LitElement implements HaFormElement {
.autoValidate=${this.schema.required}
.name=${this.schema.name}
.autocomplete=${this.schema.autocomplete}
.suffix=${isPassword
? // reserve some space for the icon.
html`<div style="width: 24px"></div>`
: this.schema.description?.suffix}
.suffix=${
this.isPassword
? // reserve some space for the icon.
html`<div style="width: 24px"></div>`
: this.schema.description?.suffix
}
@input=${this._valueChanged}
@change=${this._valueChanged}
/>
${isPassword
? html`<ha-icon-button
toggles
.label=${`${this._unmaskedPassword ? "Hide" : "Show"} password`}
@click=${this._toggleUnmaskedPassword}
.path=${this._unmaskedPassword ? mdiEyeOff : mdiEye}
></ha-icon-button>`
: ""}
></ha-auth-textfield>
${this.renderIcon()}
</ha-auth-textfield>
`;
}

protected updated(changedProps: PropertyValues): void {
if (changedProps.has("schema")) {
this.toggleAttribute("own-margin", !!this.schema.required);
}
}

private _toggleUnmaskedPassword(): void {
this._unmaskedPassword = !this._unmaskedPassword;
}

private _valueChanged(ev: Event): void {
let value: string | undefined = (ev.target as HTMLInputElement).value;
if (this.data === value) {
return;
}
if (value === "" && !this.schema.required) {
value = undefined;
}
fireEvent(this, "value-changed", {
value,
});
}

private get _stringType(): string {
if (this.schema.format) {
if (["email", "url"].includes(this.schema.format)) {
return this.schema.format;
}
if (this.schema.format === "fqdnurl") {
return "url";
}
}
return "text";
}

static get styles(): CSSResultGroup {
// No shadow dom, styles should be in authorize.html.template
return [];
}
}

declare global {
Expand Down
36 changes: 4 additions & 32 deletions src/auth/ha-auth-form.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1,32 @@
/* eslint-disable lit/prefer-static-styles */
import { CSSResultGroup, html } from "lit";
import { html } from "lit";
import { customElement } from "lit/decorators";
import { fireEvent } from "../common/dom/fire_event";
import { HaForm } from "../components/ha-form/ha-form";
import { HaFormElement, HaFormSchema } from "../components/ha-form/types";
import "./ha-auth-form-string";

@customElement("ha-auth-form")
export class HaAuthForm extends HaForm {
protected fieldElementName(type: string): string {
if (type === "string") {
return "ha-auth-form-string";
return `ha-auth-form-${type}`;
}
return super.fieldElementName(type);
}

protected createRenderRoot() {
// attach it as soon as possible to make sure we fetch all events.
this.addEventListener("value-changed", (ev) => {
ev.stopPropagation();
const schema = (ev.target as HaFormElement).schema as HaFormSchema;

if (ev.target === this) return;

const newValue = !schema.name
? ev.detail.value
: { [schema.name]: ev.detail.value };

fireEvent(this, "value-changed", {
value: { ...this.data, ...newValue },
});
});
this.addValueChangedListener(this);
return this;
}

protected render() {
return html`
<style>
ha-auth-form .root > * {
display: block;
}
ha-auth-form .root > *:not([own-margin]):not(:last-child) {
margin-bottom: 24px;
}
ha-auth-form ha-alert[own-margin] {
margin-bottom: 4px;
}
${HaForm.styles}
</style>
${super.render()}
`;
}

static get styles(): CSSResultGroup {
// No shadow dom, styles should be in <style> tag inside render
return [];
}
}

declare global {
Expand Down
114 changes: 114 additions & 0 deletions src/auth/ha-auth-textfield.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/* eslint-disable lit/prefer-static-styles */
import { html } from "lit";
import { customElement } from "lit/decorators";
import { HaTextField } from "../components/ha-textfield";

@customElement("ha-auth-textfield")
export class HaAuthTextField extends HaTextField {
public render() {
return html`
<style>
ha-auth-textfield {
display: inline-flex;
flex-direction: column;
outline: none
}
ha-auth-textfield:not([disabled]):hover :not(.mdc-text-field--invalid):not(.mdc-text-field--focused) mwc-notched-outline {
--mdc-notched-outline-border-color: var( --mdc-text-field-outlined-hover-border-color, rgba(0, 0, 0, 0.87))
}
ha-auth-textfield:not([disabled]) .mdc-text-field:not(.mdc-text-field--outlined) {
background-color: var(--mdc-text-field-fill-color, whitesmoke)
}
ha-auth-textfield:not([disabled]) .mdc-text-field.mdc-text-field--invalid mwc-notched-outline {
--mdc-notched-outline-border-color: var( --mdc-text-field-error-color, var(--mdc-theme-error, #b00020))
}
ha-auth-textfield:not([disabled]) .mdc-text-field.mdc-text-field--invalid+.mdc-text-field-helper-line .mdc-text-field-character-counter,
ha-auth-textfield:not([disabled]) .mdc-text-field.mdc-text-field--invalid .mdc-text-field__icon {
color: var(--mdc-text-field-error-color, var(--mdc-theme-error, #b00020))
}
ha-auth-textfield:not([disabled]) .mdc-text-field:not(.mdc-text-field--invalid):not(.mdc-text-field--focused) .mdc-floating-label,
ha-auth-textfield:not([disabled]) .mdc-text-field:not(.mdc-text-field--invalid):not(.mdc-text-field--focused) .mdc-floating-label::after {
color: var(--mdc-text-field-label-ink-color, rgba(0, 0, 0, 0.6))
}
ha-auth-textfield:not([disabled]) .mdc-text-field.mdc-text-field--focused mwc-notched-outline {
--mdc-notched-outline-stroke-width: 2px
}
ha-auth-textfield:not([disabled]) .mdc-text-field.mdc-text-field--focused:not(.mdc-text-field--invalid) mwc-notched-outline {
--mdc-notched-outline-border-color: var( --mdc-text-field-focused-label-color, var(--mdc-theme-primary, rgba(98, 0, 238, 0.87)))
}
ha-auth-textfield:not([disabled]) .mdc-text-field.mdc-text-field--focused:not(.mdc-text-field--invalid) .mdc-floating-label {
color: #6200ee;
color: var(--mdc-theme-primary, #6200ee)
}
ha-auth-textfield:not([disabled]) .mdc-text-field .mdc-text-field__input {
color: var(--mdc-text-field-ink-color, rgba(0, 0, 0, 0.87))
}
ha-auth-textfield:not([disabled]) .mdc-text-field .mdc-text-field__input::placeholder {
color: var(--mdc-text-field-label-ink-color, rgba(0, 0, 0, 0.6))
}
ha-auth-textfield:not([disabled]) .mdc-text-field-helper-line .mdc-text-field-helper-text:not(.mdc-text-field-helper-text--validation-msg),
ha-auth-textfield:not([disabled]) .mdc-text-field-helper-line:not(.mdc-text-field--invalid) .mdc-text-field-character-counter {
color: var(--mdc-text-field-label-ink-color, rgba(0, 0, 0, 0.6))
}
ha-auth-textfield[disabled] .mdc-text-field:not(.mdc-text-field--outlined) {
background-color: var(--mdc-text-field-disabled-fill-color, #fafafa)
}
ha-auth-textfield[disabled] .mdc-text-field.mdc-text-field--outlined mwc-notched-outline {
--mdc-notched-outline-border-color: var( --mdc-text-field-outlined-disabled-border-color, rgba(0, 0, 0, 0.06))
}
ha-auth-textfield[disabled] .mdc-text-field:not(.mdc-text-field--invalid):not(.mdc-text-field--focused) .mdc-floating-label,
ha-auth-textfield[disabled] .mdc-text-field:not(.mdc-text-field--invalid):not(.mdc-text-field--focused) .mdc-floating-label::after {
color: var(--mdc-text-field-disabled-ink-color, rgba(0, 0, 0, 0.38))
}
ha-auth-textfield[disabled] .mdc-text-field .mdc-text-field__input,
ha-auth-textfield[disabled] .mdc-text-field .mdc-text-field__input::placeholder {
color: var(--mdc-text-field-disabled-ink-color, rgba(0, 0, 0, 0.38))
}
ha-auth-textfield[disabled] .mdc-text-field-helper-line .mdc-text-field-helper-text,
ha-auth-textfield[disabled] .mdc-text-field-helper-line .mdc-text-field-character-counter {
color: var(--mdc-text-field-disabled-ink-color, rgba(0, 0, 0, 0.38))
}
ha-auth-textfield:not([disabled]) .mdc-text-field.mdc-text-field--focused:not(.mdc-text-field--invalid) .mdc-floating-label {
color: var(--mdc-theme-primary,#6200ee)
}
ha-auth-textfield[no-spinner] input::-webkit-outer-spin-button,
ha-auth-textfield[no-spinner] input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Firefox */
ha-auth-textfield[no-spinner] input[type="number"] {
-moz-appearance: textfield;
}
${HaAuthTextField.styles}
</style>
${super.render()}
`;
}

protected createRenderRoot() {
return this;
}
}

declare global {
interface HTMLElementTagNameMap {
"ha-auth-textfield": HaAuthTextField;
}
}
7 changes: 1 addition & 6 deletions src/auth/ha-authorize.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable lit/prefer-static-styles */
import { CSSResultGroup, html, LitElement, nothing, PropertyValues } from "lit";
import { html, LitElement, nothing, PropertyValues } from "lit";
import { customElement, property, state } from "lit/decorators";
import punycode from "punycode";
import { applyThemesOnElement } from "../common/dom/apply_themes_on_element";
Expand Down Expand Up @@ -248,9 +248,4 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
private async _handleAuthProviderPick(ev) {
this._authProvider = ev.detail;
}

static get styles(): CSSResultGroup {
// No shadow dom, styles should be in <style> tag inside render
return [];
}
}
Loading

0 comments on commit 8a17af6

Please sign in to comment.