@nuralyui/file-upload 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/demo/file-upload-demo.d.ts.map +1 -1
- package/demo/file-upload-demo.js +0 -1
- package/demo/file-upload-demo.js.map +1 -1
- package/file-upload.component.d.ts +1 -1
- package/file-upload.component.d.ts.map +1 -1
- package/file-upload.component.js +2 -2
- package/file-upload.component.js.map +1 -1
- package/package.json +1 -1
- package/styles.d.ts.map +1 -1
- package/styles.js +232 -173
- package/styles.js.map +1 -1
- package/demo/file-demo.d.ts +0 -18
- package/demo/file-demo.d.ts.map +0 -1
- package/demo/file-demo.js +0 -157
- package/demo/file-demo.js.map +0 -1
- package/file.component.d.ts +0 -36
- package/file.component.d.ts.map +0 -1
- package/file.component.js +0 -327
- package/file.component.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-upload-demo.d.ts","sourceRoot":"","sources":["../../../../src/components/file-upload/demo/file-upload-demo.ts"],"names":[],"mappings":"AACA;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAE5C,OAAO,0BAA0B,CAAC;AAGlC,qBACa,cAAe,SAAQ,UAAU;IACnC,KAAK,SAAU;IACf,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAa;IAEjD,YAAY;IAYrB,OAAO,CAAC,iBAAiB;IAkCzB,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,iBAAiB;cAMN,MAAM;IA0BzB,OAAgB,MAAM,
|
|
1
|
+
{"version":3,"file":"file-upload-demo.d.ts","sourceRoot":"","sources":["../../../../src/components/file-upload/demo/file-upload-demo.ts"],"names":[],"mappings":"AACA;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAE5C,OAAO,0BAA0B,CAAC;AAGlC,qBACa,cAAe,SAAQ,UAAU;IACnC,KAAK,SAAU;IACf,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAa;IAEjD,YAAY;IAYrB,OAAO,CAAC,iBAAiB;IAkCzB,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,iBAAiB;cAMN,MAAM;IA0BzB,OAAgB,MAAM,4BA4CpB;CACH"}
|
package/demo/file-upload-demo.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-upload-demo.js","sourceRoot":"","sources":["../../../../src/components/file-upload/demo/file-upload-demo.ts"],"names":[],"mappings":";;;;;;AAAA,uDAAuD;AACvD;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,0BAA0B,CAAC;AAIlC,IAAa,cAAc,GAA3B,MAAa,cAAe,SAAQ,UAAU;IAA9C;;QACW,UAAK,GAAG,MAAM,CAAC;QACf,oBAAe,GAAwB,IAAI,GAAG,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"file-upload-demo.js","sourceRoot":"","sources":["../../../../src/components/file-upload/demo/file-upload-demo.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n/**\n * @license\n * Copyright 2023 Google Laabidi Aymen\n * SPDX-License-Identifier: MIT\n */\nimport { LitElement, css, html } from 'lit';\nimport { customElement, state } from 'lit/decorators.js';\nimport \"../file-upload.component\";\nimport { UploadFile } from '../types';\n\n@customElement('hy-file-demo')\nexport class ElMeenuElement extends LitElement {\n @state() float = 'left';\n @state() uploadProcesses: Map<string, number> = new Map();\n\n override firstUpdated() {\n // Get reference to the file upload component\n const fileUpload : any = this.shadowRoot?.querySelector('nr-file-upload');\n \n if (fileUpload) {\n // Add event listeners to the component\n fileUpload.addEventListener('file-select', this._handleFileSelect.bind(this));\n fileUpload.addEventListener('file-remove', this._handleFileRemove.bind(this));\n fileUpload.addEventListener('file-exceed', this._handleFileExceed.bind(this));\n }\n }\n\n private _handleFileSelect(event: CustomEvent) {\n const { files } = event.detail;\n const fileUpload : any= this.shadowRoot?.querySelector('nr-file-upload');\n \n if (!fileUpload) return;\n \n files.forEach((file: UploadFile) => {\n // Update status to 'uploading'\n fileUpload.updateFileStatus(file.uid, 'uploading', 0);\n \n // Simulate upload process with interval\n const intervalId = window.setInterval(() => {\n const currentPercentage = file.percentage || 0;\n const percentage = Math.min(100, currentPercentage + 10);\n \n fileUpload.updateFileStatus(file.uid, 'uploading', percentage);\n \n if (percentage === 100) {\n window.clearInterval(intervalId);\n // Set file as successfully uploaded after a small delay\n setTimeout(() => {\n fileUpload.updateFileStatus(file.uid, 'success');\n }, 300);\n \n // Remove from tracking\n this.uploadProcesses.delete(file.uid);\n }\n }, 500);\n \n // Store the interval ID for potential cancellation\n this.uploadProcesses.set(file.uid, intervalId);\n });\n }\n\n private _handleFileRemove(event: CustomEvent) {\n const { file } = event.detail;\n console.log(`File removed: ${file.name}`);\n \n // Cancel upload process if it's still running\n if (this.uploadProcesses.has(file.uid)) {\n window.clearInterval(this.uploadProcesses.get(file.uid));\n this.uploadProcesses.delete(file.uid);\n }\n }\n\n private _handleFileExceed(event: CustomEvent) {\n const { files } = event.detail;\n console.warn(`Upload limit exceeded. Tried to upload ${files.length} additional files.`);\n // Could show a notification or alert here\n }\n\n protected override render() {\n return html`\n <div class=\"demo-container\">\n <h2>File Upload Demo</h2>\n <nr-file-upload\n accept=\"image/*\"\n multiple\n drag\n limit=\"5\"\n tip=\"JPG/PNG files up to 500kb\">\n </nr-file-upload>\n \n <div class=\"usage-info\">\n <h3>Usage:</h3>\n <ul>\n <li>Drag & drop files here</li>\n <li>Or click to select files</li>\n <li>Files will automatically start uploading</li>\n <li>Use the X button to remove files</li>\n <li>Click on eye icon to preview images</li>\n </ul>\n </div>\n </div>\n `;\n }\n\n static override styles = [\n css`\n :host {\n display: flex;\n flex-direction: column;\n align-items: center;\n font-family: sans-serif;\n }\n \n .demo-container {\n width: 100%;\n max-width: 700px;\n padding: 20px;\n border-radius: 8px;\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);\n background-color: #fff;\n }\n \n h2 {\n color: #333;\n margin-top: 0;\n }\n \n .usage-info {\n margin-top: 30px;\n padding: 15px;\n background-color: #f5f5f5;\n border-radius: 6px;\n }\n \n .usage-info h3 {\n margin-top: 0;\n color: #555;\n }\n \n ul {\n padding-left: 20px;\n }\n \n li {\n margin-bottom: 8px;\n color: #666;\n }\n `,\n ];\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-upload.component.d.ts","sourceRoot":"","sources":["../../../src/components/file-upload/file-upload.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAQ,cAAc,EAAE,MAAM,KAAK,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"file-upload.component.d.ts","sourceRoot":"","sources":["../../../src/components/file-upload/file-upload.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAQ,cAAc,EAAE,MAAM,KAAK,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIxC,qBACa,UAAW,SAAQ,UAAU;IACxC,OAAgB,MAAM,0BAAU;IAEJ,MAAM,EAAE,MAAM,CAAM;IACnB,QAAQ,EAAE,OAAO,CAAS;IAC1B,IAAI,EAAE,OAAO,CAAQ;IACtB,GAAG,EAAE,MAAM,CAAM;IACjB,KAAK,EAAE,MAAM,CAAK;IACjB,OAAO,EAAE,OAAO,CAAQ;IAE5C,QAAQ,EAAE,UAAU,EAAE,CAAM;IAC5B,UAAU,EAAE,OAAO,CAAS;IAC5B,YAAY,EAAE,OAAO,CAAS;IAC9B,YAAY,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IAC7C,WAAW,EAAE,MAAM,CAAK;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEnC,iBAAiB;IAUjB,oBAAoB;IAUpB,YAAY,CAAC,kBAAkB,EAAE,cAAc;IAKxD,OAAO,CAAC,oBAAoB,CAO1B;IAEF,OAAO,CAAC,oBAAoB,CAQ1B;IAEF,OAAO,CAAC,eAAe,CAOrB;IAEF,OAAO,CAAC,mBAAmB,CAYzB;IAEF,OAAO,CAAC,OAAO,CAWb;IAEF,OAAO,CAAC,QAAQ,CAEd;IAEF,OAAO,CAAC,SAAS,CAMf;YAEY,YAAY;IAmCnB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM;IAY7G,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,aAAa;IAIZ,MAAM;CAwGhB"}
|
package/file-upload.component.js
CHANGED
|
@@ -15,8 +15,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
15
15
|
};
|
|
16
16
|
import { LitElement, html } from 'lit';
|
|
17
17
|
import { customElement, property, state } from 'lit/decorators.js';
|
|
18
|
-
import { styles } from './styles';
|
|
19
|
-
import { fileUtils } from './utils';
|
|
18
|
+
import { styles } from './styles.js';
|
|
19
|
+
import { fileUtils } from './utils.js';
|
|
20
20
|
let FileUpload = class FileUpload extends LitElement {
|
|
21
21
|
constructor() {
|
|
22
22
|
super(...arguments);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-upload.component.js","sourceRoot":"","sources":["../../../src/components/file-upload/file-upload.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, PropertyValues } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { UploadFile } from './types';\nimport { styles } from './styles';\nimport { fileUtils } from './utils';\n\n@customElement('nr-file-upload')\nexport class FileUpload extends LitElement {\n static override styles = styles;\n\n @property({ type: String }) accept: string = '';\n @property({ type: Boolean }) multiple: boolean = false;\n @property({ type: Boolean }) drag: boolean = true;\n @property({ type: String }) tip: string = '';\n @property({ type: Number }) limit: number = 0;\n @property({ type: Boolean }) preview: boolean = true;\n\n @state() fileList: UploadFile[] = [];\n @state() isDragOver: boolean = false;\n @state() showDragArea: boolean = false;\n @state() inputElement: HTMLInputElement | null = null;\n @state() dragCounter: number = 0;\n @state() previewImage: string | null = null;\n\n override connectedCallback() {\n super.connectedCallback();\n if (this.drag) {\n document.addEventListener('dragenter', this._onDocumentDragEnter);\n document.addEventListener('dragleave', this._onDocumentDragLeave);\n document.addEventListener('drop', this._onDocumentDrop);\n document.addEventListener('dragover', this._onDocumentDragOver);\n }\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n if (this.drag) {\n document.removeEventListener('dragenter', this._onDocumentDragEnter);\n document.removeEventListener('dragleave', this._onDocumentDragLeave);\n document.removeEventListener('drop', this._onDocumentDrop);\n document.removeEventListener('dragover', this._onDocumentDragOver);\n }\n }\n\n override firstUpdated(_changedProperties: PropertyValues) {\n super.firstUpdated(_changedProperties);\n this.inputElement = this.shadowRoot?.querySelector('input[type=\"file\"]') || null;\n }\n\n private _onDocumentDragEnter = (e: DragEvent) => {\n e.preventDefault();\n this.dragCounter++;\n \n if (this.dragCounter === 1) {\n this.showDragArea = true;\n }\n };\n\n private _onDocumentDragLeave = (e: DragEvent) => {\n e.preventDefault();\n this.dragCounter--;\n \n if (this.dragCounter === 0) {\n this.showDragArea = false;\n this.isDragOver = false;\n }\n };\n\n private _onDocumentDrop = (e: DragEvent) => {\n if (e.target !== this && !this.contains(e.target as Node)) {\n e.preventDefault();\n this.dragCounter = 0;\n this.showDragArea = false;\n this.isDragOver = false;\n }\n };\n\n private _onDocumentDragOver = (e: DragEvent) => {\n e.preventDefault();\n \n // Determine if the drag is over our component\n const path = e.composedPath();\n const isOverComponent = path.includes(this);\n \n if (isOverComponent) {\n this.isDragOver = true;\n } else {\n this.isDragOver = false;\n }\n };\n\n private _onDrop = (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n \n this.dragCounter = 0;\n this.isDragOver = false;\n this.showDragArea = false;\n\n if (e.dataTransfer?.files) {\n this._handleFiles(e.dataTransfer.files);\n }\n };\n\n private _onClick = () => {\n this.inputElement?.click();\n };\n\n private _onChange = (e: Event) => {\n const target = e.target as HTMLInputElement;\n if (target.files) {\n this._handleFiles(target.files);\n target.value = ''; // Reset so same file can be selected again\n }\n };\n\n private async _handleFiles(files: FileList) {\n if (this.limit > 0 && this.fileList.length + files.length > this.limit) {\n this._dispatchEvent('exceed', { files });\n return;\n }\n\n const newFiles: UploadFile[] = [];\n\n for (const file of Array.from(files)) {\n const isImage = fileUtils.isImageFile(file);\n const fileObj: UploadFile = {\n name: file.name,\n size: fileUtils.formatFileSize(file.size),\n raw: file,\n status: 'ready',\n percentage: 0,\n uid: Date.now() + Math.random().toString(36).substring(2),\n isImage\n };\n\n // Create preview URL for images if preview is enabled\n if (this.preview && isImage) {\n fileObj.url = await fileUtils.createFilePreview(file);\n }\n\n this.fileList = [...this.fileList, fileObj];\n newFiles.push(fileObj);\n }\n\n this.requestUpdate();\n\n // Emit file-selected event with the new files\n this._dispatchEvent('select', { files: newFiles, fileList: this.fileList });\n }\n\n public updateFileStatus(uid: string, status: 'ready' | 'uploading' | 'success' | 'error', percentage?: number) {\n const file = this.fileList.find(f => f.uid === uid);\n \n if (file) {\n file.status = status;\n if (percentage !== undefined) {\n file.percentage = percentage;\n }\n this._updateFile(file);\n }\n }\n\n private _updateFile(updatedFile: UploadFile) {\n this.fileList = this.fileList.map(file =>\n file.uid === updatedFile.uid ? updatedFile : file\n );\n this.requestUpdate();\n }\n\n private _removeFile(uid: string) {\n const file = this.fileList.find(file => file.uid === uid);\n this.fileList = this.fileList.filter(file => file.uid !== uid);\n if (file) {\n this._dispatchEvent('remove', { file });\n }\n this.requestUpdate();\n }\n\n private _dispatchEvent(name: string, data: any) {\n this.dispatchEvent(new CustomEvent(`file-${name}`, {\n detail: data,\n bubbles: true,\n composed: true\n }));\n }\n\n private _showPreview(url: string) {\n this.previewImage = url;\n }\n\n private _closePreview() {\n this.previewImage = null;\n }\n\n override render() {\n return html`\n <div class=\"upload\" @drop=${this._onDrop} @dragover=${(e: DragEvent) => e.preventDefault()}>\n <input \n type=\"file\" \n class=\"hidden\" \n accept=${this.accept}\n ?multiple=${this.multiple}\n @change=${this._onChange}\n />\n\n ${this.showDragArea ? html`\n <div \n class=\"upload-dragger ${this.isDragOver ? 'is-dragover' : ''}\" \n @click=${this._onClick}\n >\n <div class=\"upload-icon\">\n <svg width=\"40\" height=\"40\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"></path>\n <polyline points=\"17 8 12 3 7 8\"></polyline>\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\"></line>\n </svg>\n </div>\n <div class=\"upload-text\">Drop file here or click to upload</div>\n ${this.tip ? html`<div class=\"upload-tip\">${this.tip}</div>` : ''}\n </div>\n ` : html`\n <button class=\"upload-button\" @click=${this._onClick}>Upload File</button>\n ${this.tip ? html`<div class=\"upload-tip\">${this.tip}</div>` : ''}\n `}\n\n <div class=\"file-list\">\n ${this.fileList.map(file => html`\n <div class=\"file-item\">\n ${file.isImage ? html`\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"></rect>\n <circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"></circle>\n <polyline points=\"21 15 16 10 5 21\"></polyline>\n </svg>\n ` : html`\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\"></path>\n <polyline points=\"14 2 14 8 20 8\"></polyline>\n </svg>\n `}\n <div class=\"file-name\">${file.name}</div>\n <div class=\"file-size\">${file.size}</div>\n <div class=\"file-status\">\n ${file.status === 'success' ? html`\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#67c23a\" stroke-width=\"2\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n ` : file.status === 'error' ? html`\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#f56c6c\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n ` : file.status === 'uploading' ? html`${file.percentage}%` : ''}\n </div>\n <div class=\"file-actions\">\n ${file.isImage && file.url ? html`\n <button class=\"preview-icon\" @click=${() => this._showPreview(file.url!)}>\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"></path>\n <circle cx=\"12\" cy=\"12\" r=\"3\"></circle>\n </svg>\n </button>\n ` : ''}\n <button @click=${() => this._removeFile(file.uid)}>\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n </div>\n ${file.status === 'uploading' ? html`\n <div class=\"progress-bar\">\n <div class=\"progress-inner\" style=\"width: ${file.percentage}%\"></div>\n </div>\n ` : ''}\n </div>\n ${this.preview && file.isImage && file.url ? html`\n <div class=\"file-preview\">\n <img \n class=\"image-preview\" \n src=\"${file.url}\" \n alt=\"${file.name}\" \n @click=${() => this._showPreview(file.url!)}\n />\n </div>\n ` : ''}\n `)}\n </div>\n\n ${this.previewImage ? html`\n <div class=\"preview-modal\" @click=${this._closePreview}>\n <button class=\"preview-close\">×</button>\n <img src=\"${this.previewImage}\" alt=\"Preview\" />\n </div>\n ` : ''}\n </div>\n `;\n }\n}"]}
|
|
1
|
+
{"version":3,"file":"file-upload.component.js","sourceRoot":"","sources":["../../../src/components/file-upload/file-upload.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, PropertyValues } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { UploadFile } from './types.js';\nimport { styles } from './styles.js';\nimport { fileUtils } from './utils.js';\n\n@customElement('nr-file-upload')\nexport class FileUpload extends LitElement {\n static override styles = styles;\n\n @property({ type: String }) accept: string = '';\n @property({ type: Boolean }) multiple: boolean = false;\n @property({ type: Boolean }) drag: boolean = true;\n @property({ type: String }) tip: string = '';\n @property({ type: Number }) limit: number = 0;\n @property({ type: Boolean }) preview: boolean = true;\n\n @state() fileList: UploadFile[] = [];\n @state() isDragOver: boolean = false;\n @state() showDragArea: boolean = false;\n @state() inputElement: HTMLInputElement | null = null;\n @state() dragCounter: number = 0;\n @state() previewImage: string | null = null;\n\n override connectedCallback() {\n super.connectedCallback();\n if (this.drag) {\n document.addEventListener('dragenter', this._onDocumentDragEnter);\n document.addEventListener('dragleave', this._onDocumentDragLeave);\n document.addEventListener('drop', this._onDocumentDrop);\n document.addEventListener('dragover', this._onDocumentDragOver);\n }\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n if (this.drag) {\n document.removeEventListener('dragenter', this._onDocumentDragEnter);\n document.removeEventListener('dragleave', this._onDocumentDragLeave);\n document.removeEventListener('drop', this._onDocumentDrop);\n document.removeEventListener('dragover', this._onDocumentDragOver);\n }\n }\n\n override firstUpdated(_changedProperties: PropertyValues) {\n super.firstUpdated(_changedProperties);\n this.inputElement = this.shadowRoot?.querySelector('input[type=\"file\"]') || null;\n }\n\n private _onDocumentDragEnter = (e: DragEvent) => {\n e.preventDefault();\n this.dragCounter++;\n \n if (this.dragCounter === 1) {\n this.showDragArea = true;\n }\n };\n\n private _onDocumentDragLeave = (e: DragEvent) => {\n e.preventDefault();\n this.dragCounter--;\n \n if (this.dragCounter === 0) {\n this.showDragArea = false;\n this.isDragOver = false;\n }\n };\n\n private _onDocumentDrop = (e: DragEvent) => {\n if (e.target !== this && !this.contains(e.target as Node)) {\n e.preventDefault();\n this.dragCounter = 0;\n this.showDragArea = false;\n this.isDragOver = false;\n }\n };\n\n private _onDocumentDragOver = (e: DragEvent) => {\n e.preventDefault();\n \n // Determine if the drag is over our component\n const path = e.composedPath();\n const isOverComponent = path.includes(this);\n \n if (isOverComponent) {\n this.isDragOver = true;\n } else {\n this.isDragOver = false;\n }\n };\n\n private _onDrop = (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n \n this.dragCounter = 0;\n this.isDragOver = false;\n this.showDragArea = false;\n\n if (e.dataTransfer?.files) {\n this._handleFiles(e.dataTransfer.files);\n }\n };\n\n private _onClick = () => {\n this.inputElement?.click();\n };\n\n private _onChange = (e: Event) => {\n const target = e.target as HTMLInputElement;\n if (target.files) {\n this._handleFiles(target.files);\n target.value = ''; // Reset so same file can be selected again\n }\n };\n\n private async _handleFiles(files: FileList) {\n if (this.limit > 0 && this.fileList.length + files.length > this.limit) {\n this._dispatchEvent('exceed', { files });\n return;\n }\n\n const newFiles: UploadFile[] = [];\n\n for (const file of Array.from(files)) {\n const isImage = fileUtils.isImageFile(file);\n const fileObj: UploadFile = {\n name: file.name,\n size: fileUtils.formatFileSize(file.size),\n raw: file,\n status: 'ready',\n percentage: 0,\n uid: Date.now() + Math.random().toString(36).substring(2),\n isImage\n };\n\n // Create preview URL for images if preview is enabled\n if (this.preview && isImage) {\n fileObj.url = await fileUtils.createFilePreview(file);\n }\n\n this.fileList = [...this.fileList, fileObj];\n newFiles.push(fileObj);\n }\n\n this.requestUpdate();\n\n // Emit file-selected event with the new files\n this._dispatchEvent('select', { files: newFiles, fileList: this.fileList });\n }\n\n public updateFileStatus(uid: string, status: 'ready' | 'uploading' | 'success' | 'error', percentage?: number) {\n const file = this.fileList.find(f => f.uid === uid);\n \n if (file) {\n file.status = status;\n if (percentage !== undefined) {\n file.percentage = percentage;\n }\n this._updateFile(file);\n }\n }\n\n private _updateFile(updatedFile: UploadFile) {\n this.fileList = this.fileList.map(file =>\n file.uid === updatedFile.uid ? updatedFile : file\n );\n this.requestUpdate();\n }\n\n private _removeFile(uid: string) {\n const file = this.fileList.find(file => file.uid === uid);\n this.fileList = this.fileList.filter(file => file.uid !== uid);\n if (file) {\n this._dispatchEvent('remove', { file });\n }\n this.requestUpdate();\n }\n\n private _dispatchEvent(name: string, data: any) {\n this.dispatchEvent(new CustomEvent(`file-${name}`, {\n detail: data,\n bubbles: true,\n composed: true\n }));\n }\n\n private _showPreview(url: string) {\n this.previewImage = url;\n }\n\n private _closePreview() {\n this.previewImage = null;\n }\n\n override render() {\n return html`\n <div class=\"upload\" @drop=${this._onDrop} @dragover=${(e: DragEvent) => e.preventDefault()}>\n <input \n type=\"file\" \n class=\"hidden\" \n accept=${this.accept}\n ?multiple=${this.multiple}\n @change=${this._onChange}\n />\n\n ${this.showDragArea ? html`\n <div \n class=\"upload-dragger ${this.isDragOver ? 'is-dragover' : ''}\" \n @click=${this._onClick}\n >\n <div class=\"upload-icon\">\n <svg width=\"40\" height=\"40\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"></path>\n <polyline points=\"17 8 12 3 7 8\"></polyline>\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\"></line>\n </svg>\n </div>\n <div class=\"upload-text\">Drop file here or click to upload</div>\n ${this.tip ? html`<div class=\"upload-tip\">${this.tip}</div>` : ''}\n </div>\n ` : html`\n <button class=\"upload-button\" @click=${this._onClick}>Upload File</button>\n ${this.tip ? html`<div class=\"upload-tip\">${this.tip}</div>` : ''}\n `}\n\n <div class=\"file-list\">\n ${this.fileList.map(file => html`\n <div class=\"file-item\">\n ${file.isImage ? html`\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"></rect>\n <circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"></circle>\n <polyline points=\"21 15 16 10 5 21\"></polyline>\n </svg>\n ` : html`\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\"></path>\n <polyline points=\"14 2 14 8 20 8\"></polyline>\n </svg>\n `}\n <div class=\"file-name\">${file.name}</div>\n <div class=\"file-size\">${file.size}</div>\n <div class=\"file-status\">\n ${file.status === 'success' ? html`\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#67c23a\" stroke-width=\"2\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n ` : file.status === 'error' ? html`\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#f56c6c\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n ` : file.status === 'uploading' ? html`${file.percentage}%` : ''}\n </div>\n <div class=\"file-actions\">\n ${file.isImage && file.url ? html`\n <button class=\"preview-icon\" @click=${() => this._showPreview(file.url!)}>\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"></path>\n <circle cx=\"12\" cy=\"12\" r=\"3\"></circle>\n </svg>\n </button>\n ` : ''}\n <button @click=${() => this._removeFile(file.uid)}>\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n </div>\n ${file.status === 'uploading' ? html`\n <div class=\"progress-bar\">\n <div class=\"progress-inner\" style=\"width: ${file.percentage}%\"></div>\n </div>\n ` : ''}\n </div>\n ${this.preview && file.isImage && file.url ? html`\n <div class=\"file-preview\">\n <img \n class=\"image-preview\" \n src=\"${file.url}\" \n alt=\"${file.name}\" \n @click=${() => this._showPreview(file.url!)}\n />\n </div>\n ` : ''}\n `)}\n </div>\n\n ${this.previewImage ? html`\n <div class=\"preview-modal\" @click=${this._closePreview}>\n <button class=\"preview-close\">×</button>\n <img src=\"${this.previewImage}\" alt=\"Preview\" />\n </div>\n ` : ''}\n </div>\n `;\n }\n}"]}
|
package/package.json
CHANGED
package/styles.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../src/components/file-upload/styles.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"styles.d.ts","sourceRoot":"","sources":["../../../src/components/file-upload/styles.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,MAAM,yBAmQlB,CAAC"}
|
package/styles.js
CHANGED
|
@@ -1,203 +1,262 @@
|
|
|
1
1
|
import { css } from 'lit';
|
|
2
2
|
export const styles = css `
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
:host {
|
|
4
|
+
display: block;
|
|
5
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
6
|
+
}
|
|
7
|
+
.upload {
|
|
8
|
+
width: 100%;
|
|
9
|
+
}
|
|
10
|
+
.upload-dragger {
|
|
11
|
+
background-color: #f8f9fa;
|
|
12
|
+
border: 1px dashed #d9d9d9;
|
|
13
|
+
border-radius: 6px;
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
width: 100%;
|
|
16
|
+
height: 180px;
|
|
17
|
+
text-align: center;
|
|
18
|
+
cursor: pointer;
|
|
19
|
+
position: relative;
|
|
20
|
+
overflow: hidden;
|
|
21
|
+
transition: border-color 0.3s;
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-direction: column;
|
|
24
|
+
justify-content: center;
|
|
25
|
+
align-items: center;
|
|
26
|
+
}
|
|
27
|
+
.upload-dragger:hover {
|
|
28
|
+
border-color: #409eff;
|
|
29
|
+
}
|
|
30
|
+
.upload-dragger.is-dragover {
|
|
31
|
+
background-color: rgba(64, 158, 255, 0.06);
|
|
32
|
+
border-color: #409eff;
|
|
33
|
+
}
|
|
34
|
+
.upload-icon {
|
|
35
|
+
font-size: 28px;
|
|
36
|
+
color: #c0c4cc;
|
|
37
|
+
margin-bottom: 8px;
|
|
38
|
+
}
|
|
39
|
+
.upload-text {
|
|
40
|
+
color: #606266;
|
|
41
|
+
font-size: 14px;
|
|
42
|
+
text-align: center;
|
|
43
|
+
padding: 0 12px;
|
|
44
|
+
}
|
|
45
|
+
.upload-tip {
|
|
46
|
+
font-size: 12px;
|
|
47
|
+
color: #909399;
|
|
48
|
+
margin-top: 7px;
|
|
49
|
+
padding: 0 12px;
|
|
50
|
+
}
|
|
51
|
+
.upload-button {
|
|
52
|
+
padding: 8px 16px;
|
|
53
|
+
background-color: #409eff;
|
|
54
|
+
color: white;
|
|
55
|
+
border: none;
|
|
56
|
+
border-radius: 4px;
|
|
57
|
+
cursor: pointer;
|
|
58
|
+
font-size: 14px;
|
|
59
|
+
transition: background-color 0.3s;
|
|
60
|
+
}
|
|
61
|
+
.upload-button:hover {
|
|
62
|
+
background-color: #66b1ff;
|
|
63
|
+
}
|
|
64
|
+
.file-list {
|
|
65
|
+
margin-top: 10px;
|
|
66
|
+
width: 100%;
|
|
67
|
+
}
|
|
68
|
+
.file-item {
|
|
69
|
+
display: flex;
|
|
70
|
+
align-items: center;
|
|
71
|
+
margin-bottom: 8px;
|
|
72
|
+
transition: all 0.3s;
|
|
73
|
+
padding: 8px;
|
|
74
|
+
border-radius: 4px;
|
|
75
|
+
gap: 10px; /* Add consistent spacing between items */
|
|
76
|
+
}
|
|
77
|
+
.file-item:hover {
|
|
78
|
+
background-color: #f8f9fa;
|
|
79
|
+
}
|
|
80
|
+
.file-name {
|
|
81
|
+
flex: 1;
|
|
82
|
+
white-space: nowrap;
|
|
83
|
+
overflow: hidden;
|
|
84
|
+
text-overflow: ellipsis;
|
|
85
|
+
color: #606266;
|
|
86
|
+
min-width: 0;
|
|
87
|
+
}
|
|
88
|
+
.file-size {
|
|
89
|
+
color: #909399;
|
|
90
|
+
font-size: 12px;
|
|
91
|
+
flex-shrink: 0; /* Prevent shrinking */
|
|
92
|
+
}
|
|
93
|
+
.file-status {
|
|
94
|
+
display: flex;
|
|
95
|
+
align-items: center;
|
|
96
|
+
flex-shrink: 0; /* Prevent shrinking */
|
|
97
|
+
}
|
|
98
|
+
.file-actions {
|
|
99
|
+
display: flex;
|
|
100
|
+
gap: 4px;
|
|
101
|
+
flex-shrink: 0; /* Prevent shrinking */
|
|
102
|
+
}
|
|
103
|
+
.file-actions button {
|
|
104
|
+
background: none;
|
|
105
|
+
border: none;
|
|
106
|
+
padding: 4px;
|
|
107
|
+
cursor: pointer;
|
|
108
|
+
color: #909399;
|
|
109
|
+
}
|
|
110
|
+
.file-actions button:hover {
|
|
111
|
+
color: #409eff;
|
|
112
|
+
}
|
|
7
113
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
114
|
+
/* Progress bar styles - fixed to ensure full width */
|
|
115
|
+
.progress-bar {
|
|
116
|
+
height: 2px;
|
|
117
|
+
width: 100%;
|
|
118
|
+
background-color: #e6e6e6;
|
|
119
|
+
margin-top: 4px;
|
|
120
|
+
position: relative;
|
|
121
|
+
border-radius: 2px;
|
|
122
|
+
overflow: hidden;
|
|
123
|
+
}
|
|
124
|
+
.progress-inner {
|
|
125
|
+
height: 100%;
|
|
126
|
+
background-color: #409eff;
|
|
127
|
+
position: absolute;
|
|
128
|
+
left: 0;
|
|
129
|
+
top: 0;
|
|
130
|
+
transition: width 0.3s ease;
|
|
131
|
+
}
|
|
11
132
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
cursor: pointer;
|
|
21
|
-
position: relative;
|
|
22
|
-
overflow: hidden;
|
|
23
|
-
transition: border-color .3s;
|
|
24
|
-
display: flex;
|
|
25
|
-
flex-direction: column;
|
|
26
|
-
justify-content: center;
|
|
27
|
-
align-items: center;
|
|
28
|
-
}
|
|
133
|
+
/* Progress percentage indicator */
|
|
134
|
+
.progress-percentage {
|
|
135
|
+
position: absolute;
|
|
136
|
+
right: 0;
|
|
137
|
+
top: -18px;
|
|
138
|
+
font-size: 12px;
|
|
139
|
+
color: #409eff;
|
|
140
|
+
}
|
|
29
141
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
142
|
+
.hidden {
|
|
143
|
+
display: none;
|
|
144
|
+
}
|
|
145
|
+
.success {
|
|
146
|
+
color: #67c23a;
|
|
147
|
+
}
|
|
148
|
+
.error {
|
|
149
|
+
color: #f56c6c;
|
|
150
|
+
}
|
|
151
|
+
.icon-delete {
|
|
152
|
+
color: #f56c6c;
|
|
153
|
+
}
|
|
154
|
+
.file-preview {
|
|
155
|
+
width: 100%;
|
|
156
|
+
margin-top: 4px;
|
|
157
|
+
}
|
|
158
|
+
.image-preview {
|
|
159
|
+
display: block;
|
|
160
|
+
max-width: 100%;
|
|
161
|
+
max-height: 200px;
|
|
162
|
+
border-radius: 4px;
|
|
163
|
+
object-fit: contain;
|
|
164
|
+
cursor: zoom-in;
|
|
165
|
+
}
|
|
166
|
+
.preview-modal {
|
|
167
|
+
position: fixed;
|
|
168
|
+
top: 0;
|
|
169
|
+
left: 0;
|
|
170
|
+
width: 100%;
|
|
171
|
+
height: 100%;
|
|
172
|
+
background-color: rgba(0, 0, 0, 0.7);
|
|
173
|
+
display: flex;
|
|
174
|
+
justify-content: center;
|
|
175
|
+
align-items: center;
|
|
176
|
+
z-index: 1000;
|
|
177
|
+
}
|
|
178
|
+
.preview-modal img {
|
|
179
|
+
max-width: 90%;
|
|
180
|
+
max-height: 90%;
|
|
181
|
+
object-fit: contain;
|
|
182
|
+
}
|
|
183
|
+
.preview-close {
|
|
184
|
+
position: absolute;
|
|
185
|
+
top: 20px;
|
|
186
|
+
right: 20px;
|
|
187
|
+
color: white;
|
|
188
|
+
font-size: 30px;
|
|
189
|
+
background: none;
|
|
190
|
+
border: none;
|
|
191
|
+
cursor: pointer;
|
|
192
|
+
}
|
|
193
|
+
.preview-icon {
|
|
194
|
+
padding: 4px;
|
|
195
|
+
color: #409eff;
|
|
196
|
+
cursor: zoom-in;
|
|
197
|
+
}
|
|
33
198
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
199
|
+
/* File item container with progress bar */
|
|
200
|
+
.file-container {
|
|
201
|
+
width: 100%;
|
|
202
|
+
position: relative;
|
|
203
|
+
}
|
|
38
204
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
205
|
+
/* Responsive styles */
|
|
206
|
+
@media (max-width: 600px) {
|
|
207
|
+
.upload-dragger {
|
|
208
|
+
height: 140px;
|
|
209
|
+
padding: 12px;
|
|
43
210
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
color: #606266;
|
|
47
|
-
font-size: 14px;
|
|
48
|
-
text-align: center;
|
|
211
|
+
.upload-icon {
|
|
212
|
+
font-size: 24px;
|
|
49
213
|
}
|
|
50
|
-
|
|
214
|
+
.upload-text,
|
|
51
215
|
.upload-tip {
|
|
52
|
-
font-size:
|
|
53
|
-
color: #909399;
|
|
54
|
-
margin-top: 7px;
|
|
216
|
+
font-size: 13px;
|
|
55
217
|
}
|
|
56
|
-
|
|
57
|
-
.upload-button {
|
|
58
|
-
padding: 8px 16px;
|
|
59
|
-
background-color: #409eff;
|
|
60
|
-
color: white;
|
|
61
|
-
border: none;
|
|
62
|
-
border-radius: 4px;
|
|
63
|
-
cursor: pointer;
|
|
64
|
-
font-size: 14px;
|
|
65
|
-
transition: background-color 0.3s;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
.upload-button:hover {
|
|
69
|
-
background-color: #66b1ff;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.file-list {
|
|
73
|
-
margin-top: 10px;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
218
|
.file-item {
|
|
77
|
-
display:
|
|
219
|
+
display: grid;
|
|
220
|
+
grid-template-columns: auto 1fr;
|
|
221
|
+
grid-template-areas:
|
|
222
|
+
"icon filename"
|
|
223
|
+
"size status"
|
|
224
|
+
"progress progress"
|
|
225
|
+
"actions actions";
|
|
226
|
+
gap: 4px 8px;
|
|
78
227
|
align-items: center;
|
|
79
|
-
margin-bottom: 8px;
|
|
80
|
-
transition: all .3s;
|
|
81
|
-
padding: 8px;
|
|
82
|
-
border-radius: 4px;
|
|
83
228
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
229
|
+
.file-item > svg:first-child {
|
|
230
|
+
grid-area: icon;
|
|
231
|
+
align-self: start;
|
|
87
232
|
}
|
|
88
|
-
|
|
89
233
|
.file-name {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
234
|
+
grid-area: filename;
|
|
235
|
+
margin: 0;
|
|
236
|
+
padding: 2px 0;
|
|
93
237
|
}
|
|
94
|
-
|
|
95
238
|
.file-size {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
margin-right: 10px;
|
|
239
|
+
grid-area: size;
|
|
240
|
+
margin: 0;
|
|
99
241
|
}
|
|
100
|
-
|
|
101
242
|
.file-status {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
.file-actions {
|
|
107
|
-
margin-left: 10px;
|
|
108
|
-
display: flex;
|
|
109
|
-
gap: 4px;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
.file-actions button {
|
|
113
|
-
background: none;
|
|
114
|
-
border: none;
|
|
115
|
-
padding: 4px;
|
|
116
|
-
cursor: pointer;
|
|
117
|
-
color: #909399;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
.file-actions button:hover {
|
|
121
|
-
color: #409eff;
|
|
243
|
+
grid-area: status;
|
|
244
|
+
justify-self: end;
|
|
122
245
|
}
|
|
123
|
-
|
|
124
246
|
.progress-bar {
|
|
125
|
-
|
|
247
|
+
grid-area: progress;
|
|
126
248
|
width: 100%;
|
|
127
|
-
background-color: #e6e6e6;
|
|
128
|
-
margin-top: 4px;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
.progress-inner {
|
|
132
|
-
height: 100%;
|
|
133
|
-
background-color: #409eff;
|
|
134
|
-
transition: width .3s;
|
|
135
249
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
.success {
|
|
142
|
-
color: #67c23a;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
.error {
|
|
146
|
-
color: #f56c6c;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
.icon-delete {
|
|
150
|
-
color: #f56c6c;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
.file-preview {
|
|
250
|
+
.file-actions {
|
|
251
|
+
grid-area: actions;
|
|
252
|
+
margin: 4px 0 0 0;
|
|
253
|
+
justify-content: flex-end;
|
|
154
254
|
width: 100%;
|
|
155
|
-
margin-top: 4px;
|
|
156
255
|
}
|
|
157
|
-
|
|
158
|
-
.image-preview {
|
|
159
|
-
display: block;
|
|
160
|
-
max-width: 100%;
|
|
161
|
-
max-height: 200px;
|
|
162
|
-
border-radius: 4px;
|
|
163
|
-
object-fit: contain;
|
|
164
|
-
cursor: zoom-in;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
.preview-modal {
|
|
168
|
-
position: fixed;
|
|
169
|
-
top: 0;
|
|
170
|
-
left: 0;
|
|
256
|
+
.upload-button {
|
|
171
257
|
width: 100%;
|
|
172
|
-
|
|
173
|
-
background-color: rgba(0, 0, 0, 0.7);
|
|
174
|
-
display: flex;
|
|
175
|
-
justify-content: center;
|
|
176
|
-
align-items: center;
|
|
177
|
-
z-index: 1000;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
.preview-modal img {
|
|
181
|
-
max-width: 90%;
|
|
182
|
-
max-height: 90%;
|
|
183
|
-
object-fit: contain;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
.preview-close {
|
|
187
|
-
position: absolute;
|
|
188
|
-
top: 20px;
|
|
189
|
-
right: 20px;
|
|
190
|
-
color: white;
|
|
191
|
-
font-size: 30px;
|
|
192
|
-
background: none;
|
|
193
|
-
border: none;
|
|
194
|
-
cursor: pointer;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
.preview-icon {
|
|
198
|
-
padding: 4px;
|
|
199
|
-
color: #409eff;
|
|
200
|
-
cursor: zoom-in;
|
|
258
|
+
font-size: 16px;
|
|
201
259
|
}
|
|
260
|
+
}
|
|
202
261
|
`;
|
|
203
262
|
//# sourceMappingURL=styles.js.map
|
package/styles.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../src/components/file-upload/styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"styles.js","sourceRoot":"","sources":["../../../src/components/file-upload/styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAC1B,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmQxB,CAAC","sourcesContent":["import { css } from 'lit';\nexport const styles = css`\n:host {\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;\n}\n.upload {\n width: 100%;\n}\n.upload-dragger {\n background-color: #f8f9fa;\n border: 1px dashed #d9d9d9;\n border-radius: 6px;\n box-sizing: border-box;\n width: 100%;\n height: 180px;\n text-align: center;\n cursor: pointer;\n position: relative;\n overflow: hidden;\n transition: border-color 0.3s;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n}\n.upload-dragger:hover {\n border-color: #409eff;\n}\n.upload-dragger.is-dragover {\n background-color: rgba(64, 158, 255, 0.06);\n border-color: #409eff;\n}\n.upload-icon {\n font-size: 28px;\n color: #c0c4cc;\n margin-bottom: 8px;\n}\n.upload-text {\n color: #606266;\n font-size: 14px;\n text-align: center;\n padding: 0 12px;\n}\n.upload-tip {\n font-size: 12px;\n color: #909399;\n margin-top: 7px;\n padding: 0 12px;\n}\n.upload-button {\n padding: 8px 16px;\n background-color: #409eff;\n color: white;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n font-size: 14px;\n transition: background-color 0.3s;\n}\n.upload-button:hover {\n background-color: #66b1ff;\n}\n.file-list {\n margin-top: 10px;\n width: 100%;\n}\n.file-item {\n display: flex;\n align-items: center;\n margin-bottom: 8px;\n transition: all 0.3s;\n padding: 8px;\n border-radius: 4px;\n gap: 10px; /* Add consistent spacing between items */\n}\n.file-item:hover {\n background-color: #f8f9fa;\n}\n.file-name {\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n color: #606266;\n min-width: 0;\n}\n.file-size {\n color: #909399;\n font-size: 12px;\n flex-shrink: 0; /* Prevent shrinking */\n}\n.file-status {\n display: flex;\n align-items: center;\n flex-shrink: 0; /* Prevent shrinking */\n}\n.file-actions {\n display: flex;\n gap: 4px;\n flex-shrink: 0; /* Prevent shrinking */\n}\n.file-actions button {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: #909399;\n}\n.file-actions button:hover {\n color: #409eff;\n}\n\n/* Progress bar styles - fixed to ensure full width */\n.progress-bar {\n height: 2px;\n width: 100%;\n background-color: #e6e6e6;\n margin-top: 4px;\n position: relative;\n border-radius: 2px;\n overflow: hidden;\n}\n.progress-inner {\n height: 100%;\n background-color: #409eff;\n position: absolute;\n left: 0;\n top: 0;\n transition: width 0.3s ease;\n}\n\n/* Progress percentage indicator */\n.progress-percentage {\n position: absolute;\n right: 0;\n top: -18px;\n font-size: 12px;\n color: #409eff;\n}\n\n.hidden {\n display: none;\n}\n.success {\n color: #67c23a;\n}\n.error {\n color: #f56c6c;\n}\n.icon-delete {\n color: #f56c6c;\n}\n.file-preview {\n width: 100%;\n margin-top: 4px;\n}\n.image-preview {\n display: block;\n max-width: 100%;\n max-height: 200px;\n border-radius: 4px;\n object-fit: contain;\n cursor: zoom-in;\n}\n.preview-modal {\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background-color: rgba(0, 0, 0, 0.7);\n display: flex;\n justify-content: center;\n align-items: center;\n z-index: 1000;\n}\n.preview-modal img {\n max-width: 90%;\n max-height: 90%;\n object-fit: contain;\n}\n.preview-close {\n position: absolute;\n top: 20px;\n right: 20px;\n color: white;\n font-size: 30px;\n background: none;\n border: none;\n cursor: pointer;\n}\n.preview-icon {\n padding: 4px;\n color: #409eff;\n cursor: zoom-in;\n}\n\n/* File item container with progress bar */\n.file-container {\n width: 100%;\n position: relative;\n}\n\n/* Responsive styles */\n@media (max-width: 600px) {\n .upload-dragger {\n height: 140px;\n padding: 12px;\n }\n .upload-icon {\n font-size: 24px;\n }\n .upload-text,\n .upload-tip {\n font-size: 13px;\n }\n .file-item {\n display: grid;\n grid-template-columns: auto 1fr;\n grid-template-areas: \n \"icon filename\"\n \"size status\"\n \"progress progress\"\n \"actions actions\";\n gap: 4px 8px;\n align-items: center;\n }\n .file-item > svg:first-child {\n grid-area: icon;\n align-self: start;\n }\n .file-name {\n grid-area: filename;\n margin: 0;\n padding: 2px 0;\n }\n .file-size {\n grid-area: size;\n margin: 0;\n }\n .file-status {\n grid-area: status;\n justify-self: end;\n }\n .progress-bar {\n grid-area: progress;\n width: 100%;\n }\n .file-actions {\n grid-area: actions;\n margin: 4px 0 0 0;\n justify-content: flex-end;\n width: 100%;\n }\n .upload-button {\n width: 100%;\n font-size: 16px;\n }\n}\n`;"]}
|
package/demo/file-demo.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @license
|
|
3
|
-
* Copyright 2023 Google Laabidi Aymen
|
|
4
|
-
* SPDX-License-Identifier: MIT
|
|
5
|
-
*/
|
|
6
|
-
import { LitElement } from 'lit';
|
|
7
|
-
import "../file-upload.component";
|
|
8
|
-
export declare class ElMeenuElement extends LitElement {
|
|
9
|
-
float: string;
|
|
10
|
-
uploadProcesses: Map<string, number>;
|
|
11
|
-
firstUpdated(): void;
|
|
12
|
-
private _handleFileSelect;
|
|
13
|
-
private _handleFileRemove;
|
|
14
|
-
private _handleFileExceed;
|
|
15
|
-
protected render(): import("lit").TemplateResult<1>;
|
|
16
|
-
static styles: import("lit").CSSResult[];
|
|
17
|
-
}
|
|
18
|
-
//# sourceMappingURL=file-demo.d.ts.map
|
package/demo/file-demo.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"file-demo.d.ts","sourceRoot":"","sources":["../../../../src/components/file-upload/demo/file-demo.ts"],"names":[],"mappings":"AACA;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAa,MAAM,KAAK,CAAC;AAE5C,OAAO,0BAA0B,CAAC;AAGlC,qBACa,cAAe,SAAQ,UAAU;IACnC,KAAK,SAAU;IACf,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAa;IAEjD,YAAY;IAYrB,OAAO,CAAC,iBAAiB;IAkCzB,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,iBAAiB;cAMN,MAAM;IA0BzB,OAAgB,MAAM,4BA6CpB;CACH"}
|
package/demo/file-demo.js
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
8
|
-
/**
|
|
9
|
-
* @license
|
|
10
|
-
* Copyright 2023 Google Laabidi Aymen
|
|
11
|
-
* SPDX-License-Identifier: MIT
|
|
12
|
-
*/
|
|
13
|
-
import { LitElement, css, html } from 'lit';
|
|
14
|
-
import { customElement, state } from 'lit/decorators.js';
|
|
15
|
-
import "../file-upload.component";
|
|
16
|
-
let ElMeenuElement = class ElMeenuElement extends LitElement {
|
|
17
|
-
constructor() {
|
|
18
|
-
super(...arguments);
|
|
19
|
-
this.float = 'left';
|
|
20
|
-
this.uploadProcesses = new Map();
|
|
21
|
-
}
|
|
22
|
-
firstUpdated() {
|
|
23
|
-
var _a;
|
|
24
|
-
// Get reference to the file upload component
|
|
25
|
-
const fileUpload = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('nr-file-upload');
|
|
26
|
-
if (fileUpload) {
|
|
27
|
-
// Add event listeners to the component
|
|
28
|
-
fileUpload.addEventListener('file-select', this._handleFileSelect.bind(this));
|
|
29
|
-
fileUpload.addEventListener('file-remove', this._handleFileRemove.bind(this));
|
|
30
|
-
fileUpload.addEventListener('file-exceed', this._handleFileExceed.bind(this));
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
_handleFileSelect(event) {
|
|
34
|
-
var _a;
|
|
35
|
-
const { files } = event.detail;
|
|
36
|
-
const fileUpload = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('nr-file-upload');
|
|
37
|
-
if (!fileUpload)
|
|
38
|
-
return;
|
|
39
|
-
files.forEach((file) => {
|
|
40
|
-
// Update status to 'uploading'
|
|
41
|
-
fileUpload.updateFileStatus(file.uid, 'uploading', 0);
|
|
42
|
-
// Simulate upload process with interval
|
|
43
|
-
const intervalId = window.setInterval(() => {
|
|
44
|
-
const currentPercentage = file.percentage || 0;
|
|
45
|
-
const percentage = Math.min(100, currentPercentage + 10);
|
|
46
|
-
fileUpload.updateFileStatus(file.uid, 'uploading', percentage);
|
|
47
|
-
if (percentage === 100) {
|
|
48
|
-
window.clearInterval(intervalId);
|
|
49
|
-
// Set file as successfully uploaded after a small delay
|
|
50
|
-
setTimeout(() => {
|
|
51
|
-
fileUpload.updateFileStatus(file.uid, 'success');
|
|
52
|
-
}, 300);
|
|
53
|
-
// Remove from tracking
|
|
54
|
-
this.uploadProcesses.delete(file.uid);
|
|
55
|
-
}
|
|
56
|
-
}, 500);
|
|
57
|
-
// Store the interval ID for potential cancellation
|
|
58
|
-
this.uploadProcesses.set(file.uid, intervalId);
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
_handleFileRemove(event) {
|
|
62
|
-
const { file } = event.detail;
|
|
63
|
-
console.log(`File removed: ${file.name}`);
|
|
64
|
-
// Cancel upload process if it's still running
|
|
65
|
-
if (this.uploadProcesses.has(file.uid)) {
|
|
66
|
-
window.clearInterval(this.uploadProcesses.get(file.uid));
|
|
67
|
-
this.uploadProcesses.delete(file.uid);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
_handleFileExceed(event) {
|
|
71
|
-
const { files } = event.detail;
|
|
72
|
-
console.warn(`Upload limit exceeded. Tried to upload ${files.length} additional files.`);
|
|
73
|
-
// Could show a notification or alert here
|
|
74
|
-
}
|
|
75
|
-
render() {
|
|
76
|
-
return html `
|
|
77
|
-
<div class="demo-container">
|
|
78
|
-
<h2>File Upload Demo</h2>
|
|
79
|
-
<nr-file-upload
|
|
80
|
-
accept="image/*"
|
|
81
|
-
multiple
|
|
82
|
-
drag
|
|
83
|
-
limit="5"
|
|
84
|
-
tip="JPG/PNG files up to 500kb">
|
|
85
|
-
</nr-file-upload>
|
|
86
|
-
|
|
87
|
-
<div class="usage-info">
|
|
88
|
-
<h3>Usage:</h3>
|
|
89
|
-
<ul>
|
|
90
|
-
<li>Drag & drop files here</li>
|
|
91
|
-
<li>Or click to select files</li>
|
|
92
|
-
<li>Files will automatically start uploading</li>
|
|
93
|
-
<li>Use the X button to remove files</li>
|
|
94
|
-
<li>Click on eye icon to preview images</li>
|
|
95
|
-
</ul>
|
|
96
|
-
</div>
|
|
97
|
-
</div>
|
|
98
|
-
`;
|
|
99
|
-
}
|
|
100
|
-
};
|
|
101
|
-
ElMeenuElement.styles = [
|
|
102
|
-
css `
|
|
103
|
-
:host {
|
|
104
|
-
width: 800px;
|
|
105
|
-
display: flex;
|
|
106
|
-
flex-direction: column;
|
|
107
|
-
align-items: center;
|
|
108
|
-
font-family: sans-serif;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
.demo-container {
|
|
112
|
-
width: 100%;
|
|
113
|
-
max-width: 700px;
|
|
114
|
-
padding: 20px;
|
|
115
|
-
border-radius: 8px;
|
|
116
|
-
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
|
117
|
-
background-color: #fff;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
h2 {
|
|
121
|
-
color: #333;
|
|
122
|
-
margin-top: 0;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
.usage-info {
|
|
126
|
-
margin-top: 30px;
|
|
127
|
-
padding: 15px;
|
|
128
|
-
background-color: #f5f5f5;
|
|
129
|
-
border-radius: 6px;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
.usage-info h3 {
|
|
133
|
-
margin-top: 0;
|
|
134
|
-
color: #555;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
ul {
|
|
138
|
-
padding-left: 20px;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
li {
|
|
142
|
-
margin-bottom: 8px;
|
|
143
|
-
color: #666;
|
|
144
|
-
}
|
|
145
|
-
`,
|
|
146
|
-
];
|
|
147
|
-
__decorate([
|
|
148
|
-
state()
|
|
149
|
-
], ElMeenuElement.prototype, "float", void 0);
|
|
150
|
-
__decorate([
|
|
151
|
-
state()
|
|
152
|
-
], ElMeenuElement.prototype, "uploadProcesses", void 0);
|
|
153
|
-
ElMeenuElement = __decorate([
|
|
154
|
-
customElement('hy-file-demo')
|
|
155
|
-
], ElMeenuElement);
|
|
156
|
-
export { ElMeenuElement };
|
|
157
|
-
//# sourceMappingURL=file-demo.js.map
|
package/demo/file-demo.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"file-demo.js","sourceRoot":"","sources":["../../../../src/components/file-upload/demo/file-demo.ts"],"names":[],"mappings":"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","sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\n/**\n * @license\n * Copyright 2023 Google Laabidi Aymen\n * SPDX-License-Identifier: MIT\n */\nimport { LitElement, css, html } from 'lit';\nimport { customElement, state } from 'lit/decorators.js';\nimport \"../file-upload.component\";\nimport { UploadFile } from '../types';\n\n@customElement('hy-file-demo')\nexport class ElMeenuElement extends LitElement {\n @state() float = 'left';\n @state() uploadProcesses: Map<string, number> = new Map();\n\n override firstUpdated() {\n // Get reference to the file upload component\n const fileUpload : any = this.shadowRoot?.querySelector('nr-file-upload');\n \n if (fileUpload) {\n // Add event listeners to the component\n fileUpload.addEventListener('file-select', this._handleFileSelect.bind(this));\n fileUpload.addEventListener('file-remove', this._handleFileRemove.bind(this));\n fileUpload.addEventListener('file-exceed', this._handleFileExceed.bind(this));\n }\n }\n\n private _handleFileSelect(event: CustomEvent) {\n const { files } = event.detail;\n const fileUpload : any= this.shadowRoot?.querySelector('nr-file-upload');\n \n if (!fileUpload) return;\n \n files.forEach((file: UploadFile) => {\n // Update status to 'uploading'\n fileUpload.updateFileStatus(file.uid, 'uploading', 0);\n \n // Simulate upload process with interval\n const intervalId = window.setInterval(() => {\n const currentPercentage = file.percentage || 0;\n const percentage = Math.min(100, currentPercentage + 10);\n \n fileUpload.updateFileStatus(file.uid, 'uploading', percentage);\n \n if (percentage === 100) {\n window.clearInterval(intervalId);\n // Set file as successfully uploaded after a small delay\n setTimeout(() => {\n fileUpload.updateFileStatus(file.uid, 'success');\n }, 300);\n \n // Remove from tracking\n this.uploadProcesses.delete(file.uid);\n }\n }, 500);\n \n // Store the interval ID for potential cancellation\n this.uploadProcesses.set(file.uid, intervalId);\n });\n }\n\n private _handleFileRemove(event: CustomEvent) {\n const { file } = event.detail;\n console.log(`File removed: ${file.name}`);\n \n // Cancel upload process if it's still running\n if (this.uploadProcesses.has(file.uid)) {\n window.clearInterval(this.uploadProcesses.get(file.uid));\n this.uploadProcesses.delete(file.uid);\n }\n }\n\n private _handleFileExceed(event: CustomEvent) {\n const { files } = event.detail;\n console.warn(`Upload limit exceeded. Tried to upload ${files.length} additional files.`);\n // Could show a notification or alert here\n }\n\n protected override render() {\n return html`\n <div class=\"demo-container\">\n <h2>File Upload Demo</h2>\n <nr-file-upload\n accept=\"image/*\"\n multiple\n drag\n limit=\"5\"\n tip=\"JPG/PNG files up to 500kb\">\n </nr-file-upload>\n \n <div class=\"usage-info\">\n <h3>Usage:</h3>\n <ul>\n <li>Drag & drop files here</li>\n <li>Or click to select files</li>\n <li>Files will automatically start uploading</li>\n <li>Use the X button to remove files</li>\n <li>Click on eye icon to preview images</li>\n </ul>\n </div>\n </div>\n `;\n }\n\n static override styles = [\n css`\n :host {\n width: 800px;\n display: flex;\n flex-direction: column;\n align-items: center;\n font-family: sans-serif;\n }\n \n .demo-container {\n width: 100%;\n max-width: 700px;\n padding: 20px;\n border-radius: 8px;\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);\n background-color: #fff;\n }\n \n h2 {\n color: #333;\n margin-top: 0;\n }\n \n .usage-info {\n margin-top: 30px;\n padding: 15px;\n background-color: #f5f5f5;\n border-radius: 6px;\n }\n \n .usage-info h3 {\n margin-top: 0;\n color: #555;\n }\n \n ul {\n padding-left: 20px;\n }\n \n li {\n margin-bottom: 8px;\n color: #666;\n }\n `,\n ];\n}\n"]}
|
package/file.component.d.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { LitElement, PropertyValues } from 'lit';
|
|
2
|
-
import { UploadFile } from './types';
|
|
3
|
-
export declare class FileUpload extends LitElement {
|
|
4
|
-
static styles: import("lit").CSSResult;
|
|
5
|
-
accept: string;
|
|
6
|
-
multiple: boolean;
|
|
7
|
-
drag: boolean;
|
|
8
|
-
tip: string;
|
|
9
|
-
limit: number;
|
|
10
|
-
preview: boolean;
|
|
11
|
-
fileList: UploadFile[];
|
|
12
|
-
isDragOver: boolean;
|
|
13
|
-
showDragArea: boolean;
|
|
14
|
-
inputElement: HTMLInputElement | null;
|
|
15
|
-
dragCounter: number;
|
|
16
|
-
previewImage: string | null;
|
|
17
|
-
connectedCallback(): void;
|
|
18
|
-
disconnectedCallback(): void;
|
|
19
|
-
firstUpdated(_changedProperties: PropertyValues): void;
|
|
20
|
-
private _onDocumentDragEnter;
|
|
21
|
-
private _onDocumentDragLeave;
|
|
22
|
-
private _onDocumentDrop;
|
|
23
|
-
private _onDocumentDragOver;
|
|
24
|
-
private _onDrop;
|
|
25
|
-
private _onClick;
|
|
26
|
-
private _onChange;
|
|
27
|
-
private _handleFiles;
|
|
28
|
-
updateFileStatus(uid: string, status: 'ready' | 'uploading' | 'success' | 'error', percentage?: number): void;
|
|
29
|
-
private _updateFile;
|
|
30
|
-
private _removeFile;
|
|
31
|
-
private _dispatchEvent;
|
|
32
|
-
private _showPreview;
|
|
33
|
-
private _closePreview;
|
|
34
|
-
render(): import("lit").TemplateResult<1>;
|
|
35
|
-
}
|
|
36
|
-
//# sourceMappingURL=file.component.d.ts.map
|
package/file.component.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"file.component.d.ts","sourceRoot":"","sources":["../../../src/components/file-upload/file.component.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAQ,cAAc,EAAE,MAAM,KAAK,CAAC;AAEvD,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAIrC,qBACa,UAAW,SAAQ,UAAU;IACxC,OAAgB,MAAM,0BAAU;IAEJ,MAAM,EAAE,MAAM,CAAM;IACnB,QAAQ,EAAE,OAAO,CAAS;IAC1B,IAAI,EAAE,OAAO,CAAQ;IACtB,GAAG,EAAE,MAAM,CAAM;IACjB,KAAK,EAAE,MAAM,CAAK;IACjB,OAAO,EAAE,OAAO,CAAQ;IAE5C,QAAQ,EAAE,UAAU,EAAE,CAAM;IAC5B,UAAU,EAAE,OAAO,CAAS;IAC5B,YAAY,EAAE,OAAO,CAAS;IAC9B,YAAY,EAAE,gBAAgB,GAAG,IAAI,CAAQ;IAC7C,WAAW,EAAE,MAAM,CAAK;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEnC,iBAAiB;IAUjB,oBAAoB;IAUpB,YAAY,CAAC,kBAAkB,EAAE,cAAc;IAKxD,OAAO,CAAC,oBAAoB,CAO1B;IAEF,OAAO,CAAC,oBAAoB,CAQ1B;IAEF,OAAO,CAAC,eAAe,CAOrB;IAEF,OAAO,CAAC,mBAAmB,CAYzB;IAEF,OAAO,CAAC,OAAO,CAWb;IAEF,OAAO,CAAC,QAAQ,CAEd;IAEF,OAAO,CAAC,SAAS,CAMf;YAEY,YAAY;IAmCnB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,EAAE,UAAU,CAAC,EAAE,MAAM;IAY7G,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,aAAa;IAIZ,MAAM;CAwGhB"}
|
package/file.component.js
DELETED
|
@@ -1,327 +0,0 @@
|
|
|
1
|
-
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
-
};
|
|
7
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
8
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
9
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
10
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
11
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
12
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
13
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
14
|
-
});
|
|
15
|
-
};
|
|
16
|
-
import { LitElement, html } from 'lit';
|
|
17
|
-
import { customElement, property, state } from 'lit/decorators.js';
|
|
18
|
-
import { styles } from './styles';
|
|
19
|
-
import { fileUtils } from './utils';
|
|
20
|
-
let FileUpload = class FileUpload extends LitElement {
|
|
21
|
-
constructor() {
|
|
22
|
-
super(...arguments);
|
|
23
|
-
this.accept = '';
|
|
24
|
-
this.multiple = false;
|
|
25
|
-
this.drag = true;
|
|
26
|
-
this.tip = '';
|
|
27
|
-
this.limit = 0;
|
|
28
|
-
this.preview = true;
|
|
29
|
-
this.fileList = [];
|
|
30
|
-
this.isDragOver = false;
|
|
31
|
-
this.showDragArea = false;
|
|
32
|
-
this.inputElement = null;
|
|
33
|
-
this.dragCounter = 0;
|
|
34
|
-
this.previewImage = null;
|
|
35
|
-
this._onDocumentDragEnter = (e) => {
|
|
36
|
-
e.preventDefault();
|
|
37
|
-
this.dragCounter++;
|
|
38
|
-
if (this.dragCounter === 1) {
|
|
39
|
-
this.showDragArea = true;
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
this._onDocumentDragLeave = (e) => {
|
|
43
|
-
e.preventDefault();
|
|
44
|
-
this.dragCounter--;
|
|
45
|
-
if (this.dragCounter === 0) {
|
|
46
|
-
this.showDragArea = false;
|
|
47
|
-
this.isDragOver = false;
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
this._onDocumentDrop = (e) => {
|
|
51
|
-
if (e.target !== this && !this.contains(e.target)) {
|
|
52
|
-
e.preventDefault();
|
|
53
|
-
this.dragCounter = 0;
|
|
54
|
-
this.showDragArea = false;
|
|
55
|
-
this.isDragOver = false;
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
this._onDocumentDragOver = (e) => {
|
|
59
|
-
e.preventDefault();
|
|
60
|
-
// Determine if the drag is over our component
|
|
61
|
-
const path = e.composedPath();
|
|
62
|
-
const isOverComponent = path.includes(this);
|
|
63
|
-
if (isOverComponent) {
|
|
64
|
-
this.isDragOver = true;
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
this.isDragOver = false;
|
|
68
|
-
}
|
|
69
|
-
};
|
|
70
|
-
this._onDrop = (e) => {
|
|
71
|
-
var _a;
|
|
72
|
-
e.preventDefault();
|
|
73
|
-
e.stopPropagation();
|
|
74
|
-
this.dragCounter = 0;
|
|
75
|
-
this.isDragOver = false;
|
|
76
|
-
this.showDragArea = false;
|
|
77
|
-
if ((_a = e.dataTransfer) === null || _a === void 0 ? void 0 : _a.files) {
|
|
78
|
-
this._handleFiles(e.dataTransfer.files);
|
|
79
|
-
}
|
|
80
|
-
};
|
|
81
|
-
this._onClick = () => {
|
|
82
|
-
var _a;
|
|
83
|
-
(_a = this.inputElement) === null || _a === void 0 ? void 0 : _a.click();
|
|
84
|
-
};
|
|
85
|
-
this._onChange = (e) => {
|
|
86
|
-
const target = e.target;
|
|
87
|
-
if (target.files) {
|
|
88
|
-
this._handleFiles(target.files);
|
|
89
|
-
target.value = ''; // Reset so same file can be selected again
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
connectedCallback() {
|
|
94
|
-
super.connectedCallback();
|
|
95
|
-
if (this.drag) {
|
|
96
|
-
document.addEventListener('dragenter', this._onDocumentDragEnter);
|
|
97
|
-
document.addEventListener('dragleave', this._onDocumentDragLeave);
|
|
98
|
-
document.addEventListener('drop', this._onDocumentDrop);
|
|
99
|
-
document.addEventListener('dragover', this._onDocumentDragOver);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
disconnectedCallback() {
|
|
103
|
-
super.disconnectedCallback();
|
|
104
|
-
if (this.drag) {
|
|
105
|
-
document.removeEventListener('dragenter', this._onDocumentDragEnter);
|
|
106
|
-
document.removeEventListener('dragleave', this._onDocumentDragLeave);
|
|
107
|
-
document.removeEventListener('drop', this._onDocumentDrop);
|
|
108
|
-
document.removeEventListener('dragover', this._onDocumentDragOver);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
firstUpdated(_changedProperties) {
|
|
112
|
-
var _a;
|
|
113
|
-
super.firstUpdated(_changedProperties);
|
|
114
|
-
this.inputElement = ((_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('input[type="file"]')) || null;
|
|
115
|
-
}
|
|
116
|
-
_handleFiles(files) {
|
|
117
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
118
|
-
if (this.limit > 0 && this.fileList.length + files.length > this.limit) {
|
|
119
|
-
this._dispatchEvent('exceed', { files });
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
const newFiles = [];
|
|
123
|
-
for (const file of Array.from(files)) {
|
|
124
|
-
const isImage = fileUtils.isImageFile(file);
|
|
125
|
-
const fileObj = {
|
|
126
|
-
name: file.name,
|
|
127
|
-
size: fileUtils.formatFileSize(file.size),
|
|
128
|
-
raw: file,
|
|
129
|
-
status: 'ready',
|
|
130
|
-
percentage: 0,
|
|
131
|
-
uid: Date.now() + Math.random().toString(36).substring(2),
|
|
132
|
-
isImage
|
|
133
|
-
};
|
|
134
|
-
// Create preview URL for images if preview is enabled
|
|
135
|
-
if (this.preview && isImage) {
|
|
136
|
-
fileObj.url = yield fileUtils.createFilePreview(file);
|
|
137
|
-
}
|
|
138
|
-
this.fileList = [...this.fileList, fileObj];
|
|
139
|
-
newFiles.push(fileObj);
|
|
140
|
-
}
|
|
141
|
-
this.requestUpdate();
|
|
142
|
-
// Emit file-selected event with the new files
|
|
143
|
-
this._dispatchEvent('select', { files: newFiles, fileList: this.fileList });
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
updateFileStatus(uid, status, percentage) {
|
|
147
|
-
const file = this.fileList.find(f => f.uid === uid);
|
|
148
|
-
if (file) {
|
|
149
|
-
file.status = status;
|
|
150
|
-
if (percentage !== undefined) {
|
|
151
|
-
file.percentage = percentage;
|
|
152
|
-
}
|
|
153
|
-
this._updateFile(file);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
_updateFile(updatedFile) {
|
|
157
|
-
this.fileList = this.fileList.map(file => file.uid === updatedFile.uid ? updatedFile : file);
|
|
158
|
-
this.requestUpdate();
|
|
159
|
-
}
|
|
160
|
-
_removeFile(uid) {
|
|
161
|
-
const file = this.fileList.find(file => file.uid === uid);
|
|
162
|
-
this.fileList = this.fileList.filter(file => file.uid !== uid);
|
|
163
|
-
if (file) {
|
|
164
|
-
this._dispatchEvent('remove', { file });
|
|
165
|
-
}
|
|
166
|
-
this.requestUpdate();
|
|
167
|
-
}
|
|
168
|
-
_dispatchEvent(name, data) {
|
|
169
|
-
this.dispatchEvent(new CustomEvent(`file-${name}`, {
|
|
170
|
-
detail: data,
|
|
171
|
-
bubbles: true,
|
|
172
|
-
composed: true
|
|
173
|
-
}));
|
|
174
|
-
}
|
|
175
|
-
_showPreview(url) {
|
|
176
|
-
this.previewImage = url;
|
|
177
|
-
}
|
|
178
|
-
_closePreview() {
|
|
179
|
-
this.previewImage = null;
|
|
180
|
-
}
|
|
181
|
-
render() {
|
|
182
|
-
return html `
|
|
183
|
-
<div class="upload" @drop=${this._onDrop} @dragover=${(e) => e.preventDefault()}>
|
|
184
|
-
<input
|
|
185
|
-
type="file"
|
|
186
|
-
class="hidden"
|
|
187
|
-
accept=${this.accept}
|
|
188
|
-
?multiple=${this.multiple}
|
|
189
|
-
@change=${this._onChange}
|
|
190
|
-
/>
|
|
191
|
-
|
|
192
|
-
${this.showDragArea ? html `
|
|
193
|
-
<div
|
|
194
|
-
class="upload-dragger ${this.isDragOver ? 'is-dragover' : ''}"
|
|
195
|
-
@click=${this._onClick}
|
|
196
|
-
>
|
|
197
|
-
<div class="upload-icon">
|
|
198
|
-
<svg width="40" height="40" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
199
|
-
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
|
|
200
|
-
<polyline points="17 8 12 3 7 8"></polyline>
|
|
201
|
-
<line x1="12" y1="3" x2="12" y2="15"></line>
|
|
202
|
-
</svg>
|
|
203
|
-
</div>
|
|
204
|
-
<div class="upload-text">Drop file here or click to upload</div>
|
|
205
|
-
${this.tip ? html `<div class="upload-tip">${this.tip}</div>` : ''}
|
|
206
|
-
</div>
|
|
207
|
-
` : html `
|
|
208
|
-
<button class="upload-button" @click=${this._onClick}>Upload File</button>
|
|
209
|
-
${this.tip ? html `<div class="upload-tip">${this.tip}</div>` : ''}
|
|
210
|
-
`}
|
|
211
|
-
|
|
212
|
-
<div class="file-list">
|
|
213
|
-
${this.fileList.map(file => html `
|
|
214
|
-
<div class="file-item">
|
|
215
|
-
${file.isImage ? html `
|
|
216
|
-
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
217
|
-
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
|
218
|
-
<circle cx="8.5" cy="8.5" r="1.5"></circle>
|
|
219
|
-
<polyline points="21 15 16 10 5 21"></polyline>
|
|
220
|
-
</svg>
|
|
221
|
-
` : html `
|
|
222
|
-
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
223
|
-
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
|
|
224
|
-
<polyline points="14 2 14 8 20 8"></polyline>
|
|
225
|
-
</svg>
|
|
226
|
-
`}
|
|
227
|
-
<div class="file-name">${file.name}</div>
|
|
228
|
-
<div class="file-size">${file.size}</div>
|
|
229
|
-
<div class="file-status">
|
|
230
|
-
${file.status === 'success' ? html `
|
|
231
|
-
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#67c23a" stroke-width="2">
|
|
232
|
-
<polyline points="20 6 9 17 4 12"></polyline>
|
|
233
|
-
</svg>
|
|
234
|
-
` : file.status === 'error' ? html `
|
|
235
|
-
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#f56c6c" stroke-width="2">
|
|
236
|
-
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
237
|
-
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
238
|
-
</svg>
|
|
239
|
-
` : file.status === 'uploading' ? html `${file.percentage}%` : ''}
|
|
240
|
-
</div>
|
|
241
|
-
<div class="file-actions">
|
|
242
|
-
${file.isImage && file.url ? html `
|
|
243
|
-
<button class="preview-icon" @click=${() => this._showPreview(file.url)}>
|
|
244
|
-
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
245
|
-
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"></path>
|
|
246
|
-
<circle cx="12" cy="12" r="3"></circle>
|
|
247
|
-
</svg>
|
|
248
|
-
</button>
|
|
249
|
-
` : ''}
|
|
250
|
-
<button @click=${() => this._removeFile(file.uid)}>
|
|
251
|
-
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
252
|
-
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
253
|
-
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
254
|
-
</svg>
|
|
255
|
-
</button>
|
|
256
|
-
</div>
|
|
257
|
-
${file.status === 'uploading' ? html `
|
|
258
|
-
<div class="progress-bar">
|
|
259
|
-
<div class="progress-inner" style="width: ${file.percentage}%"></div>
|
|
260
|
-
</div>
|
|
261
|
-
` : ''}
|
|
262
|
-
</div>
|
|
263
|
-
${this.preview && file.isImage && file.url ? html `
|
|
264
|
-
<div class="file-preview">
|
|
265
|
-
<img
|
|
266
|
-
class="image-preview"
|
|
267
|
-
src="${file.url}"
|
|
268
|
-
alt="${file.name}"
|
|
269
|
-
@click=${() => this._showPreview(file.url)}
|
|
270
|
-
/>
|
|
271
|
-
</div>
|
|
272
|
-
` : ''}
|
|
273
|
-
`)}
|
|
274
|
-
</div>
|
|
275
|
-
|
|
276
|
-
${this.previewImage ? html `
|
|
277
|
-
<div class="preview-modal" @click=${this._closePreview}>
|
|
278
|
-
<button class="preview-close">×</button>
|
|
279
|
-
<img src="${this.previewImage}" alt="Preview" />
|
|
280
|
-
</div>
|
|
281
|
-
` : ''}
|
|
282
|
-
</div>
|
|
283
|
-
`;
|
|
284
|
-
}
|
|
285
|
-
};
|
|
286
|
-
FileUpload.styles = styles;
|
|
287
|
-
__decorate([
|
|
288
|
-
property({ type: String })
|
|
289
|
-
], FileUpload.prototype, "accept", void 0);
|
|
290
|
-
__decorate([
|
|
291
|
-
property({ type: Boolean })
|
|
292
|
-
], FileUpload.prototype, "multiple", void 0);
|
|
293
|
-
__decorate([
|
|
294
|
-
property({ type: Boolean })
|
|
295
|
-
], FileUpload.prototype, "drag", void 0);
|
|
296
|
-
__decorate([
|
|
297
|
-
property({ type: String })
|
|
298
|
-
], FileUpload.prototype, "tip", void 0);
|
|
299
|
-
__decorate([
|
|
300
|
-
property({ type: Number })
|
|
301
|
-
], FileUpload.prototype, "limit", void 0);
|
|
302
|
-
__decorate([
|
|
303
|
-
property({ type: Boolean })
|
|
304
|
-
], FileUpload.prototype, "preview", void 0);
|
|
305
|
-
__decorate([
|
|
306
|
-
state()
|
|
307
|
-
], FileUpload.prototype, "fileList", void 0);
|
|
308
|
-
__decorate([
|
|
309
|
-
state()
|
|
310
|
-
], FileUpload.prototype, "isDragOver", void 0);
|
|
311
|
-
__decorate([
|
|
312
|
-
state()
|
|
313
|
-
], FileUpload.prototype, "showDragArea", void 0);
|
|
314
|
-
__decorate([
|
|
315
|
-
state()
|
|
316
|
-
], FileUpload.prototype, "inputElement", void 0);
|
|
317
|
-
__decorate([
|
|
318
|
-
state()
|
|
319
|
-
], FileUpload.prototype, "dragCounter", void 0);
|
|
320
|
-
__decorate([
|
|
321
|
-
state()
|
|
322
|
-
], FileUpload.prototype, "previewImage", void 0);
|
|
323
|
-
FileUpload = __decorate([
|
|
324
|
-
customElement('nr-file-upload')
|
|
325
|
-
], FileUpload);
|
|
326
|
-
export { FileUpload };
|
|
327
|
-
//# sourceMappingURL=file.component.js.map
|
package/file.component.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"file.component.js","sourceRoot":"","sources":["../../../src/components/file-upload/file.component.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, html, PropertyValues } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { UploadFile } from './types';\nimport { styles } from './styles';\nimport { fileUtils } from './utils';\n\n@customElement('nr-file-upload')\nexport class FileUpload extends LitElement {\n static override styles = styles;\n\n @property({ type: String }) accept: string = '';\n @property({ type: Boolean }) multiple: boolean = false;\n @property({ type: Boolean }) drag: boolean = true;\n @property({ type: String }) tip: string = '';\n @property({ type: Number }) limit: number = 0;\n @property({ type: Boolean }) preview: boolean = true;\n\n @state() fileList: UploadFile[] = [];\n @state() isDragOver: boolean = false;\n @state() showDragArea: boolean = false;\n @state() inputElement: HTMLInputElement | null = null;\n @state() dragCounter: number = 0;\n @state() previewImage: string | null = null;\n\n override connectedCallback() {\n super.connectedCallback();\n if (this.drag) {\n document.addEventListener('dragenter', this._onDocumentDragEnter);\n document.addEventListener('dragleave', this._onDocumentDragLeave);\n document.addEventListener('drop', this._onDocumentDrop);\n document.addEventListener('dragover', this._onDocumentDragOver);\n }\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n if (this.drag) {\n document.removeEventListener('dragenter', this._onDocumentDragEnter);\n document.removeEventListener('dragleave', this._onDocumentDragLeave);\n document.removeEventListener('drop', this._onDocumentDrop);\n document.removeEventListener('dragover', this._onDocumentDragOver);\n }\n }\n\n override firstUpdated(_changedProperties: PropertyValues) {\n super.firstUpdated(_changedProperties);\n this.inputElement = this.shadowRoot?.querySelector('input[type=\"file\"]') || null;\n }\n\n private _onDocumentDragEnter = (e: DragEvent) => {\n e.preventDefault();\n this.dragCounter++;\n \n if (this.dragCounter === 1) {\n this.showDragArea = true;\n }\n };\n\n private _onDocumentDragLeave = (e: DragEvent) => {\n e.preventDefault();\n this.dragCounter--;\n \n if (this.dragCounter === 0) {\n this.showDragArea = false;\n this.isDragOver = false;\n }\n };\n\n private _onDocumentDrop = (e: DragEvent) => {\n if (e.target !== this && !this.contains(e.target as Node)) {\n e.preventDefault();\n this.dragCounter = 0;\n this.showDragArea = false;\n this.isDragOver = false;\n }\n };\n\n private _onDocumentDragOver = (e: DragEvent) => {\n e.preventDefault();\n \n // Determine if the drag is over our component\n const path = e.composedPath();\n const isOverComponent = path.includes(this);\n \n if (isOverComponent) {\n this.isDragOver = true;\n } else {\n this.isDragOver = false;\n }\n };\n\n private _onDrop = (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n \n this.dragCounter = 0;\n this.isDragOver = false;\n this.showDragArea = false;\n\n if (e.dataTransfer?.files) {\n this._handleFiles(e.dataTransfer.files);\n }\n };\n\n private _onClick = () => {\n this.inputElement?.click();\n };\n\n private _onChange = (e: Event) => {\n const target = e.target as HTMLInputElement;\n if (target.files) {\n this._handleFiles(target.files);\n target.value = ''; // Reset so same file can be selected again\n }\n };\n\n private async _handleFiles(files: FileList) {\n if (this.limit > 0 && this.fileList.length + files.length > this.limit) {\n this._dispatchEvent('exceed', { files });\n return;\n }\n\n const newFiles: UploadFile[] = [];\n\n for (const file of Array.from(files)) {\n const isImage = fileUtils.isImageFile(file);\n const fileObj: UploadFile = {\n name: file.name,\n size: fileUtils.formatFileSize(file.size),\n raw: file,\n status: 'ready',\n percentage: 0,\n uid: Date.now() + Math.random().toString(36).substring(2),\n isImage\n };\n\n // Create preview URL for images if preview is enabled\n if (this.preview && isImage) {\n fileObj.url = await fileUtils.createFilePreview(file);\n }\n\n this.fileList = [...this.fileList, fileObj];\n newFiles.push(fileObj);\n }\n\n this.requestUpdate();\n\n // Emit file-selected event with the new files\n this._dispatchEvent('select', { files: newFiles, fileList: this.fileList });\n }\n\n public updateFileStatus(uid: string, status: 'ready' | 'uploading' | 'success' | 'error', percentage?: number) {\n const file = this.fileList.find(f => f.uid === uid);\n \n if (file) {\n file.status = status;\n if (percentage !== undefined) {\n file.percentage = percentage;\n }\n this._updateFile(file);\n }\n }\n\n private _updateFile(updatedFile: UploadFile) {\n this.fileList = this.fileList.map(file =>\n file.uid === updatedFile.uid ? updatedFile : file\n );\n this.requestUpdate();\n }\n\n private _removeFile(uid: string) {\n const file = this.fileList.find(file => file.uid === uid);\n this.fileList = this.fileList.filter(file => file.uid !== uid);\n if (file) {\n this._dispatchEvent('remove', { file });\n }\n this.requestUpdate();\n }\n\n private _dispatchEvent(name: string, data: any) {\n this.dispatchEvent(new CustomEvent(`file-${name}`, {\n detail: data,\n bubbles: true,\n composed: true\n }));\n }\n\n private _showPreview(url: string) {\n this.previewImage = url;\n }\n\n private _closePreview() {\n this.previewImage = null;\n }\n\n override render() {\n return html`\n <div class=\"upload\" @drop=${this._onDrop} @dragover=${(e: DragEvent) => e.preventDefault()}>\n <input \n type=\"file\" \n class=\"hidden\" \n accept=${this.accept}\n ?multiple=${this.multiple}\n @change=${this._onChange}\n />\n\n ${this.showDragArea ? html`\n <div \n class=\"upload-dragger ${this.isDragOver ? 'is-dragover' : ''}\" \n @click=${this._onClick}\n >\n <div class=\"upload-icon\">\n <svg width=\"40\" height=\"40\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\"></path>\n <polyline points=\"17 8 12 3 7 8\"></polyline>\n <line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"15\"></line>\n </svg>\n </div>\n <div class=\"upload-text\">Drop file here or click to upload</div>\n ${this.tip ? html`<div class=\"upload-tip\">${this.tip}</div>` : ''}\n </div>\n ` : html`\n <button class=\"upload-button\" @click=${this._onClick}>Upload File</button>\n ${this.tip ? html`<div class=\"upload-tip\">${this.tip}</div>` : ''}\n `}\n\n <div class=\"file-list\">\n ${this.fileList.map(file => html`\n <div class=\"file-item\">\n ${file.isImage ? html`\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"></rect>\n <circle cx=\"8.5\" cy=\"8.5\" r=\"1.5\"></circle>\n <polyline points=\"21 15 16 10 5 21\"></polyline>\n </svg>\n ` : html`\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\"></path>\n <polyline points=\"14 2 14 8 20 8\"></polyline>\n </svg>\n `}\n <div class=\"file-name\">${file.name}</div>\n <div class=\"file-size\">${file.size}</div>\n <div class=\"file-status\">\n ${file.status === 'success' ? html`\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#67c23a\" stroke-width=\"2\">\n <polyline points=\"20 6 9 17 4 12\"></polyline>\n </svg>\n ` : file.status === 'error' ? html`\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"#f56c6c\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n ` : file.status === 'uploading' ? html`${file.percentage}%` : ''}\n </div>\n <div class=\"file-actions\">\n ${file.isImage && file.url ? html`\n <button class=\"preview-icon\" @click=${() => this._showPreview(file.url!)}>\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z\"></path>\n <circle cx=\"12\" cy=\"12\" r=\"3\"></circle>\n </svg>\n </button>\n ` : ''}\n <button @click=${() => this._removeFile(file.uid)}>\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n </div>\n ${file.status === 'uploading' ? html`\n <div class=\"progress-bar\">\n <div class=\"progress-inner\" style=\"width: ${file.percentage}%\"></div>\n </div>\n ` : ''}\n </div>\n ${this.preview && file.isImage && file.url ? html`\n <div class=\"file-preview\">\n <img \n class=\"image-preview\" \n src=\"${file.url}\" \n alt=\"${file.name}\" \n @click=${() => this._showPreview(file.url!)}\n />\n </div>\n ` : ''}\n `)}\n </div>\n\n ${this.previewImage ? html`\n <div class=\"preview-modal\" @click=${this._closePreview}>\n <button class=\"preview-close\">×</button>\n <img src=\"${this.previewImage}\" alt=\"Preview\" />\n </div>\n ` : ''}\n </div>\n `;\n }\n}"]}
|