import { styles } from "@material/mwc-textfield/mwc-textfield.css"; import { mdiClose } from "@mdi/js"; import { css, html, LitElement, PropertyValues, TemplateResult } from "lit"; import { customElement, property, query, state } from "lit/decorators"; import { classMap } from "lit/directives/class-map"; import { fireEvent } from "../common/dom/fire_event"; import { HomeAssistant } from "../types"; import "./ha-circular-progress"; import "./ha-icon-button"; declare global { interface HASSDomEvents { "file-picked": { files: FileList }; } } @customElement("ha-file-upload") export class HaFileUpload extends LitElement { @property({ attribute: false }) public hass?: HomeAssistant; @property() public accept!: string; @property() public icon?: string; @property() public label!: string; @property() public value: string | TemplateResult | null = null; @property({ type: Boolean }) private uploading = false; @property({ type: Boolean, attribute: "auto-open-file-dialog" }) private autoOpenFileDialog = false; @state() private _drag = false; @query("#input") private _input?: HTMLInputElement; protected firstUpdated(changedProperties: PropertyValues) { super.firstUpdated(changedProperties); if (this.autoOpenFileDialog) { this._openFilePicker(); } } public render(): TemplateResult { return html` ${this.uploading ? html`` : html` `} `; } private _openFilePicker() { this._input?.click(); } private _handleDrop(ev: DragEvent) { ev.preventDefault(); ev.stopPropagation(); if (ev.dataTransfer?.files) { fireEvent(this, "file-picked", { files: ev.dataTransfer.files }); } this._drag = false; } private _handleDragStart(ev: DragEvent) { ev.preventDefault(); ev.stopPropagation(); this._drag = true; } private _handleDragEnd(ev: DragEvent) { ev.preventDefault(); ev.stopPropagation(); this._drag = false; } private _handleFilePicked(ev) { fireEvent(this, "file-picked", { files: ev.target.files }); } private _clearValue(ev: Event) { ev.preventDefault(); this.value = null; fireEvent(this, "change"); } static get styles() { return [ styles, css` :host { display: block; } .mdc-text-field--filled { height: auto; padding-top: 16px; cursor: pointer; } .mdc-text-field--filled.mdc-text-field--with-trailing-icon { padding-top: 28px; } .mdc-text-field:not(.mdc-text-field--disabled) .mdc-text-field__icon { color: var(--secondary-text-color); } .mdc-text-field--filled.mdc-text-field--with-trailing-icon .mdc-text-field__icon { align-self: flex-end; } .mdc-text-field__icon--leading { margin-bottom: 12px; inset-inline-start: initial; inset-inline-end: 0px; direction: var(--direction); } .mdc-text-field--filled .mdc-floating-label--float-above { transform: scale(0.75); top: 8px; } .mdc-floating-label { inset-inline-start: 16px !important; inset-inline-end: initial !important; direction: var(--direction); } .mdc-text-field--filled .mdc-floating-label { inset-inline-start: 48px !important; inset-inline-end: initial !important; direction: var(--direction); } .dragged:before { position: var(--layout-fit_-_position); top: var(--layout-fit_-_top); right: var(--layout-fit_-_right); bottom: var(--layout-fit_-_bottom); left: var(--layout-fit_-_left); background: currentColor; content: ""; opacity: var(--dark-divider-opacity); pointer-events: none; border-radius: 4px; } .value { width: 100%; } input.file { display: none; } img { max-width: 100%; max-height: 125px; } ha-icon-button { --mdc-icon-button-size: 24px; --mdc-icon-size: 20px; } ha-circular-progress { display: block; text-align-last: center; } `, ]; } } declare global { interface HTMLElementTagNameMap { "ha-file-upload": HaFileUpload; } }