@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.
@@ -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,4BA6CpB;CACH"}
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"}
@@ -101,7 +101,6 @@ let ElMeenuElement = class ElMeenuElement extends LitElement {
101
101
  ElMeenuElement.styles = [
102
102
  css `
103
103
  :host {
104
- width: 800px;
105
104
  display: flex;
106
105
  flex-direction: column;
107
106
  align-items: center;
@@ -1 +1 @@
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 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"]}
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,5 +1,5 @@
1
1
  import { LitElement, PropertyValues } from 'lit';
2
- import { UploadFile } from './types';
2
+ import { UploadFile } from './types.js';
3
3
  export declare class FileUpload extends LitElement {
4
4
  static styles: import("lit").CSSResult;
5
5
  accept: string;
@@ -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,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"}
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"}
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nuralyui/file-upload",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "type": "module",
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":"AAEA,eAAO,MAAM,MAAM,yBAwMlB,CAAC"}
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
- :host {
4
- display: block;
5
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
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
- .upload {
9
- width: 100%;
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
- .upload-dragger {
13
- background-color: #f8f9fa;
14
- border: 1px dashed #d9d9d9;
15
- border-radius: 6px;
16
- box-sizing: border-box;
17
- width: 100%;
18
- height: 180px;
19
- text-align: center;
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
- .upload-dragger:hover {
31
- border-color: #409eff;
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
- .upload-dragger.is-dragover {
35
- background-color: rgba(64, 158, 255, .06);
36
- border-color: #409eff;
37
- }
199
+ /* File item container with progress bar */
200
+ .file-container {
201
+ width: 100%;
202
+ position: relative;
203
+ }
38
204
 
39
- .upload-icon {
40
- font-size: 28px;
41
- color: #c0c4cc;
42
- margin-bottom: 8px;
205
+ /* Responsive styles */
206
+ @media (max-width: 600px) {
207
+ .upload-dragger {
208
+ height: 140px;
209
+ padding: 12px;
43
210
  }
44
-
45
- .upload-text {
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: 12px;
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: flex;
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
- .file-item:hover {
86
- background-color: #f8f9fa;
229
+ .file-item > svg:first-child {
230
+ grid-area: icon;
231
+ align-self: start;
87
232
  }
88
-
89
233
  .file-name {
90
- margin-left: 6px;
91
- flex: 1;
92
- color: #606266;
234
+ grid-area: filename;
235
+ margin: 0;
236
+ padding: 2px 0;
93
237
  }
94
-
95
238
  .file-size {
96
- color: #909399;
97
- font-size: 12px;
98
- margin-right: 10px;
239
+ grid-area: size;
240
+ margin: 0;
99
241
  }
100
-
101
242
  .file-status {
102
- display: flex;
103
- align-items: center;
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
- height: 2px;
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
- .hidden {
138
- display: none;
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
- height: 100%;
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;AAE1B,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwMxB,CAAC","sourcesContent":["import { css } from 'lit';\n\nexport const styles = css`\n :host {\n display: block;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;\n }\n\n .upload {\n width: 100%;\n }\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 .3s;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n }\n\n .upload-dragger:hover {\n border-color: #409eff;\n }\n\n .upload-dragger.is-dragover {\n background-color: rgba(64, 158, 255, .06);\n border-color: #409eff;\n }\n\n .upload-icon {\n font-size: 28px;\n color: #c0c4cc;\n margin-bottom: 8px;\n }\n\n .upload-text {\n color: #606266;\n font-size: 14px;\n text-align: center;\n }\n\n .upload-tip {\n font-size: 12px;\n color: #909399;\n margin-top: 7px;\n }\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\n .upload-button:hover {\n background-color: #66b1ff;\n }\n\n .file-list {\n margin-top: 10px;\n }\n\n .file-item {\n display: flex;\n align-items: center;\n margin-bottom: 8px;\n transition: all .3s;\n padding: 8px;\n border-radius: 4px;\n }\n\n .file-item:hover {\n background-color: #f8f9fa;\n }\n\n .file-name {\n margin-left: 6px;\n flex: 1;\n color: #606266;\n }\n\n .file-size {\n color: #909399;\n font-size: 12px;\n margin-right: 10px;\n }\n\n .file-status {\n display: flex;\n align-items: center;\n }\n\n .file-actions {\n margin-left: 10px;\n display: flex;\n gap: 4px;\n }\n\n .file-actions button {\n background: none;\n border: none;\n padding: 4px;\n cursor: pointer;\n color: #909399;\n }\n\n .file-actions button:hover {\n color: #409eff;\n }\n\n .progress-bar {\n height: 2px;\n width: 100%;\n background-color: #e6e6e6;\n margin-top: 4px;\n }\n\n .progress-inner {\n height: 100%;\n background-color: #409eff;\n transition: width .3s;\n }\n\n .hidden {\n display: none;\n }\n\n .success {\n color: #67c23a;\n }\n\n .error {\n color: #f56c6c;\n }\n\n .icon-delete {\n color: #f56c6c;\n }\n\n .file-preview {\n width: 100%;\n margin-top: 4px;\n }\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\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\n .preview-modal img {\n max-width: 90%;\n max-height: 90%;\n object-fit: contain;\n }\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\n .preview-icon {\n padding: 4px;\n color: #409eff;\n cursor: zoom-in;\n }\n`;"]}
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`;"]}
@@ -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
@@ -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
@@ -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"]}
@@ -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
@@ -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
@@ -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}"]}