@digital-realty/ix-file-uploader 1.0.34 → 1.0.35

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.
@@ -5,6 +5,7 @@ import UploaderFile from './internal/uploader-file.js';
5
5
  export declare class IxFileChip extends LitElement {
6
6
  static readonly styles: import("lit").CSSResult[];
7
7
  file?: UploaderFile;
8
+ deletable: boolean;
8
9
  private onClick;
9
10
  private onDelete;
10
11
  protected render(): TemplateResult<1>;
@@ -1,10 +1,14 @@
1
1
  import { __decorate } from "tslib";
2
2
  import '@digital-realty/theme';
3
3
  import '@digital-realty/ix-icon-button/ix-icon-button.js';
4
- import { html, LitElement } from 'lit';
4
+ import { html, LitElement, nothing } from 'lit';
5
5
  import { property } from 'lit/decorators.js';
6
6
  import IxFileChipStyles from './styles/ix-file-chip-styles.js';
7
7
  export class IxFileChip extends LitElement {
8
+ constructor() {
9
+ super(...arguments);
10
+ this.deletable = true;
11
+ }
8
12
  onClick() {
9
13
  const event = new CustomEvent('on-file-click', {
10
14
  detail: {
@@ -14,25 +18,29 @@ export class IxFileChip extends LitElement {
14
18
  this.dispatchEvent(event);
15
19
  }
16
20
  onDelete() {
17
- const event = new CustomEvent('on-file-delete', {
18
- detail: {
19
- file: this.file,
20
- },
21
- });
22
- this.dispatchEvent(event);
21
+ if (this.deletable) {
22
+ const event = new CustomEvent('on-file-delete', {
23
+ detail: {
24
+ file: this.file,
25
+ },
26
+ });
27
+ this.dispatchEvent(event);
28
+ }
23
29
  }
24
30
  render() {
25
31
  var _a;
26
32
  return html `<li class="file-chip">
27
33
  <span @click=${this.onClick}> ${(_a = this.file) === null || _a === void 0 ? void 0 : _a.name} </span>
28
34
 
29
- <ix-icon-button
30
- @click=${this.onDelete}
31
- name="delete-button"
32
- appearance="text"
33
- icon="delete"
34
- >
35
- </ix-icon-button>
35
+ ${this.deletable
36
+ ? html `<ix-icon-button
37
+ @click=${this.onDelete}
38
+ name="delete-button"
39
+ appearance="text"
40
+ icon="delete"
41
+ >
42
+ </ix-icon-button>`
43
+ : nothing}
36
44
  </li>`;
37
45
  }
38
46
  }
@@ -40,4 +48,7 @@ IxFileChip.styles = [IxFileChipStyles];
40
48
  __decorate([
41
49
  property({ type: Object })
42
50
  ], IxFileChip.prototype, "file", void 0);
51
+ __decorate([
52
+ property({ type: Boolean })
53
+ ], IxFileChip.prototype, "deletable", void 0);
43
54
  //# sourceMappingURL=IxFileChip.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"IxFileChip.js","sourceRoot":"","sources":["../src/IxFileChip.ts"],"names":[],"mappings":";AAAA,OAAO,uBAAuB,CAAC;AAC/B,OAAO,kDAAkD,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,UAAU,EAAkB,MAAM,KAAK,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAG7C,OAAO,gBAAgB,MAAM,iCAAiC,CAAC;AAG/D,MAAM,OAAO,UAAW,SAAQ,UAAU;IAKhC,OAAO;QACb,MAAM,KAAK,GAAG,IAAI,WAAW,CAAW,eAAe,EAAE;YACvD,MAAM,EAAE;gBACN,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAEO,QAAQ;QACd,MAAM,KAAK,GAAG,IAAI,WAAW,CAAW,gBAAgB,EAAE;YACxD,MAAM,EAAE;gBACN,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAES,MAAM;;QACd,OAAO,IAAI,CAAA;qBACM,IAAI,CAAC,OAAO,KAAK,MAAA,IAAI,CAAC,IAAI,0CAAE,IAAI;;;iBAGpC,IAAI,CAAC,QAAQ;;;;;;UAMpB,CAAC;IACT,CAAC;;AApCe,iBAAM,GAAG,CAAC,gBAAgB,CAAC,CAAC;AAEhB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;wCAAqB","sourcesContent":["import '@digital-realty/theme';\nimport '@digital-realty/ix-icon-button/ix-icon-button.js';\nimport { html, LitElement, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\n\nimport FileInfo from './internal/file-info.js';\nimport IxFileChipStyles from './styles/ix-file-chip-styles.js';\nimport UploaderFile from './internal/uploader-file.js';\n\nexport class IxFileChip extends LitElement {\n static readonly styles = [IxFileChipStyles];\n\n @property({ type: Object }) file?: UploaderFile;\n\n private onClick(): void {\n const event = new CustomEvent<FileInfo>('on-file-click', {\n detail: {\n file: this.file,\n },\n });\n\n this.dispatchEvent(event);\n }\n\n private onDelete(): void {\n const event = new CustomEvent<FileInfo>('on-file-delete', {\n detail: {\n file: this.file,\n },\n });\n\n this.dispatchEvent(event);\n }\n\n protected render(): TemplateResult<1> {\n return html`<li class=\"file-chip\">\n <span @click=${this.onClick}> ${this.file?.name} </span>\n\n <ix-icon-button\n @click=${this.onDelete}\n name=\"delete-button\"\n appearance=\"text\"\n icon=\"delete\"\n >\n </ix-icon-button>\n </li>`;\n }\n}\n"]}
1
+ {"version":3,"file":"IxFileChip.js","sourceRoot":"","sources":["../src/IxFileChip.ts"],"names":[],"mappings":";AAAA,OAAO,uBAAuB,CAAC;AAC/B,OAAO,kDAAkD,CAAC;AAC1D,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAkB,MAAM,KAAK,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAG7C,OAAO,gBAAgB,MAAM,iCAAiC,CAAC;AAG/D,MAAM,OAAO,UAAW,SAAQ,UAAU;IAA1C;;QAK+B,cAAS,GAAY,IAAI,CAAC;IAuCzD,CAAC;IArCS,OAAO;QACb,MAAM,KAAK,GAAG,IAAI,WAAW,CAAW,eAAe,EAAE;YACvD,MAAM,EAAE;gBACN,IAAI,EAAE,IAAI,CAAC,IAAI;aAChB;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC;IAEO,QAAQ;QACd,IAAI,IAAI,CAAC,SAAS,EAAE;YAClB,MAAM,KAAK,GAAG,IAAI,WAAW,CAAW,gBAAgB,EAAE;gBACxD,MAAM,EAAE;oBACN,IAAI,EAAE,IAAI,CAAC,IAAI;iBAChB;aACF,CAAC,CAAC;YAEH,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;SAC3B;IACH,CAAC;IAES,MAAM;;QACd,OAAO,IAAI,CAAA;qBACM,IAAI,CAAC,OAAO,KAAK,MAAA,IAAI,CAAC,IAAI,0CAAE,IAAI;;QAE7C,IAAI,CAAC,SAAS;YACd,CAAC,CAAC,IAAI,CAAA;qBACO,IAAI,CAAC,QAAQ;;;;;4BAKN;YACpB,CAAC,CAAC,OAAO;UACP,CAAC;IACT,CAAC;;AA1Ce,iBAAM,GAAG,CAAC,gBAAgB,CAAC,CAAC;AAEhB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;wCAAqB;AAEnB;IAA5B,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;6CAA2B","sourcesContent":["import '@digital-realty/theme';\nimport '@digital-realty/ix-icon-button/ix-icon-button.js';\nimport { html, LitElement, nothing, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\n\nimport FileInfo from './internal/file-info.js';\nimport IxFileChipStyles from './styles/ix-file-chip-styles.js';\nimport UploaderFile from './internal/uploader-file.js';\n\nexport class IxFileChip extends LitElement {\n static readonly styles = [IxFileChipStyles];\n\n @property({ type: Object }) file?: UploaderFile;\n\n @property({ type: Boolean }) deletable: boolean = true;\n\n private onClick(): void {\n const event = new CustomEvent<FileInfo>('on-file-click', {\n detail: {\n file: this.file,\n },\n });\n\n this.dispatchEvent(event);\n }\n\n private onDelete(): void {\n if (this.deletable) {\n const event = new CustomEvent<FileInfo>('on-file-delete', {\n detail: {\n file: this.file,\n },\n });\n\n this.dispatchEvent(event);\n }\n }\n\n protected render(): TemplateResult<1> {\n return html`<li class=\"file-chip\">\n <span @click=${this.onClick}> ${this.file?.name} </span>\n\n ${this.deletable\n ? html`<ix-icon-button\n @click=${this.onDelete}\n name=\"delete-button\"\n appearance=\"text\"\n icon=\"delete\"\n >\n </ix-icon-button>`\n : nothing}\n </li>`;\n }\n}\n"]}
@@ -14,6 +14,8 @@ export declare class IxFileUploader extends LitElement {
14
14
  allowMultipleFiles: boolean;
15
15
  allowDuplicates: boolean;
16
16
  bodyText: string;
17
+ defaultFiles: Array<UploaderFile>;
18
+ allowDeleteDefaultFiles: boolean;
17
19
  extensions: string[];
18
20
  headerText: string;
19
21
  maxFileCount: number;
@@ -35,6 +37,7 @@ export declare class IxFileUploader extends LitElement {
35
37
  private onFileDelete;
36
38
  private openFileUploadDialog;
37
39
  protected firstUpdated(): void;
40
+ isFileDeletable(file: UploaderFile): boolean;
38
41
  private renderFileList;
39
42
  protected updated(_: PropertyValues): void;
40
43
  protected render(): TemplateResult<1>;
@@ -18,6 +18,8 @@ export class IxFileUploader extends LitElement {
18
18
  this.allowMultipleFiles = false;
19
19
  this.allowDuplicates = false;
20
20
  this.bodyText = '';
21
+ this.defaultFiles = [];
22
+ this.allowDeleteDefaultFiles = false;
21
23
  this.extensions = [];
22
24
  this.headerText = '';
23
25
  this.maxFileCount = 10;
@@ -111,6 +113,7 @@ export class IxFileUploader extends LitElement {
111
113
  (_a = this.fileRef.value) === null || _a === void 0 ? void 0 : _a.click();
112
114
  }
113
115
  firstUpdated() {
116
+ this.files = [...this.defaultFiles];
114
117
  // connect the dropzone
115
118
  const dropzone = this.dropzoneRef.value;
116
119
  if (dropzone) {
@@ -128,10 +131,17 @@ export class IxFileUploader extends LitElement {
128
131
  const totalBytesForStorageUnit = getTotalBytes(this.maxFileSizeUnit);
129
132
  this.maxFileSizeInBytes = this.maxFileSizeValue * totalBytesForStorageUnit;
130
133
  }
134
+ isFileDeletable(file) {
135
+ if (this.defaultFiles.some(x => x.name === file.name)) {
136
+ return this.allowDeleteDefaultFiles;
137
+ }
138
+ return true;
139
+ }
131
140
  renderFileList(files = []) {
132
141
  const sortedFiles = sortFilesAscending(files);
133
142
  const chips = sortedFiles.map((file) => html `<ix-file-chip
134
143
  .file=${file}
144
+ .deletable=${this.isFileDeletable(file)}
135
145
  @on-file-click=${this.onFileClick}
136
146
  @on-file-delete=${this.onFileDelete}
137
147
  ></ix-file-chip>`);
@@ -184,6 +194,12 @@ __decorate([
184
194
  __decorate([
185
195
  property()
186
196
  ], IxFileUploader.prototype, "bodyText", void 0);
197
+ __decorate([
198
+ property({ type: Array })
199
+ ], IxFileUploader.prototype, "defaultFiles", void 0);
200
+ __decorate([
201
+ property({ type: Boolean })
202
+ ], IxFileUploader.prototype, "allowDeleteDefaultFiles", void 0);
187
203
  __decorate([
188
204
  property({ type: Array })
189
205
  ], IxFileUploader.prototype, "extensions", void 0);
@@ -1 +1 @@
1
- {"version":3,"file":"IxFileUploader.js","sourceRoot":"","sources":["../src/IxFileUploader.ts"],"names":[],"mappings":"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","sourcesContent":["import '@digital-realty/theme';\nimport { html, LitElement, nothing, PropertyValues, TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { createRef, ref, Ref } from 'lit/directives/ref.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';\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 }) allowMultipleFiles: boolean = false;\n\n @property({ type: Boolean }) allowDuplicates: boolean = false;\n\n @property() bodyText: string = '';\n\n @property({ type: Array }) extensions: string[] = [];\n\n @property() headerText: 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 @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 // 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.allowMultipleFiles ? this.maxFileCount : 1,\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 const fileIdToDelete = e.detail.file?.id;\n\n this.files = [...this.files].filter(file => file.id !== fileIdToDelete);\n\n const event = new CustomEvent<FileChangeInfo>('on-file-removed', {\n detail: { allFiles: this.files, file: e.detail.file },\n });\n\n this.dispatchEvent(event);\n }\n\n private openFileUploadDialog(): void {\n this.fileRef.value?.click();\n }\n\n protected override firstUpdated(): void {\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 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 @on-file-click=${this.onFileClick}\n @on-file-delete=${this.onFileDelete}\n ></ix-file-chip>`\n );\n\n return html`\n <ul class=\"uploaded-file-list\">\n ${chips}\n </ul>\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 protected render(): TemplateResult<1> {\n const accept = this.extensions.map(ext => `.${ext}`).join(', ');\n\n return html`<div class=\"ix-file-uploader\">\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=${this.onFileChange}\n ${ref(this.fileRef)}\n type=\"file\"\n />\n </div>\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 '@digital-realty/theme';\nimport { html, LitElement, nothing, PropertyValues, TemplateResult } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { createRef, ref, Ref } from 'lit/directives/ref.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';\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 }) allowMultipleFiles: boolean = false;\n\n @property({ type: Boolean }) allowDuplicates: boolean = false;\n\n @property() bodyText: string = '';\n\n @property({ type: Array }) defaultFiles: Array<UploaderFile> = [];\n\n @property({ type: Boolean }) allowDeleteDefaultFiles: boolean = false;\n\n @property({ type: Array }) extensions: string[] = [];\n\n @property() headerText: 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 @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 // 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.allowMultipleFiles ? this.maxFileCount : 1,\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 const fileIdToDelete = e.detail.file?.id;\n\n this.files = [...this.files].filter(file => file.id !== fileIdToDelete);\n\n const event = new CustomEvent<FileChangeInfo>('on-file-removed', {\n detail: { allFiles: this.files, file: e.detail.file },\n });\n\n this.dispatchEvent(event);\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 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 return html`\n <ul class=\"uploaded-file-list\">\n ${chips}\n </ul>\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 protected render(): TemplateResult<1> {\n const accept = this.extensions.map(ext => `.${ext}`).join(', ');\n\n return html`<div class=\"ix-file-uploader\">\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=${this.onFileChange}\n ${ref(this.fileRef)}\n type=\"file\"\n />\n </div>\n ${this.files.length ? this.renderFileList(this.files) : nothing}\n </div>`;\n }\n}\n"]}
@@ -1,3 +1,15 @@
1
+ // key is source file extension and browser infered content type
2
+ const mimeTypeMap = {
3
+ 'csv-application/vnd.ms-excel': 'text/csv',
4
+ };
5
+ function mapBrowserContentTypes(fileExtension, file) {
6
+ if (mimeTypeMap[`${fileExtension}-${file.type}`]) {
7
+ return new File([file], file.name, {
8
+ type: mimeTypeMap[`${fileExtension}-${file.type}`],
9
+ });
10
+ }
11
+ return file;
12
+ }
1
13
  export const processFiles = (config) => {
2
14
  const { currentFiles, extensions, filesToProcess, maxFileCount, maxFileSizeInBytes, allowDuplicates, } = config;
3
15
  const results = [];
@@ -50,14 +62,4 @@ export const processFiles = (config) => {
50
62
  }
51
63
  return results;
52
64
  };
53
- function mapBrowserContentTypes(fileExtension, file) {
54
- if (mimeTypeMap[`${fileExtension}-${file.type}`]) {
55
- return new File([file], file.name, { type: mimeTypeMap[`${fileExtension}-${file.type}`] });
56
- }
57
- return file;
58
- }
59
- // key is source file extension and browser infered content type
60
- const mimeTypeMap = {
61
- "csv-application/vnd.ms-excel": "text/csv"
62
- };
63
65
  //# sourceMappingURL=process-files.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"process-files.js","sourceRoot":"","sources":["../../src/internal/process-files.ts"],"names":[],"mappings":"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","sourcesContent":["import FileUploadResult from './file-upload-result.js';\nimport UploaderFile from './uploader-file.js';\n\nexport interface Config {\n currentFiles: Array<UploaderFile>;\n extensions: Array<string>;\n filesToProcess: Array<File>;\n maxFileCount: number;\n maxFileSizeInBytes: number;\n allowDuplicates: boolean;\n}\n\nexport const processFiles = (config: Config): Array<FileUploadResult> => {\n const {\n currentFiles,\n extensions,\n filesToProcess,\n maxFileCount,\n maxFileSizeInBytes,\n allowDuplicates,\n } = config;\n\n const results: Array<FileUploadResult> = [];\n\n let filesToUploadCount = 0; // counter for how many files we add in the \"for\" loop below; used to know when we reach the maximum number of files allowed\n\n for (let file of filesToProcess) {\n // check file extension\n const fileExtension = file.name.split('.').pop() || '';\n const isAllowedExtension = extensions.includes(fileExtension);\n file = mapBrowserContentTypes(fileExtension, file);\n if (!isAllowedExtension) {\n const message = `File extension for \"${file.name}\" is not allowed`;\n results.push({ file, message, uploaded: false, id: crypto.randomUUID() });\n continue;\n }\n\n // check for max file size\n if (file.size > maxFileSizeInBytes) {\n const message = `File size ${file.size} bytes is too large; maximum allowed size is ${maxFileSizeInBytes} bytes`;\n results.push({ file, message, uploaded: false, id: crypto.randomUUID() });\n continue;\n }\n\n // check for max file count\n const noMoreFilesAllowed =\n currentFiles.length + filesToUploadCount >= maxFileCount;\n if (noMoreFilesAllowed) {\n const message = `File not uploaded; it would exceed the maximum number of files (${maxFileCount})`;\n results.push({ file, message, uploaded: false, id: crypto.randomUUID() });\n continue;\n }\n\n // check for duplicate file names\n if (!allowDuplicates) {\n const isDuplicate = currentFiles.some(\n (f: UploaderFile) => f.name === file.name\n );\n if (isDuplicate) {\n const message = `File not uploaded; there is already a file named ${file.name}`;\n results.push({\n file,\n message,\n uploaded: false,\n id: crypto.randomUUID(),\n });\n continue;\n }\n }\n\n // The file passes all validation and can be added\n results.push({\n file,\n message: 'File uploaded',\n uploaded: true,\n id: crypto.randomUUID(),\n });\n filesToUploadCount += 1;\n }\n\n return results;\n};\nfunction mapBrowserContentTypes(fileExtension: string, file: File) {\n if(mimeTypeMap[`${fileExtension}-${file.type}`]) {\n return new File([file], file.name, { type: mimeTypeMap[`${fileExtension}-${file.type}`]});\n }\n return file;\n}\n\n// key is source file extension and browser infered content type\nconst mimeTypeMap:{[key:string]: string} = {\n \"csv-application/vnd.ms-excel\": \"text/csv\"\n}"]}
1
+ {"version":3,"file":"process-files.js","sourceRoot":"","sources":["../../src/internal/process-files.ts"],"names":[],"mappings":"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","sourcesContent":["import FileUploadResult from './file-upload-result.js';\nimport UploaderFile from './uploader-file.js';\n\nexport interface Config {\n currentFiles: Array<UploaderFile>;\n extensions: Array<string>;\n filesToProcess: Array<File>;\n maxFileCount: number;\n maxFileSizeInBytes: number;\n allowDuplicates: boolean;\n}\n\n// key is source file extension and browser infered content type\nconst mimeTypeMap: { [key: string]: string } = {\n 'csv-application/vnd.ms-excel': 'text/csv',\n};\n\nfunction mapBrowserContentTypes(fileExtension: string, file: File) {\n if (mimeTypeMap[`${fileExtension}-${file.type}`]) {\n return new File([file], file.name, {\n type: mimeTypeMap[`${fileExtension}-${file.type}`],\n });\n }\n return file;\n}\n\nexport const processFiles = (config: Config): Array<FileUploadResult> => {\n const {\n currentFiles,\n extensions,\n filesToProcess,\n maxFileCount,\n maxFileSizeInBytes,\n allowDuplicates,\n } = config;\n\n const results: Array<FileUploadResult> = [];\n\n let filesToUploadCount = 0; // counter for how many files we add in the \"for\" loop below; used to know when we reach the maximum number of files allowed\n\n for (let file of filesToProcess) {\n // check file extension\n const fileExtension = file.name.split('.').pop() || '';\n const isAllowedExtension = extensions.includes(fileExtension);\n file = mapBrowserContentTypes(fileExtension, file);\n if (!isAllowedExtension) {\n const message = `File extension for \"${file.name}\" is not allowed`;\n results.push({ file, message, uploaded: false, id: crypto.randomUUID() });\n continue;\n }\n\n // check for max file size\n if (file.size > maxFileSizeInBytes) {\n const message = `File size ${file.size} bytes is too large; maximum allowed size is ${maxFileSizeInBytes} bytes`;\n results.push({ file, message, uploaded: false, id: crypto.randomUUID() });\n continue;\n }\n\n // check for max file count\n const noMoreFilesAllowed =\n currentFiles.length + filesToUploadCount >= maxFileCount;\n if (noMoreFilesAllowed) {\n const message = `File not uploaded; it would exceed the maximum number of files (${maxFileCount})`;\n results.push({ file, message, uploaded: false, id: crypto.randomUUID() });\n continue;\n }\n\n // check for duplicate file names\n if (!allowDuplicates) {\n const isDuplicate = currentFiles.some(\n (f: UploaderFile) => f.name === file.name\n );\n if (isDuplicate) {\n const message = `File not uploaded; there is already a file named ${file.name}`;\n results.push({\n file,\n message,\n uploaded: false,\n id: crypto.randomUUID(),\n });\n continue;\n }\n }\n\n // The file passes all validation and can be added\n results.push({\n file,\n message: 'File uploaded',\n uploaded: true,\n id: crypto.randomUUID(),\n });\n filesToUploadCount += 1;\n }\n\n return results;\n};\n"]}
@@ -1 +1 @@
1
- import{__decorate}from"tslib";import"@digital-realty/theme";import{css,LitElement,html,nothing}from"lit";import{property,state}from"lit/decorators.js";import{createRef,ref}from"lit/directives/ref.js";import"@digital-realty/ix-icon-button/ix-icon-button.js";const IxFileChipStyles=css`.file-chip{align-items:center;background:#f5f7ff;cursor:pointer;display:flex;flex:auto;padding:4px 8px}.file-chip span{margin-right:10px}`;class IxFileChip extends LitElement{onClick(){var e=new CustomEvent("on-file-click",{detail:{file:this.file}});this.dispatchEvent(e)}onDelete(){var 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><ix-icon-button @click="${this.onDelete}" name="delete-button" appearance="text" icon="delete"></ix-icon-button></li>`}}IxFileChip.styles=[IxFileChipStyles],__decorate([property({type:Object})],IxFileChip.prototype,"file",void 0),customElements.define("ix-file-chip",IxFileChip),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"}(DataStorageUnit=DataStorageUnit||{});var DataStorageUnit,DataStorageUnit$1=DataStorageUnit;const 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}},processFiles=e=>{var{currentFiles:t,extensions:l,filesToProcess:e,maxFileCount:a,maxFileSizeInBytes:o,allowDuplicates:s}=e,r=[];let n=0;for(let i of e){var p=i.name.split(".").pop()||"",d=l.includes(p);if(i=mapBrowserContentTypes(p,i),d)if(i.size>o){p=`File size ${i.size} bytes is too large; maximum allowed size is ${o} bytes`;r.push({file:i,message:p,uploaded:!1,id:crypto.randomUUID()})}else if(t.length+n>=a)r.push({file:i,message:`File not uploaded; it would exceed the maximum number of files (${a})`,uploaded:!1,id:crypto.randomUUID()});else{if(!s)if(t.some(e=>e.name===i.name)){d="File not uploaded; there is already a file named "+i.name;r.push({file:i,message:d,uploaded:!1,id:crypto.randomUUID()});continue}r.push({file:i,message:"File uploaded",uploaded:!0,id:crypto.randomUUID()}),n+=1}else{p=`File extension for "${i.name}" is not allowed`;r.push({file:i,message:p,uploaded:!1,id:crypto.randomUUID()})}}return r};function mapBrowserContentTypes(e,i){return mimeTypeMap[e+"-"+i.type]?new File([i],i.name,{type:mimeTypeMap[e+"-"+i.type]}):i}const mimeTypeMap={"csv-application/vnd.ms-excel":"text/csv"},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}.dropzone{background:var(--Background,#f5f7ff);border:1px dashed var(--Secondary-Main,#378aca);border-radius:3px;cursor:pointer;display:flex;flex-direction:column;gap:4px;padding:16px}.ix-file-uploader__label{color:var(--Text-Dark,#092241);font-family:Red Hat Display;font-size:.75rem;font-style:normal;font-weight:700;line-height:16px;letter-spacing:1.25px;text-align:center;text-transform:uppercase}.ix-file-uploader__help-text{color:var(--Text-Dark,#092241);font-family:Red Hat Display;font-size:.75rem;text-align:center}.uploaded-file-list{display:flex;flex-wrap:wrap;gap:16px;list-style:none;margin:0;margin-top:32px;padding:0}.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}`;class IxFileUploader extends LitElement{constructor(){super(...arguments),this.internals=this.attachInternals(),this.dropzoneRef=createRef(),this.fileRef=createRef(),this.allowMultipleFiles=!1,this.allowDuplicates=!1,this.bodyText="",this.extensions=[],this.headerText="",this.maxFileCount=10,this.maxFileSizeUnit=DataStorageUnit$1.MB,this.maxFileSizeValue=10,this.name="ix-file-uploader",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}process(e){e=processFiles({currentFiles:this.files,extensions:this.extensions,filesToProcess:e,maxFileCount:this.allowMultipleFiles?this.maxFileCount:1,maxFileSizeInBytes:this.maxFileSizeInBytes,allowDuplicates:this.allowDuplicates});this.updateState(e),this.onFilesUploaded(e)}updateState(e=[]){const 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){const i=null==(t=e.detail.file)?void 0:t.id;this.files=[...this.files].filter(e=>e.id!==i);var t=new CustomEvent("on-file-removed",{detail:{allFiles:this.files,file:e.detail.file}});this.dispatchEvent(t)}openFileUploadDialog(){var e;null!=(e=this.fileRef.value)&&e.click()}firstUpdated(){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}renderFileList(e=[]){e=sortFilesAscending(e).map(e=>html`<ix-file-chip .file="${e}" @on-file-click="${this.onFileClick}" @on-file-delete="${this.onFileDelete}"></ix-file-chip>`);return html`<ul class="uploaded-file-list">${e}</ul>`}updated(e){const i=new FormData;this.files.forEach(e=>{i.append(this.name+"[]",e)}),this.internals.setFormValue(i)}render(){var e=this.extensions.map(e=>"."+e).join(", ");return html`<div class="ix-file-uploader"><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="${this.onFileChange}" ${ref(this.fileRef)} type="file"></div>${this.files.length?this.renderFileList(this.files):nothing}</div>`}}IxFileUploader.styles=[IxFileUploaderStyles],IxFileUploader.formAssociated=!0,__decorate([property({type:Boolean})],IxFileUploader.prototype,"allowMultipleFiles",void 0),__decorate([property({type:Boolean})],IxFileUploader.prototype,"allowDuplicates",void 0),__decorate([property()],IxFileUploader.prototype,"bodyText",void 0),__decorate([property({type:Array})],IxFileUploader.prototype,"extensions",void 0),__decorate([property()],IxFileUploader.prototype,"headerText",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([state()],IxFileUploader.prototype,"files",void 0),customElements.define("ix-file-uploader",IxFileUploader);
1
+ import{__decorate}from"tslib";import"@digital-realty/theme";import{css,LitElement,html,nothing}from"lit";import{property,state}from"lit/decorators.js";import{createRef,ref}from"lit/directives/ref.js";import"@digital-realty/ix-icon-button/ix-icon-button.js";const 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}`;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" appearance="text" icon="delete"></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),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"}(DataStorageUnit=DataStorageUnit||{});var DataStorageUnit,DataStorageUnit$1=DataStorageUnit;const 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,t){return mimeTypeMap[e+"-"+t.type]?new File([t],t.name,{type:mimeTypeMap[e+"-"+t.type]}):t}const processFiles=e=>{var{currentFiles:i,extensions:l,filesToProcess:e,maxFileCount:a,maxFileSizeInBytes:o,allowDuplicates:s}=e,r=[];let n=0;for(let t of e){var p=t.name.split(".").pop()||"",d=l.includes(p);if(t=mapBrowserContentTypes(p,t),d)if(t.size>o){p=`File size ${t.size} bytes is too large; maximum allowed size is ${o} bytes`;r.push({file:t,message:p,uploaded:!1,id:crypto.randomUUID()})}else if(i.length+n>=a)r.push({file:t,message:`File not uploaded; it would exceed the maximum number of files (${a})`,uploaded:!1,id:crypto.randomUUID()});else{if(!s)if(i.some(e=>e.name===t.name)){d="File not uploaded; there is already a file named "+t.name;r.push({file:t,message:d,uploaded:!1,id:crypto.randomUUID()});continue}r.push({file:t,message:"File uploaded",uploaded:!0,id:crypto.randomUUID()}),n+=1}else{p=`File extension for "${t.name}" is not allowed`;r.push({file:t,message:p,uploaded:!1,id:crypto.randomUUID()})}}return r},sortFilesAscending=(e=[])=>e.sort((e,t)=>{e=e.name.toLocaleLowerCase(),t=t.name.toLocaleLowerCase();return e<t?-1:0}),IxFileUploaderStyles=css`.ix-file-uploader{display:flex;flex-direction:column;justify-content:center;min-width:320px}.dropzone{background:var(--Background,#f5f7ff);border:1px dashed var(--Secondary-Main,#378aca);border-radius:3px;cursor:pointer;display:flex;flex-direction:column;gap:4px;padding:16px}.ix-file-uploader__label{color:var(--Text-Dark,#092241);font-family:Red Hat Display;font-size:.75rem;font-style:normal;font-weight:700;line-height:16px;letter-spacing:1.25px;text-align:center;text-transform:uppercase}.ix-file-uploader__help-text{color:var(--Text-Dark,#092241);font-family:Red Hat Display;font-size:.75rem;text-align:center}.uploaded-file-list{display:flex;flex-wrap:wrap;gap:16px;list-style:none;margin:0;margin-top:32px;padding:0}.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}`;class IxFileUploader extends LitElement{constructor(){super(...arguments),this.internals=this.attachInternals(),this.dropzoneRef=createRef(),this.fileRef=createRef(),this.allowMultipleFiles=!1,this.allowDuplicates=!1,this.bodyText="",this.defaultFiles=[],this.allowDeleteDefaultFiles=!1,this.extensions=[],this.headerText="",this.maxFileCount=10,this.maxFileSizeUnit=DataStorageUnit$1.MB,this.maxFileSizeValue=10,this.name="ix-file-uploader",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}process(e){e=processFiles({currentFiles:this.files,extensions:this.extensions,filesToProcess:e,maxFileCount:this.allowMultipleFiles?this.maxFileCount:1,maxFileSizeInBytes:this.maxFileSizeInBytes,allowDuplicates:this.allowDuplicates});this.updateState(e),this.onFilesUploaded(e)}updateState(e=[]){const t=[];e.forEach(e=>{e.uploaded&&t.push(Object.assign(e.file,{id:e.id}))}),this.allowMultipleFiles?this.files=[...this.files,...t]:t.length&&(e=t[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){const t=null==(i=e.detail.file)?void 0:i.id;this.files=[...this.files].filter(e=>e.id!==t);var i=new CustomEvent("on-file-removed",{detail:{allFiles:this.files,file:e.detail.file}});this.dispatchEvent(i)}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}isFileDeletable(t){return!this.defaultFiles.some(e=>e.name===t.name)||this.allowDeleteDefaultFiles}renderFileList(e=[]){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>`);return html`<ul class="uploaded-file-list">${e}</ul>`}updated(e){const t=new FormData;this.files.forEach(e=>{t.append(this.name+"[]",e)}),this.internals.setFormValue(t)}render(){var e=this.extensions.map(e=>"."+e).join(", ");return html`<div class="ix-file-uploader"><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="${this.onFileChange}" ${ref(this.fileRef)} type="file"></div>${this.files.length?this.renderFileList(this.files):nothing}</div>`}}IxFileUploader.styles=[IxFileUploaderStyles],IxFileUploader.formAssociated=!0,__decorate([property({type:Boolean})],IxFileUploader.prototype,"allowMultipleFiles",void 0),__decorate([property({type:Boolean})],IxFileUploader.prototype,"allowDuplicates",void 0),__decorate([property()],IxFileUploader.prototype,"bodyText",void 0),__decorate([property({type:Array})],IxFileUploader.prototype,"defaultFiles",void 0),__decorate([property({type:Boolean})],IxFileUploader.prototype,"allowDeleteDefaultFiles",void 0),__decorate([property({type:Array})],IxFileUploader.prototype,"extensions",void 0),__decorate([property()],IxFileUploader.prototype,"headerText",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([state()],IxFileUploader.prototype,"files",void 0),customElements.define("ix-file-uploader",IxFileUploader);
@@ -7,6 +7,7 @@ const IxFileChipStyles = css `
7
7
  display: flex;
8
8
  flex: auto;
9
9
  padding: 4px 8px;
10
+ height: 40px;
10
11
  }
11
12
 
12
13
  .file-chip span {
@@ -1 +1 @@
1
- {"version":3,"file":"ix-file-chip-styles.js","sourceRoot":"","sources":["../../src/styles/ix-file-chip-styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,gBAAgB,GAAG,GAAG,CAAA;;;;;;;;;;;;;CAa3B,CAAC;AAEF,eAAe,gBAAgB,CAAC","sourcesContent":["import { css } from 'lit';\n\nconst IxFileChipStyles = css`\n .file-chip {\n align-items: center;\n background: #f5f7ff;\n cursor: pointer;\n display: flex;\n flex: auto;\n padding: 4px 8px;\n }\n\n .file-chip span {\n margin-right: 10px;\n }\n`;\n\nexport default IxFileChipStyles;\n"]}
1
+ {"version":3,"file":"ix-file-chip-styles.js","sourceRoot":"","sources":["../../src/styles/ix-file-chip-styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,gBAAgB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;CAc3B,CAAC;AAEF,eAAe,gBAAgB,CAAC","sourcesContent":["import { css } from 'lit';\n\nconst IxFileChipStyles = css`\n .file-chip {\n align-items: center;\n background: #f5f7ff;\n cursor: pointer;\n display: flex;\n flex: auto;\n padding: 4px 8px;\n height: 40px;\n }\n\n .file-chip span {\n margin-right: 10px;\n }\n`;\n\nexport default IxFileChipStyles;\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.0.34",
6
+ "version": "1.0.35",
7
7
  "type": "module",
8
8
  "main": "dist/index.js",
9
9
  "module": "dist/index.js",
@@ -113,5 +113,5 @@
113
113
  "README.md",
114
114
  "LICENSE"
115
115
  ],
116
- "gitHead": "d1ae79d9416a388c31319d8b88bcafd610542736"
116
+ "gitHead": "91b300a7f807ed30cb83b70ee85645469223f52e"
117
117
  }