import { customElement, DeesElement, type TemplateResult, property, html, css, unsafeCSS, cssManager, type CSSResult, } from '@design.estate/dees-element'; import * as domtools from '@design.estate/dees-domtools'; declare global { interface HTMLElementTagNameMap { 'dees-input-fileupload': DeesInputFileupload; } } @customElement('dees-input-fileupload') export class DeesInputFileupload extends DeesElement { public static demo = () => html``; // INSTANCE public changeSubject = new domtools.rxjs.Subject(); @property({ type: String, }) public label: string = null; @property({ type: String, reflect: true, }) public key: string; @property({ attribute: false, }) public value: File[] = []; @property() public state: 'idle' | 'dragOver' | 'dropped' | 'uploading' | 'completed' = 'idle'; @property({ type: Boolean, }) public required: boolean = false; @property({ type: Boolean, }) public disabled: boolean = false; @property({ type: String, }) public buttonText: string = 'Upload File...'; constructor() { super(); } public static styles = [ cssManager.defaultStyles, css` :host { position: relative; display: grid; margin: 10px 0px; margin-bottom: 24px; } .hidden { display: none; } .maincontainer { color: ${cssManager.bdTheme('#333', '#ccc')}; } .label { font-size: 14px; margin-bottom: 5px; } .uploadButton { position: relative; cursor: pointer; padding: 8px; max-width: 600px; background: ${cssManager.bdTheme('#fafafa', '#333333')}; border-radius: 3px; text-align: center; } .uploadButton:hover { color: #fff; background: rgb(3, 155, 229); } .uploadButton::after { top: 2px; right: 2px; left: 2px; bottom: 2px; transform: scale3d(0.98, 0.9, 1); position: absolute; content: ''; display: block; border: 2px dashed rgba(255, 255, 255, 0); transition: all 0.2s; } .uploadButton.dragOver::after { transform: scale3d(1, 1, 1); border: 2px dashed rgba(255, 255, 255, 0.3); } .uploadCandidate { text-align: left; border-bottom: 1px dashed #444; color: ${cssManager.bdTheme('#666', '#ccc')}; padding: 8px; font-family: 'Roboto', 'Inter', sans-serif; } .uploadButton:hover .uploadCandidate { color: ${cssManager.bdTheme('#fff', '#fff')}; border-bottom: 1px dashed #fff; } .uploadCandidate:last-child { margin-bottom: 8px; } `, ]; public render(): TemplateResult { return html`
${this.label ? html`
${this.label}
` : null} ${this.value.map((fileArg) => html`
${fileArg.name} | ${fileArg.size}
`)}
${this.buttonText}
`; } public async openFileSelector() { const inputFile: HTMLInputElement = this.shadowRoot.querySelector('input[type="file"]'); inputFile.click(); this.state = 'idle'; this.buttonText = 'Upload more files...'; } public async updateValue(eventArg: Event) { const target: any = eventArg.target; this.value = target.value; this.changeSubject.next(this); } public firstUpdated() { const inputFile: HTMLInputElement = this.shadowRoot.querySelector('input[type="file"]'); inputFile.addEventListener('change', (event: Event) => { const target = event.target as HTMLInputElement; for (const file of Array.from(target.files)) { this.value.push(file); } this.requestUpdate(); console.log(`Got ${this.value.length} files!`); // Reset the input value to allow selecting the same file again if needed target.value = ''; }); // lets handle drag and drop const dropArea = this.shadowRoot.querySelector('.uploadButton'); const handlerFunction = (eventArg: DragEvent) => { eventArg.preventDefault(); switch (eventArg.type) { case 'dragover': this.state = 'dragOver'; this.buttonText = 'release to upload file...'; break; case 'dragleave': this.state = 'idle'; this.buttonText = 'Upload File...'; break; case 'drop': this.state = 'idle'; this.buttonText = 'Upload more files...'; } console.log(eventArg); for (const file of Array.from(eventArg.dataTransfer.files)) { this.value.push(file); this.requestUpdate(); } console.log(`Got ${this.value.length} files!`); }; dropArea.addEventListener('dragenter', handlerFunction, false); dropArea.addEventListener('dragleave', handlerFunction, false); dropArea.addEventListener('dragover', handlerFunction, false); dropArea.addEventListener('drop', handlerFunction, false); } }