@digital-realty/ix-file-uploader 1.3.1-alpha.1 → 1.3.1

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.
@@ -31,6 +31,7 @@ export declare class IxFileUploader extends LitElement {
31
31
  isDeleteBulkFileDialogOpen: boolean;
32
32
  pendingFileDeletion: UploaderFile | undefined;
33
33
  files: Array<UploaderFile>;
34
+ errors: Array<string>;
34
35
  private maxFileSizeInBytes;
35
36
  /**
36
37
  * The associated form element with which this element's value will submit.
@@ -54,6 +55,7 @@ export declare class IxFileUploader extends LitElement {
54
55
  protected updated(_: PropertyValues): void;
55
56
  renderDeleteBulkFileConfirmationDialog(): TemplateResult<1> | typeof nothing;
56
57
  renderHintText(): TemplateResult<1> | typeof nothing;
58
+ renderErrors(): TemplateResult<1>;
57
59
  renderBody(): TemplateResult<1>;
58
60
  protected render(): TemplateResult<1>;
59
61
  }
@@ -36,6 +36,7 @@ export class IxFileUploader extends LitElement {
36
36
  this.isDeleteBulkFileDialogOpen = false;
37
37
  this.pendingFileDeletion = undefined;
38
38
  this.files = [];
39
+ this.errors = [];
39
40
  this.maxFileSizeInBytes = 0;
40
41
  }
41
42
  /**
@@ -96,13 +97,17 @@ export class IxFileUploader extends LitElement {
96
97
  }
97
98
  }
98
99
  onFilesUploaded(results) {
100
+ this.errors = [];
101
+ const filesNotUploaded = results.filter(result => !result.uploaded);
99
102
  const event = new CustomEvent('on-files-uploaded', {
100
103
  detail: {
101
104
  allFiles: this.files,
102
105
  filesUploaded: results.filter(result => result.uploaded),
103
- filesNotUploaded: results.filter(result => !result.uploaded),
106
+ filesNotUploaded,
104
107
  },
105
108
  });
109
+ const uniqueErrors = filesNotUploaded === null || filesNotUploaded === void 0 ? void 0 : filesNotUploaded.map(f => f.message).filter((v, i, a) => a.indexOf(v) === i);
110
+ this.errors = [...uniqueErrors];
106
111
  this.dispatchEvent(event);
107
112
  }
108
113
  onFileClick(e) {
@@ -252,6 +257,11 @@ export class IxFileUploader extends LitElement {
252
257
  ${this.hintText}
253
258
  </div>`;
254
259
  }
260
+ renderErrors() {
261
+ return html ` <div class="error-text">
262
+ ${this.errors.map(e => html `<span>* ${e}</span>`)}
263
+ </div>`;
264
+ }
255
265
  renderBody() {
256
266
  const accept = this.extensions.map(ext => `.${ext}`).join(', ');
257
267
  const classes = {
@@ -264,23 +274,32 @@ export class IxFileUploader extends LitElement {
264
274
  @keyup=${this.openFileUploadDialog}
265
275
  ${ref(this.dropzoneRef)}
266
276
  >
267
- <div class="ix-file-uploader__label">${this.headerText}</div>
268
- <div class="ix-file-uploader__help-text">${this.bodyText}</div>
277
+ <label class="ix-file-uploader__label" for="fileUploader"
278
+ >${this.headerText}</label
279
+ >
280
+ <div class="ix-file-uploader__help-text" id="fileUploaderDesc">
281
+ ${this.bodyText}
282
+ </div>
269
283
  <input
284
+ id="fileUploader"
270
285
  accept=${accept}
271
286
  class="file-input"
272
287
  ?multiple=${this.allowMultipleFiles}
273
288
  onchange=${(e) => this.onFileChange(e)}
274
289
  ${ref(this.fileRef)}
290
+ aria-describedby="fileUploaderDesc"
275
291
  type="file"
276
292
  />
277
293
  </div>
278
- ${this.renderHintText()}
294
+ ${this.renderErrors()} ${this.renderHintText()}
279
295
  </div>`;
280
296
  }
281
297
  render() {
282
298
  return html `<div
283
- class=${classMap({ 'ix-file-uploader': true, error: this.error })}
299
+ class=${classMap({
300
+ 'ix-file-uploader': true,
301
+ error: this.errors.length || this.error,
302
+ })}
284
303
  >
285
304
  ${this.renderBody()}
286
305
  ${this.files.length ? this.renderFileList(this.files) : nothing}
@@ -350,4 +369,7 @@ __decorate([
350
369
  __decorate([
351
370
  state()
352
371
  ], IxFileUploader.prototype, "files", void 0);
372
+ __decorate([
373
+ state()
374
+ ], IxFileUploader.prototype, "errors", void 0);
353
375
  //# sourceMappingURL=IxFileUploader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"IxFileUploader.js","sourceRoot":"","sources":["../src/IxFileUploader.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, LitElement, nothing, PropertyValues, TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { createRef, ref, Ref } from 'lit/directives/ref.js';\nimport { classMap } from 'lit/directives/class-map.js';\n\nimport './ix-file-chip.js';\nimport DataStorageUnit from './data-storage-unit.js';\nimport FileInfo from './internal/file-info.js';\nimport FileUploadResult from './internal/file-upload-result.js';\nimport FileChangeInfo from './internal/file-change-info.js';\nimport FilesUploadedInfo from './internal/files-uploaded-info.js';\nimport getTotalBytes from './internal/get-total-bytes.js';\nimport { processFiles } from './internal/process-files.js';\nimport sortFilesAscending from './internal/sort-files-ascending.js';\nimport IxFileUploaderStyles from './styles/ix-file-uploader-styles.js';\nimport UploaderFile from './internal/uploader-file.js';\nimport '@digital-realty/ix-dialog/ix-dialog.js';\n\nexport class IxFileUploader extends LitElement {\n static readonly styles = [IxFileUploaderStyles];\n\n /** @nocollapse */\n static readonly formAssociated = true;\n\n private readonly internals = (this as HTMLElement).attachInternals();\n\n dropzoneRef: Ref<HTMLInputElement> = createRef();\n\n fileRef: Ref<HTMLInputElement> = createRef();\n\n @property({ type: Boolean }) showTemplateFileLink: boolean = false;\n\n @property({ type: Boolean }) allowMultipleFiles: boolean = false;\n\n @property({ type: Boolean }) allowDuplicates: boolean = false;\n\n @property() headerText: string = '';\n\n @property() bodyText: string = '';\n\n @property() hintText: string | undefined = undefined;\n\n @property({ type: Array }) defaultFiles: Array<UploaderFile> = [];\n\n @property({ type: Boolean }) allowDeleteDefaultFiles: boolean = false;\n\n @property({ type: Boolean }) hideBody: boolean = false;\n\n @property({ type: Array }) extensions: string[] = [];\n\n @property({ type: Number }) maxFileCount: number = 10;\n\n @property() maxFileSizeUnit: DataStorageUnit = DataStorageUnit.MB;\n\n @property({ type: Number }) maxFileSizeValue: number = 10;\n\n @property() name: string = 'ix-file-uploader';\n\n @property({ type: Boolean }) error: boolean = false;\n\n @property({ type: Boolean }) askConfirmationOnDeleteFile: boolean = false;\n\n @property() deleteConfirmationDialogLabel: string =\n 'Are you sure you want to delete your upload file?';\n\n @state() isDeleteBulkFileDialogOpen: boolean = false;\n\n @state() pendingFileDeletion: UploaderFile | undefined = undefined;\n\n @state() files: Array<UploaderFile> = [];\n\n private maxFileSizeInBytes: number = 0;\n\n /**\n * The associated form element with which this element's value will submit.\n */\n get form() {\n return this.internals.form;\n }\n\n // called when the user drops files on the dropzone\n private onDrop(e: DragEvent): void {\n e.preventDefault();\n\n if (!e.dataTransfer) {\n return; // no files dropped\n }\n\n const filesToProcess = Array.from(e.dataTransfer.files);\n\n this.process(filesToProcess);\n }\n\n // This is called when the user selects files from the file dialog\n private onFileChange(e: Event): void {\n const fileList = (e.currentTarget as any).files as FileList;\n\n const filesToProcess = Array.from(fileList);\n\n this.process(filesToProcess);\n\n // clear the files from the file input; we are tracking state at the component level, not in the file input\n this.fileRef.value!.files = new DataTransfer().files;\n }\n\n get allowedMaxFileCount(): number {\n return this.allowMultipleFiles ? this.maxFileCount : 1;\n }\n\n // common method for processing files which are dropped or selected from file input dialog\n private process(filesToProcess: Array<File>): void {\n const results = processFiles({\n currentFiles: this.files,\n extensions: this.extensions,\n filesToProcess,\n maxFileCount: this.allowedMaxFileCount,\n maxFileSizeInBytes: this.maxFileSizeInBytes,\n allowDuplicates: this.allowDuplicates,\n });\n\n this.updateState(results);\n\n this.onFilesUploaded(results);\n }\n\n private updateState(results: Array<FileUploadResult> = []): void {\n const filesToUpload: Array<UploaderFile> = [];\n\n results.forEach(result => {\n if (result.uploaded) {\n filesToUpload.push(Object.assign(result.file, { id: result.id }));\n }\n });\n\n // handle multiple file setting\n if (this.allowMultipleFiles) {\n this.files = [...this.files, ...filesToUpload];\n return;\n }\n\n // handle single file setting\n if (filesToUpload.length) {\n const file = filesToUpload[0];\n this.files = [file];\n }\n }\n\n private onFilesUploaded(results: Array<FileUploadResult>): void {\n const event = new CustomEvent<FilesUploadedInfo>('on-files-uploaded', {\n detail: {\n allFiles: this.files,\n filesUploaded: results.filter(result => result.uploaded),\n filesNotUploaded: results.filter(result => !result.uploaded),\n },\n });\n\n this.dispatchEvent(event);\n }\n\n private onFileClick(e: CustomEvent<FileInfo>): void {\n const event = new CustomEvent<FileChangeInfo>('on-file-clicked', {\n detail: { allFiles: this.files, file: e.detail.file },\n });\n\n this.dispatchEvent(event);\n }\n\n private onFileDelete(e: CustomEvent<FileInfo>): void {\n this.pendingFileDeletion = e.detail.file;\n\n if (this.askConfirmationOnDeleteFile) {\n this.isDeleteBulkFileDialogOpen = true;\n return;\n }\n\n this.handleDeleteBulkFile();\n }\n\n handleDeleteBulkFile() {\n this.files = [...this.files].filter(\n file => file.id !== this.pendingFileDeletion?.id\n );\n\n const event = new CustomEvent<FileChangeInfo>('on-file-removed', {\n detail: { allFiles: this.files, file: this.pendingFileDeletion },\n });\n\n this.isDeleteBulkFileDialogOpen = false;\n this.dispatchEvent(event);\n }\n\n public deleteLastFileWithoutConfirmation(): void {\n if (this.files.length === 0) {\n return; // no files to delete\n }\n\n this.pendingFileDeletion = this.files[this.files.length - 1];\n\n this.handleDeleteBulkFile();\n }\n\n private openFileUploadDialog(): void {\n this.fileRef.value?.click();\n }\n\n protected override firstUpdated(): void {\n this.files = [...this.defaultFiles];\n\n // connect the dropzone\n const dropzone = this.dropzoneRef.value;\n if (dropzone) {\n dropzone.addEventListener('dragenter', e => e.preventDefault());\n dropzone.addEventListener('dragover', e => e.preventDefault());\n dropzone.addEventListener('drop', this.onDrop.bind(this));\n }\n\n // connect the file input\n const fileElem = this.fileRef.value;\n if (fileElem) {\n fileElem.addEventListener('change', this.onFileChange.bind(this));\n }\n\n // calculate the maxBytes based on props\n // Calculate the max file size in bytes to use for checking if files are too large\n const totalBytesForStorageUnit = getTotalBytes(this.maxFileSizeUnit);\n this.maxFileSizeInBytes = this.maxFileSizeValue * totalBytesForStorageUnit;\n }\n\n protected update(changedProperties: PropertyValues) {\n super.update(changedProperties);\n\n if (changedProperties.has('defaultFiles')) {\n this.files = [\n ...this.files.filter(\n file => !this.defaultFiles.some(x => x.name === file.name)\n ),\n ...this.defaultFiles,\n ];\n }\n }\n\n isFileDeletable(file: UploaderFile): boolean {\n if (this.defaultFiles.some(x => x.name === file.name)) {\n return this.allowDeleteDefaultFiles;\n }\n\n return true;\n }\n\n private renderFileList(files: Array<UploaderFile> = []): TemplateResult<1> {\n const sortedFiles = sortFilesAscending(files);\n const chips = sortedFiles.map(\n (file?: UploaderFile) => html`<ix-file-chip\n .file=${file}\n .deletable=${this.isFileDeletable(file!)}\n @on-file-click=${this.onFileClick}\n @on-file-delete=${this.onFileDelete}\n ></ix-file-chip>`\n );\n\n const uploadedFileListClasses = {\n 'uploaded-file-list': true,\n 'uploaded-file-list--spaced': !this.hideBody,\n };\n\n return html`\n <ul class=\"${classMap(uploadedFileListClasses)}\">\n ${chips}\n ${this.showTemplateFileLink\n ? html`<li class=\"ix-file-uploader__template-file\">\n <slot name=\"template-file\"></slot>\n </li>`\n : nothing}\n </ul>\n ${this.renderDeleteBulkFileConfirmationDialog()}\n `;\n }\n\n protected override updated(_: PropertyValues) {\n const formData = new FormData();\n\n this.files.forEach(file => {\n formData.append(`${this.name}[]`, file);\n });\n\n this.internals.setFormValue(formData);\n }\n\n renderDeleteBulkFileConfirmationDialog() {\n if (!this.askConfirmationOnDeleteFile) return nothing;\n\n return html`<ix-dialog\n id=\"deleteFileConfirmationDialog\"\n ?open=${this.isDeleteBulkFileDialogOpen}\n preventCloseOnScrimClick=\"true\"\n @closed=${() => {\n this.isDeleteBulkFileDialogOpen = false;\n }}\n @close=${() => {\n this.isDeleteBulkFileDialogOpen = false;\n }}\n >\n <form\n slot=\"content\"\n id=\"delete-file-id\"\n method=\"dialog\"\n class=\"delete-file-confirmation-dialog\"\n >\n ${this.deleteConfirmationDialogLabel}\n </form>\n <div slot=\"actions\">\n <ix-button\n appearance=\"text\"\n @click=${() => {\n this.isDeleteBulkFileDialogOpen = false;\n }}\n >\n <span class=\"button-label\">NO</span>\n </ix-button>\n <ix-button\n appearance=\"text\"\n name=\"submitBtn\"\n @click=${() => this.handleDeleteBulkFile()}\n >\n <span class=\"button-label\">YES</span>\n </ix-button>\n </div>\n </ix-dialog>`;\n }\n\n renderHintText() {\n if (!this.hintText) {\n return nothing;\n }\n\n return html`<div class=\"ix-file-uploader__hint-text\">\n ${this.hintText}\n </div>`;\n }\n\n renderBody() {\n const accept = this.extensions.map(ext => `.${ext}`).join(', ');\n\n const classes = {\n 'ix-file-uploader--hide-body': this.hideBody,\n };\n\n return html`<div class=${classMap(classes)}>\n <div\n class=\"dropzone\"\n @click=${this.openFileUploadDialog}\n @keyup=${this.openFileUploadDialog}\n ${ref(this.dropzoneRef)}\n >\n <div class=\"ix-file-uploader__label\">${this.headerText}</div>\n <div class=\"ix-file-uploader__help-text\">${this.bodyText}</div>\n <input\n accept=${accept}\n class=\"file-input\"\n ?multiple=${this.allowMultipleFiles}\n onchange=${(e: Event) => this.onFileChange(e)}\n ${ref(this.fileRef)}\n type=\"file\"\n />\n </div>\n ${this.renderHintText()}\n </div>`;\n }\n\n protected render(): TemplateResult<1> {\n return html`<div\n class=${classMap({ 'ix-file-uploader': true, error: this.error })}\n >\n ${this.renderBody()}\n ${this.files.length ? this.renderFileList(this.files) : nothing}\n </div>`;\n }\n}\n"]}
1
+ {"version":3,"file":"IxFileUploader.js","sourceRoot":"","sources":["../src/IxFileUploader.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, LitElement, nothing, PropertyValues, TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { createRef, ref, Ref } from 'lit/directives/ref.js';\nimport { classMap } from 'lit/directives/class-map.js';\n\nimport './ix-file-chip.js';\nimport DataStorageUnit from './data-storage-unit.js';\nimport FileInfo from './internal/file-info.js';\nimport FileUploadResult from './internal/file-upload-result.js';\nimport FileChangeInfo from './internal/file-change-info.js';\nimport FilesUploadedInfo from './internal/files-uploaded-info.js';\nimport getTotalBytes from './internal/get-total-bytes.js';\nimport { processFiles } from './internal/process-files.js';\nimport sortFilesAscending from './internal/sort-files-ascending.js';\nimport IxFileUploaderStyles from './styles/ix-file-uploader-styles.js';\nimport UploaderFile from './internal/uploader-file.js';\nimport '@digital-realty/ix-dialog/ix-dialog.js';\n\nexport class IxFileUploader extends LitElement {\n static readonly styles = [IxFileUploaderStyles];\n\n /** @nocollapse */\n static readonly formAssociated = true;\n\n private readonly internals = (this as HTMLElement).attachInternals();\n\n dropzoneRef: Ref<HTMLInputElement> = createRef();\n\n fileRef: Ref<HTMLInputElement> = createRef();\n\n @property({ type: Boolean }) showTemplateFileLink: boolean = false;\n\n @property({ type: Boolean }) allowMultipleFiles: boolean = false;\n\n @property({ type: Boolean }) allowDuplicates: boolean = false;\n\n @property() headerText: string = '';\n\n @property() bodyText: string = '';\n\n @property() hintText: string | undefined = undefined;\n\n @property({ type: Array }) defaultFiles: Array<UploaderFile> = [];\n\n @property({ type: Boolean }) allowDeleteDefaultFiles: boolean = false;\n\n @property({ type: Boolean }) hideBody: boolean = false;\n\n @property({ type: Array }) extensions: string[] = [];\n\n @property({ type: Number }) maxFileCount: number = 10;\n\n @property() maxFileSizeUnit: DataStorageUnit = DataStorageUnit.MB;\n\n @property({ type: Number }) maxFileSizeValue: number = 10;\n\n @property() name: string = 'ix-file-uploader';\n\n @property({ type: Boolean }) error: boolean = false;\n\n @property({ type: Boolean }) askConfirmationOnDeleteFile: boolean = false;\n\n @property() deleteConfirmationDialogLabel: string =\n 'Are you sure you want to delete your upload file?';\n\n @state() isDeleteBulkFileDialogOpen: boolean = false;\n\n @state() pendingFileDeletion: UploaderFile | undefined = undefined;\n\n @state() files: Array<UploaderFile> = [];\n\n @state() errors: Array<string> = [];\n\n private maxFileSizeInBytes: number = 0;\n\n /**\n * The associated form element with which this element's value will submit.\n */\n get form() {\n return this.internals.form;\n }\n\n // called when the user drops files on the dropzone\n private onDrop(e: DragEvent): void {\n e.preventDefault();\n\n if (!e.dataTransfer) {\n return; // no files dropped\n }\n\n const filesToProcess = Array.from(e.dataTransfer.files);\n\n this.process(filesToProcess);\n }\n\n // This is called when the user selects files from the file dialog\n private onFileChange(e: Event): void {\n const fileList = (e.currentTarget as any).files as FileList;\n\n const filesToProcess = Array.from(fileList);\n\n this.process(filesToProcess);\n\n // clear the files from the file input; we are tracking state at the component level, not in the file input\n this.fileRef.value!.files = new DataTransfer().files;\n }\n\n get allowedMaxFileCount(): number {\n return this.allowMultipleFiles ? this.maxFileCount : 1;\n }\n\n // common method for processing files which are dropped or selected from file input dialog\n private process(filesToProcess: Array<File>): void {\n const results = processFiles({\n currentFiles: this.files,\n extensions: this.extensions,\n filesToProcess,\n maxFileCount: this.allowedMaxFileCount,\n maxFileSizeInBytes: this.maxFileSizeInBytes,\n allowDuplicates: this.allowDuplicates,\n });\n\n this.updateState(results);\n\n this.onFilesUploaded(results);\n }\n\n private updateState(results: Array<FileUploadResult> = []): void {\n const filesToUpload: Array<UploaderFile> = [];\n\n results.forEach(result => {\n if (result.uploaded) {\n filesToUpload.push(Object.assign(result.file, { id: result.id }));\n }\n });\n\n // handle multiple file setting\n if (this.allowMultipleFiles) {\n this.files = [...this.files, ...filesToUpload];\n return;\n }\n\n // handle single file setting\n if (filesToUpload.length) {\n const file = filesToUpload[0];\n this.files = [file];\n }\n }\n\n private onFilesUploaded(results: Array<FileUploadResult>): void {\n this.errors = [];\n\n const filesNotUploaded = results.filter(result => !result.uploaded);\n\n const event = new CustomEvent<FilesUploadedInfo>('on-files-uploaded', {\n detail: {\n allFiles: this.files,\n filesUploaded: results.filter(result => result.uploaded),\n filesNotUploaded,\n },\n });\n\n const uniqueErrors = filesNotUploaded\n ?.map(f => f.message)\n .filter((v, i, a) => a.indexOf(v) === i);\n this.errors = [...uniqueErrors];\n\n this.dispatchEvent(event);\n }\n\n private onFileClick(e: CustomEvent<FileInfo>): void {\n const event = new CustomEvent<FileChangeInfo>('on-file-clicked', {\n detail: { allFiles: this.files, file: e.detail.file },\n });\n\n this.dispatchEvent(event);\n }\n\n private onFileDelete(e: CustomEvent<FileInfo>): void {\n this.pendingFileDeletion = e.detail.file;\n\n if (this.askConfirmationOnDeleteFile) {\n this.isDeleteBulkFileDialogOpen = true;\n return;\n }\n\n this.handleDeleteBulkFile();\n }\n\n handleDeleteBulkFile() {\n this.files = [...this.files].filter(\n file => file.id !== this.pendingFileDeletion?.id\n );\n\n const event = new CustomEvent<FileChangeInfo>('on-file-removed', {\n detail: { allFiles: this.files, file: this.pendingFileDeletion },\n });\n\n this.isDeleteBulkFileDialogOpen = false;\n this.dispatchEvent(event);\n }\n\n public deleteLastFileWithoutConfirmation(): void {\n if (this.files.length === 0) {\n return; // no files to delete\n }\n\n this.pendingFileDeletion = this.files[this.files.length - 1];\n\n this.handleDeleteBulkFile();\n }\n\n private openFileUploadDialog(): void {\n this.fileRef.value?.click();\n }\n\n protected override firstUpdated(): void {\n this.files = [...this.defaultFiles];\n\n // connect the dropzone\n const dropzone = this.dropzoneRef.value;\n if (dropzone) {\n dropzone.addEventListener('dragenter', e => e.preventDefault());\n dropzone.addEventListener('dragover', e => e.preventDefault());\n dropzone.addEventListener('drop', this.onDrop.bind(this));\n }\n\n // connect the file input\n const fileElem = this.fileRef.value;\n if (fileElem) {\n fileElem.addEventListener('change', this.onFileChange.bind(this));\n }\n\n // calculate the maxBytes based on props\n // Calculate the max file size in bytes to use for checking if files are too large\n const totalBytesForStorageUnit = getTotalBytes(this.maxFileSizeUnit);\n this.maxFileSizeInBytes = this.maxFileSizeValue * totalBytesForStorageUnit;\n }\n\n protected update(changedProperties: PropertyValues) {\n super.update(changedProperties);\n\n if (changedProperties.has('defaultFiles')) {\n this.files = [\n ...this.files.filter(\n file => !this.defaultFiles.some(x => x.name === file.name)\n ),\n ...this.defaultFiles,\n ];\n }\n }\n\n isFileDeletable(file: UploaderFile): boolean {\n if (this.defaultFiles.some(x => x.name === file.name)) {\n return this.allowDeleteDefaultFiles;\n }\n\n return true;\n }\n\n private renderFileList(files: Array<UploaderFile> = []): TemplateResult<1> {\n const sortedFiles = sortFilesAscending(files);\n const chips = sortedFiles.map(\n (file?: UploaderFile) => html`<ix-file-chip\n .file=${file}\n .deletable=${this.isFileDeletable(file!)}\n @on-file-click=${this.onFileClick}\n @on-file-delete=${this.onFileDelete}\n ></ix-file-chip>`\n );\n\n const uploadedFileListClasses = {\n 'uploaded-file-list': true,\n 'uploaded-file-list--spaced': !this.hideBody,\n };\n\n return html`\n <ul class=\"${classMap(uploadedFileListClasses)}\">\n ${chips}\n ${this.showTemplateFileLink\n ? html`<li class=\"ix-file-uploader__template-file\">\n <slot name=\"template-file\"></slot>\n </li>`\n : nothing}\n </ul>\n ${this.renderDeleteBulkFileConfirmationDialog()}\n `;\n }\n\n protected override updated(_: PropertyValues) {\n const formData = new FormData();\n\n this.files.forEach(file => {\n formData.append(`${this.name}[]`, file);\n });\n\n this.internals.setFormValue(formData);\n }\n\n renderDeleteBulkFileConfirmationDialog() {\n if (!this.askConfirmationOnDeleteFile) return nothing;\n\n return html`<ix-dialog\n id=\"deleteFileConfirmationDialog\"\n ?open=${this.isDeleteBulkFileDialogOpen}\n preventCloseOnScrimClick=\"true\"\n @closed=${() => {\n this.isDeleteBulkFileDialogOpen = false;\n }}\n @close=${() => {\n this.isDeleteBulkFileDialogOpen = false;\n }}\n >\n <form\n slot=\"content\"\n id=\"delete-file-id\"\n method=\"dialog\"\n class=\"delete-file-confirmation-dialog\"\n >\n ${this.deleteConfirmationDialogLabel}\n </form>\n <div slot=\"actions\">\n <ix-button\n appearance=\"text\"\n @click=${() => {\n this.isDeleteBulkFileDialogOpen = false;\n }}\n >\n <span class=\"button-label\">NO</span>\n </ix-button>\n <ix-button\n appearance=\"text\"\n name=\"submitBtn\"\n @click=${() => this.handleDeleteBulkFile()}\n >\n <span class=\"button-label\">YES</span>\n </ix-button>\n </div>\n </ix-dialog>`;\n }\n\n renderHintText() {\n if (!this.hintText) {\n return nothing;\n }\n\n return html`<div class=\"ix-file-uploader__hint-text\">\n ${this.hintText}\n </div>`;\n }\n\n renderErrors() {\n return html` <div class=\"error-text\">\n ${this.errors.map(e => html`<span>* ${e}</span>`)}\n </div>`;\n }\n\n renderBody() {\n const accept = this.extensions.map(ext => `.${ext}`).join(', ');\n\n const classes = {\n 'ix-file-uploader--hide-body': this.hideBody,\n };\n\n return html`<div class=${classMap(classes)}>\n <div\n class=\"dropzone\"\n @click=${this.openFileUploadDialog}\n @keyup=${this.openFileUploadDialog}\n ${ref(this.dropzoneRef)}\n >\n <label class=\"ix-file-uploader__label\" for=\"fileUploader\"\n >${this.headerText}</label\n >\n <div class=\"ix-file-uploader__help-text\" id=\"fileUploaderDesc\">\n ${this.bodyText}\n </div>\n <input\n id=\"fileUploader\"\n accept=${accept}\n class=\"file-input\"\n ?multiple=${this.allowMultipleFiles}\n onchange=${(e: Event) => this.onFileChange(e)}\n ${ref(this.fileRef)}\n aria-describedby=\"fileUploaderDesc\"\n type=\"file\"\n />\n </div>\n ${this.renderErrors()} ${this.renderHintText()}\n </div>`;\n }\n\n protected render(): TemplateResult<1> {\n return html`<div\n class=${classMap({\n 'ix-file-uploader': true,\n error: this.errors.length || this.error,\n })}\n >\n ${this.renderBody()}\n ${this.files.length ? this.renderFileList(this.files) : nothing}\n </div>`;\n }\n}\n"]}
@@ -1,10 +1,249 @@
1
- import{__decorate}from"tslib";import{css,svg,LitElement,nothing,html}from"lit";import{property,state}from"lit/decorators.js";import{createRef,ref}from"lit/directives/ref.js";import{classMap}from"lit/directives/class-map.js";import"@digital-realty/ix-icon-button/ix-icon-button.js";import"@digital-realty/ix-dialog/ix-dialog.js";let IxFileChipStyles=css`.file-chip{align-items:center;background:#f5f7ff;cursor:pointer;display:flex;flex:auto;padding:4px 8px;height:40px}.file-chip span{margin-right:10px;font-size:var(--ix-file-chip-font-size,var(--text-small-size,1rem));line-height:var(--ix-file-chip-line-height,var(--text-small-line-height,1.3rem));letter-spacing:var(--ix-file-chip-letter-spacing,var(--text-small-letter-spacing,.15px));color:var(--ix-file-chip-color, var(--clr-on-surface, 'inherit'))}.delete-icon{color:var(--md-sys-color-error)}`,trash=svg`<svg viewBox="0 0 24 24"><path d="M15.5 4H19V6H5V4H8.5L9.5 3H14.5L15.5 4ZM8 21C6.9 21 6 20.1 6 19V7H18V19C18 20.1 17.1 21 16 21H8Z"/></svg>`;class IxFileChip extends LitElement{constructor(){super(...arguments),this.deletable=!0}onClick(){var e=new CustomEvent("on-file-click",{detail:{file:this.file}});this.dispatchEvent(e)}onDelete(){var e;this.deletable&&(e=new CustomEvent("on-file-delete",{detail:{file:this.file}}),this.dispatchEvent(e))}render(){var e;return html`<li class="file-chip"><span @click="${this.onClick}">${null==(e=this.file)?void 0:e.name} </span>${this.deletable?html`<ix-icon-button @click="${this.onDelete}" name="delete-button"><ix-icon slot="default" class="delete-icon">${trash}</ix-icon></ix-icon-button>`:nothing}</li>`}}IxFileChip.styles=[IxFileChipStyles],__decorate([property({type:Object})],IxFileChip.prototype,"file",void 0),__decorate([property({type:Boolean})],IxFileChip.prototype,"deletable",void 0),customElements.define("ix-file-chip",IxFileChip),(e=>{e.B="B",e.KB="KB",e.MB="MB",e.GB="GB",e.TB="TB",e.PB="PB",e.EB="EB",e.ZB="ZB",e.YB="YB"})(DataStorageUnit=DataStorageUnit||{});var DataStorageUnit,DataStorageUnit$1=DataStorageUnit;let KB=1024,MB=1024*KB,GB=1024*MB,TB=1024*GB,PB=1024*TB,EB=1024*PB,ZB=1024*EB,YB=1024*ZB,getTotalBytes=e=>{switch(e){case DataStorageUnit$1.KB:return KB;case DataStorageUnit$1.MB:return MB;case DataStorageUnit$1.GB:return GB;case DataStorageUnit$1.TB:return TB;case DataStorageUnit$1.PB:return PB;case DataStorageUnit$1.EB:return EB;case DataStorageUnit$1.ZB:return ZB;case DataStorageUnit$1.YB:return YB;default:return 0}},mimeTypeMap={"csv-application/vnd.ms-excel":"text/csv"};function mapBrowserContentTypes(e,i){return mimeTypeMap[e+"-"+i.type]?new File([i],i.name,{type:mimeTypeMap[e+"-"+i.type]}):i}let processFiles=e=>{var{currentFiles:t,extensions:l,filesToProcess:e,maxFileCount:a,maxFileSizeInBytes:o,allowDuplicates:r}=e,s=[];let n=0;for(let i of e){var p=i.name.split(".").pop()||"",d=l.includes(p.toLocaleLowerCase());if(i=mapBrowserContentTypes(p,i),d)if(i.size>o)s.push({file:i,message:"The file you are attempting to upload exceeds the maximum size allowed.",uploaded:!1,id:crypto.randomUUID()});else if(t.length+n>=a)s.push({file:i,message:`File not uploaded; it would exceed the maximum number of files (${a})`,uploaded:!1,id:crypto.randomUUID()});else{if(!r)if(t.some(e=>e.name===i.name)){p="File not uploaded; there is already a file named "+i.name;s.push({file:i,message:p,uploaded:!1,id:crypto.randomUUID()});continue}s.push({file:i,message:"File uploaded",uploaded:!0,id:crypto.randomUUID()}),n+=1}else{d=`File extension for "${i.name}" is not allowed`;s.push({file:i,message:d,uploaded:!1,id:crypto.randomUUID()})}}return s},sortFilesAscending=(e=[])=>e.sort((e,i)=>{e=e.name.toLocaleLowerCase(),i=i.name.toLocaleLowerCase();return e<i?-1:0}),IxFileUploaderStyles=css`.ix-file-uploader{display:flex;flex-direction:column;justify-content:center;min-width:320px}.ix-file-uploader--hide-body{display:none}.dropzone{background:var(--clr-surface,#f5f7ff);border:1px dashed var(--clr-info,#2196f3);border-radius:3px;cursor:pointer;display:flex;flex-direction:column;gap:4px;padding:16px}.ix-file-uploader__label{color:var(
1
+ import{__decorate as e}from"tslib";import{css as i,svg as t,LitElement as l,nothing as o,html as s}from"lit";import{property as a,state as r}from"lit/decorators.js";import{createRef as n,ref as d}from"lit/directives/ref.js";import{classMap as p}from"lit/directives/class-map.js";import"@digital-realty/ix-icon-button/ix-icon-button.js";import"@digital-realty/ix-dialog/ix-dialog.js";const h=i`
2
+ .file-chip {
3
+ align-items: center;
4
+ background: #f5f7ff;
5
+ cursor: pointer;
6
+ display: flex;
7
+ flex: auto;
8
+ padding: 4px 8px;
9
+ height: 40px;
10
+ }
11
+
12
+ .file-chip span {
13
+ margin-right: 10px;
14
+
15
+ font-size: var(--ix-file-chip-font-size, var(--text-small-size, 1rem));
16
+ line-height: var(
17
+ --ix-file-chip-line-height,
18
+ var(--text-small-line-height, 1.3rem)
19
+ );
20
+ letter-spacing: var(
21
+ --ix-file-chip-letter-spacing,
22
+ var(--text-small-letter-spacing, 0.15px)
23
+ );
24
+ color: var(--ix-file-chip-color, var(--clr-on-surface, 'inherit'));
25
+ }
26
+
27
+ .delete-icon {
28
+ color: var(--md-sys-color-error);
29
+ }
30
+ `,f=t`<svg viewBox="0 0 24 24"><path d="M15.5 4H19V6H5V4H8.5L9.5 3H14.5L15.5 4ZM8 21C6.9 21 6 20.1 6 19V7H18V19C18 20.1 17.1 21 16 21H8Z" /></svg>`;class c extends l{constructor(){super(...arguments),this.deletable=!0}onClick(){const e=new CustomEvent("on-file-click",{detail:{file:this.file}});this.dispatchEvent(e)}onDelete(){if(this.deletable){const e=new CustomEvent("on-file-delete",{detail:{file:this.file}});this.dispatchEvent(e)}}render(){var e;return s`<li class="file-chip">
31
+ <span @click=${this.onClick}> ${null===(e=this.file)||void 0===e?void 0:e.name} </span>
32
+
33
+ ${this.deletable?s`<ix-icon-button @click=${this.onDelete} name="delete-button">
34
+ <ix-icon slot="default" class="delete-icon"> ${f} </ix-icon>
35
+ </ix-icon-button>`:o}
36
+ </li>`}}var u;c.styles=[h],e([a({type:Object})],c.prototype,"file",void 0),e([a({type:Boolean})],c.prototype,"deletable",void 0),customElements.define("ix-file-chip",c),function(e){e.B="B",e.KB="KB",e.MB="MB",e.GB="GB",e.TB="TB",e.PB="PB",e.EB="EB",e.ZB="ZB",e.YB="YB"}(u||(u={}));var m=u;const x=1048576,v=1024*x,g=1024*v,y=1024*g,F=1024*y,D=1024*F,B=1024*D,b={"csv-application/vnd.ms-excel":"text/csv"};function w(e,i){return b[`${e}-${i.type}`]?new File([i],i.name,{type:b[`${e}-${i.type}`]}):i}const $=i`
37
+ .ix-file-uploader {
38
+ display: flex;
39
+ flex-direction: column;
40
+ justify-content: center;
41
+ min-width: 320px;
42
+ }
43
+ .ix-file-uploader--hide-body {
44
+ display: none;
45
+ }
46
+ .dropzone {
47
+ background: var(--clr-surface, #f5f7ff);
48
+ border: 1px dashed var(--clr-info, #2196f3);
49
+ border-radius: 3px;
50
+ cursor: pointer;
51
+ display: flex;
52
+ flex-direction: column;
53
+ gap: 4px;
54
+ padding: 16px;
55
+ }
56
+ .ix-file-uploader__label {
57
+ color: var(
2
58
  --ix-file-uploader-label-color,
3
59
  var(--clr-on-surface, 'inherit')
4
- );font-family:var(
60
+ );
61
+ font-family: var(
5
62
  --ix-file-uploader-label-font-family,
6
63
  var(--root-secondary-font, 'inherit')
7
- );font-size:var(--ix-file-uploader-label-font-size,var(--text-small-size,.75rem));font-style:normal;font-weight:var(--ix-file-uploader-label-font-weight,700);line-height:var(--ix-file-uploader-label-line-height,var(--text-small-line-height,16px));letter-spacing:var(--ix-file-uploader-label-letter-spacing,var(--text-small-letter-spacing,1.25px));text-align:center;text-transform:var(--ix-file-uploader-label-text-transform,uppercase);margin:auto;width:var(--ix-file-uploader-label-width,100%)}.ix-file-uploader__help-text{color:var(--ix-file-uploader-help-color, var(--clr-on-surface, 'inherit'));font-family:var(
64
+ );
65
+ font-size: var(
66
+ --ix-file-uploader-label-font-size,
67
+ var(--text-small-size, 0.75rem)
68
+ );
69
+ font-style: normal;
70
+ font-weight: var(--ix-file-uploader-label-font-weight, 700);
71
+ line-height: var(
72
+ --ix-file-uploader-label-line-height,
73
+ var(--text-small-line-height, 16px)
74
+ );
75
+ letter-spacing: var(
76
+ --ix-file-uploader-label-letter-spacing,
77
+ var(--text-small-letter-spacing, 1.25px)
78
+ );
79
+ text-align: center;
80
+ text-transform: var(--ix-file-uploader-label-text-transform, uppercase);
81
+ margin: auto;
82
+ width: var(--ix-file-uploader-label-width, 100%);
83
+ }
84
+ .ix-file-uploader__help-text {
85
+ color: var(--ix-file-uploader-help-color, var(--clr-on-surface, 'inherit'));
86
+ font-family: var(
8
87
  --ix-file-uploader-help-font-family,
9
88
  var(--root-secondary-font, 'inherit')
10
- );font-size:var(--ix-file-uploader-help-font-size,var(--text-small-size,.75rem));line-height:var(--ix-file-uploader-help-line-height,var(--text-small-line-height,16px));letter-spacing:var(--ix-file-uploader-help-letter-spacing,var(--text-small-letter-spacing,1.25px));text-align:center}.uploaded-file-list{display:flex;flex-wrap:wrap;gap:16px;list-style:none;margin:0;padding:0}.uploaded-file-list--spaced{margin-top:32px}.file-input{opacity:0;border-width:0;clip:rect(0,0,0,0);height:1px;margin:-1px;overflow:hidden;padding:0;white-space:nowrap;width:1px}.error .dropzone{border-color:var(--md-sys-color-error)}.ix-file-uploader__hint-text{font-family:var(--root-primary-font, 'inherit') font-weight: 400;font-size:12px;line-height:16px;letter-spacing:.4px;padding-top:.5rem;color:var(--clr-on-surface, 'inherit')}.ix-file-uploader__template-file{display:flex;align-items:center}.delete-file-confirmation-dialog{max-width:560px;font-family:var(--root-secondary-font, 'Red Hat Display');font-weight:700;font-size:20px;leading-trim:NONE;line-height:24px;letter-spacing:.15px}`;class IxFileUploader extends LitElement{constructor(){super(...arguments),this.internals=this.attachInternals(),this.dropzoneRef=createRef(),this.fileRef=createRef(),this.showTemplateFileLink=!1,this.allowMultipleFiles=!1,this.allowDuplicates=!1,this.headerText="",this.bodyText="",this.hintText=void 0,this.defaultFiles=[],this.allowDeleteDefaultFiles=!1,this.hideBody=!1,this.extensions=[],this.maxFileCount=10,this.maxFileSizeUnit=DataStorageUnit$1.MB,this.maxFileSizeValue=10,this.name="ix-file-uploader",this.error=!1,this.askConfirmationOnDeleteFile=!1,this.deleteConfirmationDialogLabel="Are you sure you want to delete your upload file?",this.isDeleteBulkFileDialogOpen=!1,this.pendingFileDeletion=void 0,this.files=[],this.maxFileSizeInBytes=0}get form(){return this.internals.form}onDrop(e){e.preventDefault(),e.dataTransfer&&(e=Array.from(e.dataTransfer.files),this.process(e))}onFileChange(e){e=e.currentTarget.files,e=Array.from(e);this.process(e),this.fileRef.value.files=(new DataTransfer).files}get allowedMaxFileCount(){return this.allowMultipleFiles?this.maxFileCount:1}process(e){e=processFiles({currentFiles:this.files,extensions:this.extensions,filesToProcess:e,maxFileCount:this.allowedMaxFileCount,maxFileSizeInBytes:this.maxFileSizeInBytes,allowDuplicates:this.allowDuplicates});this.updateState(e),this.onFilesUploaded(e)}updateState(e=[]){let i=[];e.forEach(e=>{e.uploaded&&i.push(Object.assign(e.file,{id:e.id}))}),this.allowMultipleFiles?this.files=[...this.files,...i]:i.length&&(e=i[0],this.files=[e])}onFilesUploaded(e){e=new CustomEvent("on-files-uploaded",{detail:{allFiles:this.files,filesUploaded:e.filter(e=>e.uploaded),filesNotUploaded:e.filter(e=>!e.uploaded)}});this.dispatchEvent(e)}onFileClick(e){e=new CustomEvent("on-file-clicked",{detail:{allFiles:this.files,file:e.detail.file}});this.dispatchEvent(e)}onFileDelete(e){this.pendingFileDeletion=e.detail.file,this.askConfirmationOnDeleteFile?this.isDeleteBulkFileDialogOpen=!0:this.handleDeleteBulkFile()}handleDeleteBulkFile(){this.files=[...this.files].filter(e=>e.id!==(null==(e=this.pendingFileDeletion)?void 0:e.id));var e=new CustomEvent("on-file-removed",{detail:{allFiles:this.files,file:this.pendingFileDeletion}});this.isDeleteBulkFileDialogOpen=!1,this.dispatchEvent(e)}deleteLastFileWithoutConfirmation(){0!==this.files.length&&(this.pendingFileDeletion=this.files[this.files.length-1],this.handleDeleteBulkFile())}openFileUploadDialog(){var e;null!=(e=this.fileRef.value)&&e.click()}firstUpdated(){this.files=[...this.defaultFiles];var e=this.dropzoneRef.value,e=(e&&(e.addEventListener("dragenter",e=>e.preventDefault()),e.addEventListener("dragover",e=>e.preventDefault()),e.addEventListener("drop",this.onDrop.bind(this))),this.fileRef.value),e=(e&&e.addEventListener("change",this.onFileChange.bind(this)),getTotalBytes(this.maxFileSizeUnit));this.maxFileSizeInBytes=this.maxFileSizeValue*e}update(e){super.update(e),e.has("defaultFiles")&&(this.files=[...this.files.filter(i=>!this.defaultFiles.some(e=>e.name===i.name)),...this.defaultFiles])}isFileDeletable(i){return!this.defaultFiles.some(e=>e.name===i.name)||this.allowDeleteDefaultFiles}renderFileList(e=[]){var e=sortFilesAscending(e).map(e=>html`<ix-file-chip .file="${e}" .deletable="${this.isFileDeletable(e)}" @on-file-click="${this.onFileClick}" @on-file-delete="${this.onFileDelete}"></ix-file-chip>`),i={"uploaded-file-list":!0,"uploaded-file-list--spaced":!this.hideBody};return html`<ul class="${classMap(i)}">${e} ${this.showTemplateFileLink?html`<li class="ix-file-uploader__template-file"><slot name="template-file"></slot></li>`:nothing}</ul>${this.renderDeleteBulkFileConfirmationDialog()}`}updated(e){let i=new FormData;this.files.forEach(e=>{i.append(this.name+"[]",e)}),this.internals.setFormValue(i)}renderDeleteBulkFileConfirmationDialog(){return this.askConfirmationOnDeleteFile?html`<ix-dialog id="deleteFileConfirmationDialog" ?open="${this.isDeleteBulkFileDialogOpen}" preventCloseOnScrimClick="true" @closed="${()=>{this.isDeleteBulkFileDialogOpen=!1}}" @close="${()=>{this.isDeleteBulkFileDialogOpen=!1}}"><form slot="content" id="delete-file-id" method="dialog" class="delete-file-confirmation-dialog">${this.deleteConfirmationDialogLabel}</form><div slot="actions"><ix-button appearance="text" @click="${()=>{this.isDeleteBulkFileDialogOpen=!1}}"><span class="button-label">NO</span></ix-button><ix-button appearance="text" name="submitBtn" @click="${()=>this.handleDeleteBulkFile()}"><span class="button-label">YES</span></ix-button></div></ix-dialog>`:nothing}renderHintText(){return this.hintText?html`<div class="ix-file-uploader__hint-text">${this.hintText}</div>`:nothing}renderBody(){var e=this.extensions.map(e=>"."+e).join(", "),i={"ix-file-uploader--hide-body":this.hideBody};return html`<div class="${classMap(i)}"><div class="dropzone" @click="${this.openFileUploadDialog}" @keyup="${this.openFileUploadDialog}" ${ref(this.dropzoneRef)}><div class="ix-file-uploader__label">${this.headerText}</div><div class="ix-file-uploader__help-text">${this.bodyText}</div><input accept="${e}" class="file-input" ?multiple="${this.allowMultipleFiles}" onchange="${e=>this.onFileChange(e)}" ${ref(this.fileRef)} type="file"></div>${this.renderHintText()}</div>`}render(){return html`<div class="${classMap({"ix-file-uploader":!0,error:this.error})}">${this.renderBody()} ${this.files.length?this.renderFileList(this.files):nothing}</div>`}}IxFileUploader.styles=[IxFileUploaderStyles],IxFileUploader.formAssociated=!0,__decorate([property({type:Boolean})],IxFileUploader.prototype,"showTemplateFileLink",void 0),__decorate([property({type:Boolean})],IxFileUploader.prototype,"allowMultipleFiles",void 0),__decorate([property({type:Boolean})],IxFileUploader.prototype,"allowDuplicates",void 0),__decorate([property()],IxFileUploader.prototype,"headerText",void 0),__decorate([property()],IxFileUploader.prototype,"bodyText",void 0),__decorate([property()],IxFileUploader.prototype,"hintText",void 0),__decorate([property({type:Array})],IxFileUploader.prototype,"defaultFiles",void 0),__decorate([property({type:Boolean})],IxFileUploader.prototype,"allowDeleteDefaultFiles",void 0),__decorate([property({type:Boolean})],IxFileUploader.prototype,"hideBody",void 0),__decorate([property({type:Array})],IxFileUploader.prototype,"extensions",void 0),__decorate([property({type:Number})],IxFileUploader.prototype,"maxFileCount",void 0),__decorate([property()],IxFileUploader.prototype,"maxFileSizeUnit",void 0),__decorate([property({type:Number})],IxFileUploader.prototype,"maxFileSizeValue",void 0),__decorate([property()],IxFileUploader.prototype,"name",void 0),__decorate([property({type:Boolean})],IxFileUploader.prototype,"error",void 0),__decorate([property({type:Boolean})],IxFileUploader.prototype,"askConfirmationOnDeleteFile",void 0),__decorate([property()],IxFileUploader.prototype,"deleteConfirmationDialogLabel",void 0),__decorate([state()],IxFileUploader.prototype,"isDeleteBulkFileDialogOpen",void 0),__decorate([state()],IxFileUploader.prototype,"pendingFileDeletion",void 0),__decorate([state()],IxFileUploader.prototype,"files",void 0),customElements.define("ix-file-uploader",IxFileUploader);
89
+ );
90
+ font-size: var(
91
+ --ix-file-uploader-help-font-size,
92
+ var(--text-small-size, 0.75rem)
93
+ );
94
+ line-height: var(
95
+ --ix-file-uploader-help-line-height,
96
+ var(--text-small-line-height, 16px)
97
+ );
98
+ letter-spacing: var(
99
+ --ix-file-uploader-help-letter-spacing,
100
+ var(--text-small-letter-spacing, 1.25px)
101
+ );
102
+ text-align: center;
103
+ }
104
+ .uploaded-file-list {
105
+ display: flex;
106
+ flex-wrap: wrap;
107
+ gap: 16px;
108
+ list-style: none;
109
+ margin: 0;
110
+ padding: 0;
111
+ }
112
+ .uploaded-file-list--spaced {
113
+ margin-top: 32px;
114
+ }
115
+ .file-input {
116
+ /*
117
+ Per MDN -> https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file
118
+ "Note: opacity is used to hide the file input instead of visibility: hidden or display: none, because assistive technology interprets the latter two styles to mean the file input isn't interactive."
119
+ */
120
+ opacity: 0;
121
+
122
+ /*
123
+ Adapted styles from https://tailwindcss.com/docs/screen-readers
124
+ */
125
+ border-width: 0;
126
+ clip: rect(0, 0, 0, 0);
127
+ height: 1px;
128
+ margin: -1px;
129
+ overflow: hidden;
130
+ padding: 0;
131
+ white-space: nowrap;
132
+ width: 1px;
133
+ }
134
+ .error .dropzone {
135
+ border-color: var(--md-sys-color-error);
136
+ }
137
+
138
+ .error .error-text {
139
+ color: var(--md-sys-color-error);
140
+ padding-left: 0.75rem;
141
+ font-size: 0.75rem;
142
+ font-weight: 400;
143
+ display: flex;
144
+ flex-direction: column;
145
+ margin-top: 0.5rem;
146
+ line-height: 0.75rem;
147
+ }
148
+
149
+ .ix-file-uploader__hint-text{
150
+ font-family: var(--root-primary-font, 'inherit')
151
+ font-weight: 400;
152
+ font-size: 12px;
153
+ line-height: 16px;
154
+ letter-spacing: 0.4px;
155
+ padding-top: 0.5rem;
156
+ color: var(--clr-on-surface, 'inherit');
157
+ }
158
+
159
+ .ix-file-uploader__template-file {
160
+ display: flex;
161
+ align-items: center;
162
+ }
163
+ .delete-file-confirmation-dialog {
164
+ max-width: 560px;
165
+ font-family: var(--root-secondary-font, 'Red Hat Display');
166
+ font-weight: 700;
167
+ font-size: 20px;
168
+ leading-trim: NONE;
169
+ line-height: 24px;
170
+ letter-spacing: 0.15px;
171
+ }
172
+ `;class k extends l{constructor(){super(...arguments),this.internals=this.attachInternals(),this.dropzoneRef=n(),this.fileRef=n(),this.showTemplateFileLink=!1,this.allowMultipleFiles=!1,this.allowDuplicates=!1,this.headerText="",this.bodyText="",this.hintText=void 0,this.defaultFiles=[],this.allowDeleteDefaultFiles=!1,this.hideBody=!1,this.extensions=[],this.maxFileCount=10,this.maxFileSizeUnit=m.MB,this.maxFileSizeValue=10,this.name="ix-file-uploader",this.error=!1,this.askConfirmationOnDeleteFile=!1,this.deleteConfirmationDialogLabel="Are you sure you want to delete your upload file?",this.isDeleteBulkFileDialogOpen=!1,this.pendingFileDeletion=void 0,this.files=[],this.errors=[],this.maxFileSizeInBytes=0}get form(){return this.internals.form}onDrop(e){if(e.preventDefault(),!e.dataTransfer)return;const i=Array.from(e.dataTransfer.files);this.process(i)}onFileChange(e){const i=e.currentTarget.files,t=Array.from(i);this.process(t),this.fileRef.value.files=(new DataTransfer).files}get allowedMaxFileCount(){return this.allowMultipleFiles?this.maxFileCount:1}process(e){const i=(e=>{const{currentFiles:i,extensions:t,filesToProcess:l,maxFileCount:o,maxFileSizeInBytes:s,allowDuplicates:a}=e,r=[];let n=0;for(let e of l){const l=e.name.split(".").pop()||"",d=t.includes(l.toLocaleLowerCase());if(e=w(l,e),!d){const i=`File extension for "${e.name}" is not allowed`;r.push({file:e,message:i,uploaded:!1,id:crypto.randomUUID()});continue}if(e.size>s){const i="The file you are attempting to upload exceeds the maximum size allowed.";r.push({file:e,message:i,uploaded:!1,id:crypto.randomUUID()});continue}if(i.length+n>=o){const i=`File not uploaded; it would exceed the maximum number of files (${o})`;r.push({file:e,message:i,uploaded:!1,id:crypto.randomUUID()});continue}if(!a&&i.some(i=>i.name===e.name)){const i=`File not uploaded; there is already a file named ${e.name}`;r.push({file:e,message:i,uploaded:!1,id:crypto.randomUUID()});continue}r.push({file:e,message:"File uploaded",uploaded:!0,id:crypto.randomUUID()}),n+=1}return r})({currentFiles:this.files,extensions:this.extensions,filesToProcess:e,maxFileCount:this.allowedMaxFileCount,maxFileSizeInBytes:this.maxFileSizeInBytes,allowDuplicates:this.allowDuplicates});this.updateState(i),this.onFilesUploaded(i)}updateState(e=[]){const i=[];if(e.forEach(e=>{e.uploaded&&i.push(Object.assign(e.file,{id:e.id}))}),this.allowMultipleFiles)this.files=[...this.files,...i];else if(i.length){const e=i[0];this.files=[e]}}onFilesUploaded(e){this.errors=[];const i=e.filter(e=>!e.uploaded),t=new CustomEvent("on-files-uploaded",{detail:{allFiles:this.files,filesUploaded:e.filter(e=>e.uploaded),filesNotUploaded:i}}),l=null==i?void 0:i.map(e=>e.message).filter((e,i,t)=>t.indexOf(e)===i);this.errors=[...l],this.dispatchEvent(t)}onFileClick(e){const i=new CustomEvent("on-file-clicked",{detail:{allFiles:this.files,file:e.detail.file}});this.dispatchEvent(i)}onFileDelete(e){this.pendingFileDeletion=e.detail.file,this.askConfirmationOnDeleteFile?this.isDeleteBulkFileDialogOpen=!0:this.handleDeleteBulkFile()}handleDeleteBulkFile(){this.files=[...this.files].filter(e=>{var i;return e.id!==(null===(i=this.pendingFileDeletion)||void 0===i?void 0:i.id)});const e=new CustomEvent("on-file-removed",{detail:{allFiles:this.files,file:this.pendingFileDeletion}});this.isDeleteBulkFileDialogOpen=!1,this.dispatchEvent(e)}deleteLastFileWithoutConfirmation(){0!==this.files.length&&(this.pendingFileDeletion=this.files[this.files.length-1],this.handleDeleteBulkFile())}openFileUploadDialog(){var e;null===(e=this.fileRef.value)||void 0===e||e.click()}firstUpdated(){this.files=[...this.defaultFiles];const e=this.dropzoneRef.value;e&&(e.addEventListener("dragenter",e=>e.preventDefault()),e.addEventListener("dragover",e=>e.preventDefault()),e.addEventListener("drop",this.onDrop.bind(this)));const i=this.fileRef.value;i&&i.addEventListener("change",this.onFileChange.bind(this));const t=(e=>{switch(e){case m.KB:return 1024;case m.MB:return x;case m.GB:return v;case m.TB:return g;case m.PB:return y;case m.EB:return F;case m.ZB:return D;case m.YB:return B;default:return 0}})(this.maxFileSizeUnit);this.maxFileSizeInBytes=this.maxFileSizeValue*t}update(e){super.update(e),e.has("defaultFiles")&&(this.files=[...this.files.filter(e=>!this.defaultFiles.some(i=>i.name===e.name)),...this.defaultFiles])}isFileDeletable(e){return!this.defaultFiles.some(i=>i.name===e.name)||this.allowDeleteDefaultFiles}renderFileList(e=[]){const i=((e=[])=>e.sort((e,i)=>{const t=e.name.toLocaleLowerCase(),l=i.name.toLocaleLowerCase();return t<l?-1:l>t?1:0}))(e).map(e=>s`<ix-file-chip
173
+ .file=${e}
174
+ .deletable=${this.isFileDeletable(e)}
175
+ @on-file-click=${this.onFileClick}
176
+ @on-file-delete=${this.onFileDelete}
177
+ ></ix-file-chip>`),t={"uploaded-file-list":!0,"uploaded-file-list--spaced":!this.hideBody};return s`
178
+ <ul class="${p(t)}">
179
+ ${i}
180
+ ${this.showTemplateFileLink?s`<li class="ix-file-uploader__template-file">
181
+ <slot name="template-file"></slot>
182
+ </li>`:o}
183
+ </ul>
184
+ ${this.renderDeleteBulkFileConfirmationDialog()}
185
+ `}updated(e){const i=new FormData;this.files.forEach(e=>{i.append(`${this.name}[]`,e)}),this.internals.setFormValue(i)}renderDeleteBulkFileConfirmationDialog(){return this.askConfirmationOnDeleteFile?s`<ix-dialog
186
+ id="deleteFileConfirmationDialog"
187
+ ?open=${this.isDeleteBulkFileDialogOpen}
188
+ preventCloseOnScrimClick="true"
189
+ @closed=${()=>{this.isDeleteBulkFileDialogOpen=!1}}
190
+ @close=${()=>{this.isDeleteBulkFileDialogOpen=!1}}
191
+ >
192
+ <form
193
+ slot="content"
194
+ id="delete-file-id"
195
+ method="dialog"
196
+ class="delete-file-confirmation-dialog"
197
+ >
198
+ ${this.deleteConfirmationDialogLabel}
199
+ </form>
200
+ <div slot="actions">
201
+ <ix-button
202
+ appearance="text"
203
+ @click=${()=>{this.isDeleteBulkFileDialogOpen=!1}}
204
+ >
205
+ <span class="button-label">NO</span>
206
+ </ix-button>
207
+ <ix-button
208
+ appearance="text"
209
+ name="submitBtn"
210
+ @click=${()=>this.handleDeleteBulkFile()}
211
+ >
212
+ <span class="button-label">YES</span>
213
+ </ix-button>
214
+ </div>
215
+ </ix-dialog>`:o}renderHintText(){return this.hintText?s`<div class="ix-file-uploader__hint-text">
216
+ ${this.hintText}
217
+ </div>`:o}renderErrors(){return s` <div class="error-text">
218
+ ${this.errors.map(e=>s`<span>* ${e}</span>`)}
219
+ </div>`}renderBody(){const e=this.extensions.map(e=>`.${e}`).join(", "),i={"ix-file-uploader--hide-body":this.hideBody};return s`<div class=${p(i)}>
220
+ <div
221
+ class="dropzone"
222
+ @click=${this.openFileUploadDialog}
223
+ @keyup=${this.openFileUploadDialog}
224
+ ${d(this.dropzoneRef)}
225
+ >
226
+ <label class="ix-file-uploader__label" for="fileUploader"
227
+ >${this.headerText}</label
228
+ >
229
+ <div class="ix-file-uploader__help-text" id="fileUploaderDesc">
230
+ ${this.bodyText}
231
+ </div>
232
+ <input
233
+ id="fileUploader"
234
+ accept=${e}
235
+ class="file-input"
236
+ ?multiple=${this.allowMultipleFiles}
237
+ onchange=${e=>this.onFileChange(e)}
238
+ ${d(this.fileRef)}
239
+ aria-describedby="fileUploaderDesc"
240
+ type="file"
241
+ />
242
+ </div>
243
+ ${this.renderErrors()} ${this.renderHintText()}
244
+ </div>`}render(){return s`<div
245
+ class=${p({"ix-file-uploader":!0,error:this.errors.length||this.error})}
246
+ >
247
+ ${this.renderBody()}
248
+ ${this.files.length?this.renderFileList(this.files):o}
249
+ </div>`}}k.styles=[$],k.formAssociated=!0,e([a({type:Boolean})],k.prototype,"showTemplateFileLink",void 0),e([a({type:Boolean})],k.prototype,"allowMultipleFiles",void 0),e([a({type:Boolean})],k.prototype,"allowDuplicates",void 0),e([a()],k.prototype,"headerText",void 0),e([a()],k.prototype,"bodyText",void 0),e([a()],k.prototype,"hintText",void 0),e([a({type:Array})],k.prototype,"defaultFiles",void 0),e([a({type:Boolean})],k.prototype,"allowDeleteDefaultFiles",void 0),e([a({type:Boolean})],k.prototype,"hideBody",void 0),e([a({type:Array})],k.prototype,"extensions",void 0),e([a({type:Number})],k.prototype,"maxFileCount",void 0),e([a()],k.prototype,"maxFileSizeUnit",void 0),e([a({type:Number})],k.prototype,"maxFileSizeValue",void 0),e([a()],k.prototype,"name",void 0),e([a({type:Boolean})],k.prototype,"error",void 0),e([a({type:Boolean})],k.prototype,"askConfirmationOnDeleteFile",void 0),e([a()],k.prototype,"deleteConfirmationDialogLabel",void 0),e([r()],k.prototype,"isDeleteBulkFileDialogOpen",void 0),e([r()],k.prototype,"pendingFileDeletion",void 0),e([r()],k.prototype,"files",void 0),e([r()],k.prototype,"errors",void 0),customElements.define("ix-file-uploader",k);
@@ -100,6 +100,18 @@ const IxFileUploaderStyles = css `
100
100
  .error .dropzone {
101
101
  border-color: var(--md-sys-color-error);
102
102
  }
103
+
104
+ .error .error-text {
105
+ color: var(--md-sys-color-error);
106
+ padding-left: 0.75rem;
107
+ font-size: 0.75rem;
108
+ font-weight: 400;
109
+ display: flex;
110
+ flex-direction: column;
111
+ margin-top: 0.5rem;
112
+ line-height: 0.75rem;
113
+ }
114
+
103
115
  .ix-file-uploader__hint-text{
104
116
  font-family: var(--root-primary-font, 'inherit')
105
117
  font-weight: 400;
@@ -1 +1 @@
1
- {"version":3,"file":"ix-file-uploader-styles.js","sourceRoot":"","sources":["../../src/styles/ix-file-uploader-styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,oBAAoB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4H/B,CAAC;AAEF,eAAe,oBAAoB,CAAC","sourcesContent":["import { css } from 'lit';\n\nconst IxFileUploaderStyles = css`\n .ix-file-uploader {\n display: flex;\n flex-direction: column;\n justify-content: center;\n min-width: 320px;\n }\n .ix-file-uploader--hide-body {\n display: none;\n }\n .dropzone {\n background: var(--clr-surface, #f5f7ff);\n border: 1px dashed var(--clr-info, #2196f3);\n border-radius: 3px;\n cursor: pointer;\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding: 16px;\n }\n .ix-file-uploader__label {\n color: var(\n --ix-file-uploader-label-color,\n var(--clr-on-surface, 'inherit')\n );\n font-family: var(\n --ix-file-uploader-label-font-family,\n var(--root-secondary-font, 'inherit')\n );\n font-size: var(\n --ix-file-uploader-label-font-size,\n var(--text-small-size, 0.75rem)\n );\n font-style: normal;\n font-weight: var(--ix-file-uploader-label-font-weight, 700);\n line-height: var(\n --ix-file-uploader-label-line-height,\n var(--text-small-line-height, 16px)\n );\n letter-spacing: var(\n --ix-file-uploader-label-letter-spacing,\n var(--text-small-letter-spacing, 1.25px)\n );\n text-align: center;\n text-transform: var(--ix-file-uploader-label-text-transform, uppercase);\n margin: auto;\n width: var(--ix-file-uploader-label-width, 100%);\n }\n .ix-file-uploader__help-text {\n color: var(--ix-file-uploader-help-color, var(--clr-on-surface, 'inherit'));\n font-family: var(\n --ix-file-uploader-help-font-family,\n var(--root-secondary-font, 'inherit')\n );\n font-size: var(\n --ix-file-uploader-help-font-size,\n var(--text-small-size, 0.75rem)\n );\n line-height: var(\n --ix-file-uploader-help-line-height,\n var(--text-small-line-height, 16px)\n );\n letter-spacing: var(\n --ix-file-uploader-help-letter-spacing,\n var(--text-small-letter-spacing, 1.25px)\n );\n text-align: center;\n }\n .uploaded-file-list {\n display: flex;\n flex-wrap: wrap;\n gap: 16px;\n list-style: none;\n margin: 0;\n padding: 0;\n }\n .uploaded-file-list--spaced {\n margin-top: 32px;\n }\n .file-input {\n /*\n Per MDN -> https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file\n \"Note: opacity is used to hide the file input instead of visibility: hidden or display: none, because assistive technology interprets the latter two styles to mean the file input isn't interactive.\"\n */\n opacity: 0;\n\n /*\n Adapted styles from https://tailwindcss.com/docs/screen-readers\n */\n border-width: 0;\n clip: rect(0, 0, 0, 0);\n height: 1px;\n margin: -1px;\n overflow: hidden;\n padding: 0;\n white-space: nowrap;\n width: 1px;\n }\n .error .dropzone {\n border-color: var(--md-sys-color-error);\n }\n .ix-file-uploader__hint-text{\n font-family: var(--root-primary-font, 'inherit')\n font-weight: 400;\n font-size: 12px;\n line-height: 16px;\n letter-spacing: 0.4px;\n padding-top: 0.5rem;\n color: var(--clr-on-surface, 'inherit');\n }\n\n .ix-file-uploader__template-file {\n display: flex;\n align-items: center;\n }\n .delete-file-confirmation-dialog {\n max-width: 560px;\n font-family: var(--root-secondary-font, 'Red Hat Display');\n font-weight: 700;\n font-size: 20px;\n leading-trim: NONE;\n line-height: 24px;\n letter-spacing: 0.15px;\n}\n`;\n\nexport default IxFileUploaderStyles;\n"]}
1
+ {"version":3,"file":"ix-file-uploader-styles.js","sourceRoot":"","sources":["../../src/styles/ix-file-uploader-styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,oBAAoB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwI/B,CAAC;AAEF,eAAe,oBAAoB,CAAC","sourcesContent":["import { css } from 'lit';\n\nconst IxFileUploaderStyles = css`\n .ix-file-uploader {\n display: flex;\n flex-direction: column;\n justify-content: center;\n min-width: 320px;\n }\n .ix-file-uploader--hide-body {\n display: none;\n }\n .dropzone {\n background: var(--clr-surface, #f5f7ff);\n border: 1px dashed var(--clr-info, #2196f3);\n border-radius: 3px;\n cursor: pointer;\n display: flex;\n flex-direction: column;\n gap: 4px;\n padding: 16px;\n }\n .ix-file-uploader__label {\n color: var(\n --ix-file-uploader-label-color,\n var(--clr-on-surface, 'inherit')\n );\n font-family: var(\n --ix-file-uploader-label-font-family,\n var(--root-secondary-font, 'inherit')\n );\n font-size: var(\n --ix-file-uploader-label-font-size,\n var(--text-small-size, 0.75rem)\n );\n font-style: normal;\n font-weight: var(--ix-file-uploader-label-font-weight, 700);\n line-height: var(\n --ix-file-uploader-label-line-height,\n var(--text-small-line-height, 16px)\n );\n letter-spacing: var(\n --ix-file-uploader-label-letter-spacing,\n var(--text-small-letter-spacing, 1.25px)\n );\n text-align: center;\n text-transform: var(--ix-file-uploader-label-text-transform, uppercase);\n margin: auto;\n width: var(--ix-file-uploader-label-width, 100%);\n }\n .ix-file-uploader__help-text {\n color: var(--ix-file-uploader-help-color, var(--clr-on-surface, 'inherit'));\n font-family: var(\n --ix-file-uploader-help-font-family,\n var(--root-secondary-font, 'inherit')\n );\n font-size: var(\n --ix-file-uploader-help-font-size,\n var(--text-small-size, 0.75rem)\n );\n line-height: var(\n --ix-file-uploader-help-line-height,\n var(--text-small-line-height, 16px)\n );\n letter-spacing: var(\n --ix-file-uploader-help-letter-spacing,\n var(--text-small-letter-spacing, 1.25px)\n );\n text-align: center;\n }\n .uploaded-file-list {\n display: flex;\n flex-wrap: wrap;\n gap: 16px;\n list-style: none;\n margin: 0;\n padding: 0;\n }\n .uploaded-file-list--spaced {\n margin-top: 32px;\n }\n .file-input {\n /*\n Per MDN -> https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file\n \"Note: opacity is used to hide the file input instead of visibility: hidden or display: none, because assistive technology interprets the latter two styles to mean the file input isn't interactive.\"\n */\n opacity: 0;\n\n /*\n Adapted styles from https://tailwindcss.com/docs/screen-readers\n */\n border-width: 0;\n clip: rect(0, 0, 0, 0);\n height: 1px;\n margin: -1px;\n overflow: hidden;\n padding: 0;\n white-space: nowrap;\n width: 1px;\n }\n .error .dropzone {\n border-color: var(--md-sys-color-error);\n }\n \n .error .error-text {\n color: var(--md-sys-color-error);\n padding-left: 0.75rem;\n font-size: 0.75rem;\n font-weight: 400;\n display: flex;\n flex-direction: column;\n margin-top: 0.5rem;\n line-height: 0.75rem;\n }\n\n .ix-file-uploader__hint-text{\n font-family: var(--root-primary-font, 'inherit')\n font-weight: 400;\n font-size: 12px;\n line-height: 16px;\n letter-spacing: 0.4px;\n padding-top: 0.5rem;\n color: var(--clr-on-surface, 'inherit');\n }\n\n .ix-file-uploader__template-file {\n display: flex;\n align-items: center;\n }\n .delete-file-confirmation-dialog {\n max-width: 560px;\n font-family: var(--root-secondary-font, 'Red Hat Display');\n font-weight: 700;\n font-size: 20px;\n leading-trim: NONE;\n line-height: 24px;\n letter-spacing: 0.15px;\n}\n`;\n\nexport default IxFileUploaderStyles;\n"]}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "Webcomponent ix-file-uploader following open-wc recommendations",
4
4
  "license": "MIT",
5
5
  "author": "Digital Realty",
6
- "version": "1.3.1-alpha.1",
6
+ "version": "1.3.1",
7
7
  "type": "module",
8
8
  "main": "dist/index.js",
9
9
  "module": "dist/index.js",
@@ -11,6 +11,7 @@
11
11
  ".": "./dist/index.js",
12
12
  "./ix-file-uploader.js": "./dist/ix-file-uploader.js",
13
13
  "./ix-file-uploader.min.js": "./dist/ix-file-uploader.min.js",
14
+ "./FileUploadResult": "./dist/file-upload-result.js",
14
15
  "./IxFileUploader": "./dist/react/IxFileUploader.js",
15
16
  "./DataStorageUnit": "./dist/data-storage-unit.js"
16
17
  },
@@ -20,51 +21,45 @@
20
21
  "scripts": {
21
22
  "analyze": "cem analyze --litelement",
22
23
  "build": "tsc && npm run analyze -- --exclude dist && rollup -c",
23
- "format": "eslint --ext .ts,.html . --fix --ignore-path .gitignore && prettier \"**/*.ts\" --write --ignore-path .gitignore",
24
- "lint": "eslint --ext .ts,.html . --ignore-path .gitignore && prettier \"**/*.ts\" --check --ignore-path .gitignore",
24
+ "format": "eslint --ext .ts,.html . --fix && prettier \"**/*.ts\" --write --ignore-path .gitignore",
25
+ "lint": "eslint --ext .ts,.html . && prettier \"**/*.ts\" --check --ignore-path .gitignore",
25
26
  "prepublish": "tsc && npm run analyze -- --exclude dist",
26
27
  "start": "tsc && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"wds\"",
27
28
  "test": "tsc && wtr --coverage",
28
29
  "test:watch": "tsc && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"wtr --watch\""
29
30
  },
30
31
  "dependencies": {
31
- "@digital-realty/ix-button": "^3.4.1",
32
- "@digital-realty/ix-dialog": "^1.2.1",
33
- "@digital-realty/ix-icon-button": "^1.2.1",
32
+ "@digital-realty/ix-button": "^3.5.1",
33
+ "@digital-realty/ix-dialog": "^1.3.1",
34
+ "@digital-realty/ix-icon-button": "^1.3.1",
34
35
  "@lit-labs/react": "^2.1.0",
35
36
  "@lit/react": "^1.0.2",
36
- "@material/web": "1.2.0",
37
+ "@material/web": "2.4.0",
37
38
  "lit": "^3.2.1",
38
39
  "react": "^18.2.0"
39
40
  },
40
41
  "devDependencies": {
41
42
  "@custom-elements-manifest/analyzer": "^0.4.17",
42
- "@open-wc/eslint-config": "^9.2.1",
43
43
  "@open-wc/testing": "^3.1.6",
44
- "@typescript-eslint/eslint-plugin": "^5.48.0",
45
- "@typescript-eslint/parser": "^5.48.0",
44
+ "@rollup/plugin-terser": "^1.0.0",
45
+ "@typescript-eslint/eslint-plugin": "^8.58.2",
46
+ "@typescript-eslint/parser": "^8.58.2",
46
47
  "@web/dev-server": "^0.4.6",
47
48
  "@web/test-runner": "^0.20.2",
48
- "concurrently": "^9.1.0",
49
- "eslint": "^8.31.0",
49
+ "concurrently": "^9.2.1",
50
+ "eslint": "^9.39.4",
50
51
  "eslint-config-prettier": "^8.3.0",
51
52
  "husky": "^4.3.8",
52
53
  "lint-staged": "^10.5.4",
53
54
  "prettier": "^2.4.1",
54
55
  "rollup": "^4.29.1",
55
- "rollup-plugin-minify-html-literals": "^1.2.6",
56
56
  "rollup-plugin-summary": "^2.0.0",
57
- "rollup-plugin-uglify": "^6.0.4",
58
57
  "tslib": "^2.3.1",
59
58
  "typescript": "^4.5.2"
60
59
  },
61
60
  "customElements": "custom-elements.json",
62
61
  "eslintConfig": {
63
62
  "parser": "@typescript-eslint/parser",
64
- "extends": [
65
- "@open-wc",
66
- "prettier"
67
- ],
68
63
  "plugins": [
69
64
  "@typescript-eslint"
70
65
  ],
@@ -112,5 +107,6 @@
112
107
  "package.json",
113
108
  "README.md",
114
109
  "LICENSE"
115
- ]
110
+ ],
111
+ "gitHead": "da06737d6707fd3d4ef898ba0fa632e7b3ed8019"
116
112
  }