mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-22 00:36:34 +00:00
Add input elements to login page for password managers (#9369)
This commit is contained in:
parent
d93db16963
commit
a4aba93d57
@ -7,6 +7,7 @@ import {
|
|||||||
PropertyValues,
|
PropertyValues,
|
||||||
TemplateResult,
|
TemplateResult,
|
||||||
} from "lit";
|
} from "lit";
|
||||||
|
import "./ha-password-manager-polyfill";
|
||||||
import { property, state } from "lit/decorators";
|
import { property, state } from "lit/decorators";
|
||||||
import "../components/ha-form/ha-form";
|
import "../components/ha-form/ha-form";
|
||||||
import "../components/ha-markdown";
|
import "../components/ha-markdown";
|
||||||
@ -20,7 +21,7 @@ import { litLocalizeLiteMixin } from "../mixins/lit-localize-lite-mixin";
|
|||||||
type State = "loading" | "error" | "step";
|
type State = "loading" | "error" | "step";
|
||||||
|
|
||||||
class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
|
class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
|
||||||
@property() public authProvider?: AuthProvider;
|
@property({ attribute: false }) public authProvider?: AuthProvider;
|
||||||
|
|
||||||
@property() public clientId?: string;
|
@property() public clientId?: string;
|
||||||
|
|
||||||
@ -37,7 +38,15 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
|
|||||||
@state() private _errorMessage?: string;
|
@state() private _errorMessage?: string;
|
||||||
|
|
||||||
protected render() {
|
protected render() {
|
||||||
return html` <form>${this._renderForm()}</form> `;
|
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>
|
||||||
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected firstUpdated(changedProps: PropertyValues) {
|
protected firstUpdated(changedProps: PropertyValues) {
|
||||||
@ -231,11 +240,17 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
|
|||||||
await this.updateComplete;
|
await this.updateComplete;
|
||||||
// 100ms to give all the form elements time to initialize.
|
// 100ms to give all the form elements time to initialize.
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const form = this.shadowRoot!.querySelector("ha-form");
|
const form = this.renderRoot.querySelector("ha-form");
|
||||||
if (form) {
|
if (form) {
|
||||||
(form as any).focus();
|
(form as any).focus();
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.renderRoot.querySelector(
|
||||||
|
"ha-password-manager-polyfill"
|
||||||
|
)!.boundingRect = this.getBoundingClientRect();
|
||||||
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _stepDataChanged(ev: CustomEvent) {
|
private _stepDataChanged(ev: CustomEvent) {
|
||||||
@ -329,3 +344,9 @@ class HaAuthFlow extends litLocalizeLiteMixin(LitElement) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
customElements.define("ha-auth-flow", HaAuthFlow);
|
customElements.define("ha-auth-flow", HaAuthFlow);
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-auth-flow": HaAuthFlow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
110
src/auth/ha-password-manager-polyfill.ts
Normal file
110
src/auth/ha-password-manager-polyfill.ts
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
import { html, LitElement, TemplateResult } from "lit";
|
||||||
|
import { customElement, property } from "lit/decorators";
|
||||||
|
import { fireEvent } from "../common/dom/fire_event";
|
||||||
|
import { HaFormSchema } from "../components/ha-form/ha-form";
|
||||||
|
import { DataEntryFlowStep } from "../data/data_entry_flow";
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface HTMLElementTagNameMap {
|
||||||
|
"ha-password-manager-polyfill": HaPasswordManagerPolyfill;
|
||||||
|
}
|
||||||
|
interface HASSDomEvents {
|
||||||
|
"form-submitted": undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ENABLED_HANDLERS = [
|
||||||
|
"homeassistant",
|
||||||
|
"legacy_api_password",
|
||||||
|
"command_line",
|
||||||
|
];
|
||||||
|
|
||||||
|
@customElement("ha-password-manager-polyfill")
|
||||||
|
export class HaPasswordManagerPolyfill extends LitElement {
|
||||||
|
@property({ attribute: false }) public step?: DataEntryFlowStep;
|
||||||
|
|
||||||
|
@property({ attribute: false }) public stepData: any;
|
||||||
|
|
||||||
|
@property({ attribute: false }) public boundingRect?: DOMRect;
|
||||||
|
|
||||||
|
protected createRenderRoot() {
|
||||||
|
// Add under document body so the element isn't placed inside any shadow roots
|
||||||
|
return document.body;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get styles() {
|
||||||
|
return `
|
||||||
|
.password-manager-polyfill {
|
||||||
|
position: absolute;
|
||||||
|
top: ${this.boundingRect?.y || 148}px;
|
||||||
|
left: calc(50% - ${(this.boundingRect?.width || 360) / 2}px);
|
||||||
|
width: ${this.boundingRect?.width || 360}px;
|
||||||
|
opacity: 0;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
.password-manager-polyfill input {
|
||||||
|
width: 100%;
|
||||||
|
height: 62px;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
.password-manager-polyfill input[type="submit"] {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected render(): TemplateResult {
|
||||||
|
if (
|
||||||
|
this.step &&
|
||||||
|
this.step.type === "form" &&
|
||||||
|
this.step.step_id === "init" &&
|
||||||
|
ENABLED_HANDLERS.includes(this.step.handler[0])
|
||||||
|
) {
|
||||||
|
return html`
|
||||||
|
<form
|
||||||
|
class="password-manager-polyfill"
|
||||||
|
aria-hidden="true"
|
||||||
|
@submit=${this._handleSubmit}
|
||||||
|
>
|
||||||
|
${this.step.data_schema.map((input) => this.render_input(input))}
|
||||||
|
<input type="submit" />
|
||||||
|
<style>
|
||||||
|
${this.styles}
|
||||||
|
</style>
|
||||||
|
</form>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
return html``;
|
||||||
|
}
|
||||||
|
|
||||||
|
private render_input(schema: HaFormSchema): TemplateResult | string {
|
||||||
|
const inputType = schema.name.includes("password") ? "password" : "text";
|
||||||
|
if (schema.type !== "string") {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return html`
|
||||||
|
<input
|
||||||
|
tabindex="-1"
|
||||||
|
.id=${schema.name}
|
||||||
|
.type=${inputType}
|
||||||
|
.value=${this.stepData[schema.name] || ""}
|
||||||
|
@input=${this._valueChanged}
|
||||||
|
/>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleSubmit(ev: Event) {
|
||||||
|
ev.preventDefault();
|
||||||
|
fireEvent(this, "form-submitted");
|
||||||
|
}
|
||||||
|
|
||||||
|
private _valueChanged(ev: Event) {
|
||||||
|
const target = ev.target! as HTMLInputElement;
|
||||||
|
this.stepData = { ...this.stepData, [target.id]: target.value };
|
||||||
|
fireEvent(this, "value-changed", {
|
||||||
|
value: this.stepData,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user