Skip to content

Commit

Permalink
Move auth components from shadow DOM to light DOM
Browse files Browse the repository at this point in the history
  • Loading branch information
piitaya committed Sep 25, 2023
1 parent dac7c0f commit cec3cbb
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 238 deletions.
49 changes: 11 additions & 38 deletions src/auth/ha-auth-flow.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
import "@material/mwc-button";
import { genClientId } from "home-assistant-js-websocket";
import {
css,
CSSResultGroup,
html,
LitElement,
nothing,
PropertyValues,
} from "lit";
import { CSSResultGroup, html, LitElement, nothing, PropertyValues } from "lit";
import { customElement, property, state } from "lit/decorators";
import { LocalizeFunc } from "../common/translations/localize";
import "../components/ha-alert";
import "../components/ha-checkbox";
import { computeInitialHaFormData } from "../components/ha-form/compute-initial-ha-form-data";
import "../components/ha-form/ha-form";
import "../components/ha-formfield";
import "../components/ha-markdown";
import { AuthProvider, autocompleteLoginFields } from "../data/auth";
import {
DataEntryFlowStep,
DataEntryFlowStepForm,
} from "../data/data_entry_flow";
import "./ha-password-manager-polyfill";
import "./ha-auth-form";

type State = "loading" | "error" | "step";

Expand Down Expand Up @@ -49,6 +41,10 @@ export class HaAuthFlow extends LitElement {

@state() private _storeToken = false;

createRenderRoot() {
return this;
}

willUpdate(changedProps: PropertyValues) {
super.willUpdate(changedProps);

Expand Down Expand Up @@ -78,15 +74,7 @@ export class HaAuthFlow extends LitElement {
}

protected render() {
return html`
<form>${this._renderForm()}</form>
<ha-password-manager-polyfill
.step=${this._step}
.stepData=${this._stepData}
@form-submitted=${this._handleSubmit}
@value-changed=${this._stepDataChanged}
></ha-password-manager-polyfill>
`;
return html` <form>${this._renderForm()}</form> `;
}

protected firstUpdated(changedProps: PropertyValues) {
Expand Down Expand Up @@ -128,12 +116,6 @@ export class HaAuthFlow extends LitElement {
(form as any).focus();
}
}, 100);

setTimeout(() => {
this.renderRoot.querySelector(
"ha-password-manager-polyfill"
)!.boundingRect = this.getBoundingClientRect();
}, 500);
}

private _renderForm() {
Expand Down Expand Up @@ -205,15 +187,15 @@ export class HaAuthFlow extends LitElement {
></ha-markdown>
`
: nothing}
<ha-form
<ha-auth-form
.data=${this._stepData}
.schema=${autocompleteLoginFields(step.data_schema)}
.error=${step.errors}
.disabled=${this._submitting}
.computeLabel=${this._computeLabelCallback(step)}
.computeError=${this._computeErrorCallback(step)}
@value-changed=${this._stepDataChanged}
></ha-form>
></ha-auth-form>
${this.clientId === genClientId() &&
!["select_mfa_module", "mfa"].includes(step.step_id)
? html`
Expand Down Expand Up @@ -397,17 +379,8 @@ export class HaAuthFlow extends LitElement {
}

static get styles(): CSSResultGroup {
return css`
.action {
margin: 24px 0 8px;
text-align: center;
}
/* Align with the rest of the form. */
.store-token {
margin-top: 10px;
margin-left: -16px;
}
`;
// No shadow dom, styles should be in authorize.html.template
return [];
}
}

Expand Down
129 changes: 129 additions & 0 deletions src/auth/ha-auth-form-string.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
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";
import "../components/ha-icon-button";

const MASKED_FIELDS = ["password", "secret", "token"];

@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;

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"}
.label=${this.label}
.value=${this.data || ""}
.helper=${this.helper}
helperPersistent
.disabled=${this.disabled}
.required=${this.schema.required}
.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}
@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>`
: ""}
`;
}

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 {
interface HTMLElementTagNameMap {
"ha-auth-form-string": HaAuthFormString;
}
}
46 changes: 46 additions & 0 deletions src/auth/ha-auth-form.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { CSSResultGroup } 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 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 },
});
});
return this;
}

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

declare global {
interface HTMLElementTagNameMap {
"ha-auth-form": HaAuthForm;
}
}
35 changes: 8 additions & 27 deletions src/auth/ha-authorize.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
import punycode from "punycode";
import {
css,
CSSResultGroup,
html,
LitElement,
nothing,
PropertyValues,
} from "lit";
import { CSSResultGroup, 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";
import { extractSearchParamsObject } from "../common/url/search-params";
import "../components/ha-alert";
Expand Down Expand Up @@ -123,6 +116,10 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
`;
}

createRenderRoot() {
return this;
}

protected firstUpdated(changedProps: PropertyValues) {
super.firstUpdated(changedProps);

Expand Down Expand Up @@ -219,23 +216,7 @@ export class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
}

static get styles(): CSSResultGroup {
return css`
ha-pick-auth-provider {
display: block;
margin-top: 48px;
}
ha-auth-flow {
display: block;
margin-top: 24px;
}
ha-alert {
display: block;
margin: 16px 0;
}
p {
font-size: 14px;
line-height: 20px;
}
`;
// No shadow dom, styles should be in authorize.html.template
return [];
}
}
Loading

0 comments on commit cec3cbb

Please sign in to comment.