import { css, html } from "lit"; import { customElement, property, query } from "lit/decorators.js"; import { DropzoneElement, DropzoneOptions } from "@scoped-elements/dropzone"; import { consume } from "@lit/context"; import { FormField, FormFieldController, sharedStyles, } from "@holochain-open-dev/elements"; import { localized } from "@lit/localize"; import { FileStorageClient } from "../file-storage-client.js"; import { fileStorageClientContext } from "../context.js"; import { HolochainDropzone } from "../holochain-dropzone.js"; import { EntryHash } from "@holochain/client"; /** * @fires file-uploaded - Fired after having uploaded the file * @csspart dropzone - Style the dropzone itself */ @localized() @customElement("upload-files") export class UploadFiles extends DropzoneElement implements FormField { /** * The name of the field if this element is used inside a form * Required only if the element is used inside a form */ @property() name!: string; /** * Whether this field is required if this element is used inside a form */ @property() required = false; /** * Whether this field is disabled if this element is used inside a form */ @property() disabled = false; /** * The default value that this element will take if it is resetted in a form */ @property() defaultValue!: EntryHash | Array; /** Public attributes */ /** * Whether this element should allow only file to be uploaded */ @property({ type: Boolean, attribute: "one-file" }) oneFile = false; /** * The type of files accepted by this element * Learn how to use this here: https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/accept */ @property({ type: String, attribute: "accepted-files" }) acceptedFiles: | string | undefined = undefined; /** * @internal */ @consume({ context: fileStorageClientContext }) _client!: FileStorageClient; /** * @internal */ _controller = new FormFieldController(this); async firstUpdated() { super.firstUpdated(); this.reset(); } async reset() { this.clear(); if (this.defaultValue) { if (Array.isArray(this.defaultValue)) { for (const fileHash of this.defaultValue) { const image = await this._client.downloadFile(fileHash); this.dropzone.addFile(image as any); } } else { const image = await this._client.downloadFile(this.defaultValue); this.dropzone.addFile(image as any); } } } /** * @internal */ get value() { if (this.oneFile) return this.dropzone.files[0] ? (this.dropzone.files[0] as any).hash : undefined; return this.dropzone.files.map((file) => (file as any).hash); } /** * @internal */ @query("#hidden-input") private _input!: HTMLInputElement; reportValidity() { const invalid = this.required !== false && this.value === undefined; if (invalid) { this._input.setCustomValidity(`Uploading a file is required`); this._input.reportValidity(); } return !invalid; } buildDropzone(dropzoneElement: HTMLElement, options: DropzoneOptions) { return new HolochainDropzone( dropzoneElement, this._client, options ) as any as Dropzone; } render() { return html`
${super.render()}
`; } static get styles() { return [ DropzoneElement.styles, sharedStyles, css` :host { display: flex; } `, ]; } }