@digital-realty/ix-file-uploader 1.0.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.
Files changed (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +67 -0
  3. package/dist/IxFileChip.d.ts +10 -0
  4. package/dist/IxFileChip.js +48 -0
  5. package/dist/IxFileChip.js.map +1 -0
  6. package/dist/IxFileUploader.d.ts +39 -0
  7. package/dist/IxFileUploader.js +203 -0
  8. package/dist/IxFileUploader.js.map +1 -0
  9. package/dist/data-storage-unit.d.ts +12 -0
  10. package/dist/data-storage-unit.js +15 -0
  11. package/dist/data-storage-unit.js.map +1 -0
  12. package/dist/index.d.ts +3 -0
  13. package/dist/index.js +4 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/internal/file-change-info.d.ts +5 -0
  16. package/dist/internal/file-change-info.js +2 -0
  17. package/dist/internal/file-change-info.js.map +1 -0
  18. package/dist/internal/file-info.d.ts +4 -0
  19. package/dist/internal/file-info.js +2 -0
  20. package/dist/internal/file-info.js.map +1 -0
  21. package/dist/internal/file-upload-result.d.ts +6 -0
  22. package/dist/internal/file-upload-result.js +2 -0
  23. package/dist/internal/file-upload-result.js.map +1 -0
  24. package/dist/internal/files-uploaded-info.d.ts +7 -0
  25. package/dist/internal/files-uploaded-info.js +2 -0
  26. package/dist/internal/files-uploaded-info.js.map +1 -0
  27. package/dist/internal/get-total-bytes.d.ts +11 -0
  28. package/dist/internal/get-total-bytes.js +33 -0
  29. package/dist/internal/get-total-bytes.js.map +1 -0
  30. package/dist/internal/process-files.d.ts +9 -0
  31. package/dist/internal/process-files.js +40 -0
  32. package/dist/internal/process-files.js.map +1 -0
  33. package/dist/internal/sort-files-ascending.d.ts +2 -0
  34. package/dist/internal/sort-files-ascending.js +13 -0
  35. package/dist/internal/sort-files-ascending.js.map +1 -0
  36. package/dist/ix-file-chip.d.ts +1 -0
  37. package/dist/ix-file-chip.js +3 -0
  38. package/dist/ix-file-chip.js.map +1 -0
  39. package/dist/ix-file-uploader.d.ts +1 -0
  40. package/dist/ix-file-uploader.js +3 -0
  41. package/dist/ix-file-uploader.js.map +1 -0
  42. package/dist/react/IxFileUploader.d.ts +2 -0
  43. package/dist/react/IxFileUploader.js +10 -0
  44. package/dist/react/IxFileUploader.js.map +1 -0
  45. package/dist/styles/ix-file-chip-styles.d.ts +2 -0
  46. package/dist/styles/ix-file-chip-styles.js +13 -0
  47. package/dist/styles/ix-file-chip-styles.js.map +1 -0
  48. package/dist/styles/ix-file-uploader-styles.d.ts +2 -0
  49. package/dist/styles/ix-file-uploader-styles.js +74 -0
  50. package/dist/styles/ix-file-uploader-styles.js.map +1 -0
  51. package/package.json +109 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 ix-file-uploader
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # <ix-file-uploader>
2
+
3
+ This webcomponent follows the [open-wc](https://github.com/open-wc/open-wc) recommendation.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm i @digital-realty/ix-file-uploader
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```html
14
+ <script type="module">
15
+ import '@digital-realty/ix-file-uploader/ix-file-uploader.js';
16
+ </script>
17
+
18
+ <ix-file-uploader></ix-file-uploader>
19
+ ```
20
+
21
+ ### In React
22
+
23
+ ```html
24
+ import { IxFileUploaderReact } from '@digital-realty/ix-file-uploader'
25
+ ```
26
+
27
+ ## Linting and formatting
28
+
29
+ To scan the project for linting and formatting errors, run
30
+
31
+ ```bash
32
+ npm run lint
33
+ ```
34
+
35
+ To automatically fix linting and formatting errors, run
36
+
37
+ ```bash
38
+ npm run format
39
+ ```
40
+
41
+ ## Testing with Web Test Runner
42
+
43
+ To execute a single test run:
44
+
45
+ ```bash
46
+ npm run test
47
+ ```
48
+
49
+ To run the tests in interactive watch mode run:
50
+
51
+ ```bash
52
+ npm run test:watch
53
+ ```
54
+
55
+ ## Tooling configs
56
+
57
+ For most of the tools, the configuration is in the `package.json` to reduce the amount of files in your project.
58
+
59
+ If you customize the configuration a lot, you can consider moving them to individual files.
60
+
61
+ ## Local Demo with `web-dev-server`
62
+
63
+ ```bash
64
+ npm start
65
+ ```
66
+
67
+ To run a local development server that serves the basic demo located in `demo/index.html`
@@ -0,0 +1,10 @@
1
+ import '@digital-realty/theme';
2
+ import '@digital-realty/ix-icon-button/ix-icon-button.js';
3
+ import { LitElement, TemplateResult } from 'lit';
4
+ export declare class IxFileChip extends LitElement {
5
+ static readonly styles: import("lit").CSSResult[];
6
+ file?: File;
7
+ private onClick;
8
+ private onDelete;
9
+ protected render(): TemplateResult<1>;
10
+ }
@@ -0,0 +1,48 @@
1
+ import { __decorate } from "tslib";
2
+ import '@digital-realty/theme';
3
+ import '@digital-realty/ix-icon-button/ix-icon-button.js';
4
+ import { html, LitElement } from 'lit';
5
+ import { property } from 'lit/decorators.js';
6
+ import IxFileChipStyles from './styles/ix-file-chip-styles.js';
7
+ export class IxFileChip extends LitElement {
8
+ onClick() {
9
+ const event = new CustomEvent('on-file-click', {
10
+ detail: {
11
+ file: this.file,
12
+ },
13
+ });
14
+ this.dispatchEvent(event);
15
+ }
16
+ onDelete() {
17
+ const event = new CustomEvent('on-file-delete', {
18
+ detail: {
19
+ file: this.file,
20
+ },
21
+ });
22
+ this.dispatchEvent(event);
23
+ }
24
+ render() {
25
+ var _a;
26
+ return html `<li class="file-chip">
27
+ <ix-button
28
+ @click=${this.onClick}
29
+ appearance="text"
30
+ name="file-button"
31
+ type="button"
32
+ >
33
+ ${(_a = this.file) === null || _a === void 0 ? void 0 : _a.name}
34
+ </ix-button>
35
+ <ix-icon-button
36
+ @click=${this.onDelete}
37
+ icon="delete"
38
+ name="delete-button"
39
+ type="button"
40
+ ></ix-icon-button>
41
+ </li>`;
42
+ }
43
+ }
44
+ IxFileChip.styles = [IxFileChipStyles];
45
+ __decorate([
46
+ property({ type: Object })
47
+ ], IxFileChip.prototype, "file", void 0);
48
+ //# sourceMappingURL=IxFileChip.js.map
@@ -0,0 +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;AAE/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;;iBAEE,IAAI,CAAC,OAAO;;;;;UAKnB,MAAA,IAAI,CAAC,IAAI,0CAAE,IAAI;;;iBAGR,IAAI,CAAC,QAAQ;;;;;UAKpB,CAAC;IACT,CAAC;;AAzCe,iBAAM,GAAG,CAAC,gBAAgB,CAAC,CAAC;AAEhB;IAA3B,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;wCAAa","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';\n\nexport class IxFileChip extends LitElement {\n static readonly styles = [IxFileChipStyles];\n\n @property({ type: Object }) file?: File;\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 <ix-button\n @click=${this.onClick}\n appearance=\"text\"\n name=\"file-button\"\n type=\"button\"\n >\n ${this.file?.name}\n </ix-button>\n <ix-icon-button\n @click=${this.onDelete}\n icon=\"delete\"\n name=\"delete-button\"\n type=\"button\"\n ></ix-icon-button>\n </li>`;\n }\n}\n"]}
@@ -0,0 +1,39 @@
1
+ import '@digital-realty/theme';
2
+ import { LitElement, PropertyValues, TemplateResult } from 'lit';
3
+ import { Ref } from 'lit/directives/ref.js';
4
+ import './ix-file-chip.js';
5
+ import DataStorageUnit from './data-storage-unit.js';
6
+ export declare class IxFileUploader extends LitElement {
7
+ static readonly styles: import("lit").CSSResult[];
8
+ /** @nocollapse */
9
+ static readonly formAssociated = true;
10
+ private readonly internals;
11
+ dropzoneRef: Ref<HTMLInputElement>;
12
+ fileRef: Ref<HTMLInputElement>;
13
+ allowMultipleFiles: boolean;
14
+ bodyText: string;
15
+ extensions: string[];
16
+ headerText: string;
17
+ maxFileCount: number;
18
+ maxFileSizeUnit: DataStorageUnit;
19
+ maxFileSizeValue: number;
20
+ name: string;
21
+ files: Array<File>;
22
+ private maxFileSizeInBytes;
23
+ /**
24
+ * The associated form element with which this element's value will submit.
25
+ */
26
+ get form(): HTMLFormElement | null;
27
+ private onDrop;
28
+ private onFileChange;
29
+ private process;
30
+ private updateState;
31
+ private onFilesUploaded;
32
+ private onFileClick;
33
+ private onFileDelete;
34
+ private openFileUploadDialog;
35
+ protected firstUpdated(): void;
36
+ private renderFileList;
37
+ protected updated(_: PropertyValues): void;
38
+ protected render(): TemplateResult<1>;
39
+ }
@@ -0,0 +1,203 @@
1
+ import { __decorate } from "tslib";
2
+ import '@digital-realty/theme';
3
+ import { html, LitElement, nothing } from 'lit';
4
+ import { property, state } from 'lit/decorators.js';
5
+ import { createRef, ref } from 'lit/directives/ref.js';
6
+ import './ix-file-chip.js';
7
+ import DataStorageUnit from './data-storage-unit.js';
8
+ import getTotalBytes from './internal/get-total-bytes.js';
9
+ import { processFiles } from './internal/process-files.js';
10
+ import sortFilesAscending from './internal/sort-files-ascending.js';
11
+ import IxFileUploaderStyles from './styles/ix-file-uploader-styles.js';
12
+ export class IxFileUploader extends LitElement {
13
+ constructor() {
14
+ super(...arguments);
15
+ this.internals = this.attachInternals();
16
+ this.dropzoneRef = createRef();
17
+ this.fileRef = createRef();
18
+ this.allowMultipleFiles = false;
19
+ this.bodyText = '';
20
+ this.extensions = [];
21
+ this.headerText = '';
22
+ this.maxFileCount = 10;
23
+ this.maxFileSizeUnit = DataStorageUnit.MB;
24
+ this.maxFileSizeValue = 10;
25
+ this.name = 'ix-file-uploader';
26
+ this.files = [];
27
+ this.maxFileSizeInBytes = 0;
28
+ }
29
+ /**
30
+ * The associated form element with which this element's value will submit.
31
+ */
32
+ get form() {
33
+ return this.internals.form;
34
+ }
35
+ // called when the user drops files on the dropzone
36
+ onDrop(e) {
37
+ e.preventDefault();
38
+ if (!e.dataTransfer) {
39
+ return; // no files dropped
40
+ }
41
+ const filesToProcess = Array.from(e.dataTransfer.files);
42
+ this.process(filesToProcess);
43
+ }
44
+ // This is called when the user selects files from the file dialog
45
+ onFileChange(e) {
46
+ const fileList = e.currentTarget.files;
47
+ const filesToProcess = Array.from(fileList);
48
+ this.process(filesToProcess);
49
+ // clear the files from the file input; we are tracking state at the component level, not in the file input
50
+ this.fileRef.value.files = new DataTransfer().files;
51
+ }
52
+ // common method for processing files which are dropped or selected from file input dialog
53
+ process(filesToProcess) {
54
+ const results = processFiles({
55
+ currentFiles: this.files,
56
+ extensions: this.extensions,
57
+ filesToProcess,
58
+ maxFileCount: this.allowMultipleFiles ? this.maxFileCount : 1,
59
+ maxFileSizeInBytes: this.maxFileSizeInBytes,
60
+ });
61
+ this.updateState(results);
62
+ this.onFilesUploaded(results);
63
+ }
64
+ updateState(results = []) {
65
+ const filesToUpload = [];
66
+ results.forEach(result => {
67
+ if (result.uploaded) {
68
+ filesToUpload.push(result.file);
69
+ }
70
+ });
71
+ // handle multiple file setting
72
+ if (this.allowMultipleFiles) {
73
+ this.files = [...this.files, ...filesToUpload];
74
+ return;
75
+ }
76
+ // handle single file setting
77
+ if (filesToUpload.length) {
78
+ const file = filesToUpload[0];
79
+ this.files = [file];
80
+ }
81
+ }
82
+ onFilesUploaded(results) {
83
+ const event = new CustomEvent('on-files-uploaded', {
84
+ detail: {
85
+ allFiles: this.files,
86
+ filesUploaded: results.filter(result => result.uploaded),
87
+ filesNotUploaded: results.filter(result => !result.uploaded),
88
+ },
89
+ });
90
+ this.dispatchEvent(event);
91
+ }
92
+ onFileClick(e) {
93
+ const event = new CustomEvent('on-file-clicked', {
94
+ detail: { allFiles: this.files, file: e.detail.file },
95
+ });
96
+ this.dispatchEvent(event);
97
+ }
98
+ onFileDelete(e) {
99
+ var _a;
100
+ const fileNameToDelete = (_a = e.detail.file) === null || _a === void 0 ? void 0 : _a.name;
101
+ this.files = [...this.files].filter(file => file.name !== fileNameToDelete);
102
+ const event = new CustomEvent('on-file-removed', {
103
+ detail: { allFiles: this.files, file: e.detail.file },
104
+ });
105
+ this.dispatchEvent(event);
106
+ }
107
+ openFileUploadDialog() {
108
+ var _a;
109
+ (_a = this.fileRef.value) === null || _a === void 0 ? void 0 : _a.click();
110
+ }
111
+ firstUpdated() {
112
+ // connect the dropzone
113
+ const dropzone = this.dropzoneRef.value;
114
+ if (dropzone) {
115
+ dropzone.addEventListener('dragenter', e => e.preventDefault());
116
+ dropzone.addEventListener('dragover', e => e.preventDefault());
117
+ dropzone.addEventListener('drop', this.onDrop.bind(this));
118
+ }
119
+ // connect the file input
120
+ const fileElem = this.fileRef.value;
121
+ if (fileElem) {
122
+ fileElem.addEventListener('change', this.onFileChange.bind(this));
123
+ }
124
+ // calculate the maxBytes based on props
125
+ // Calculate the max file size in bytes to use for checking if files are too large
126
+ const totalBytesForStorageUnit = getTotalBytes(this.maxFileSizeUnit);
127
+ this.maxFileSizeInBytes = this.maxFileSizeValue * totalBytesForStorageUnit;
128
+ }
129
+ renderFileList(files = []) {
130
+ const sortedFiles = sortFilesAscending(files);
131
+ const chips = sortedFiles.map((file) => html `<ix-file-chip
132
+ .file=${file}
133
+ @on-file-click=${this.onFileClick}
134
+ @on-file-delete=${this.onFileDelete}
135
+ ></ix-file-chip>`);
136
+ return html `
137
+ <ul class="uploaded-file-list">
138
+ ${chips}
139
+ </ul>
140
+ `;
141
+ }
142
+ updated(_) {
143
+ const formData = new FormData();
144
+ this.files.forEach(file => {
145
+ formData.append(`${this.name}[]`, file);
146
+ });
147
+ this.internals.setFormValue(formData);
148
+ }
149
+ render() {
150
+ const accept = this.extensions.map(ext => `.${ext}`).join(', ');
151
+ return html `<div class="ix-file-uploader">
152
+ <div
153
+ class="dropzone"
154
+ @click=${this.openFileUploadDialog}
155
+ @keyup=${this.openFileUploadDialog}
156
+ ${ref(this.dropzoneRef)}
157
+ >
158
+ <div class="ix-file-uploader__label">${this.headerText}</div>
159
+ <div class="ix-file-uploader__help-text">${this.bodyText}</div>
160
+ <input
161
+ accept=${accept}
162
+ class="file-input"
163
+ ?multiple=${this.allowMultipleFiles}
164
+ onchange=${this.onFileChange}
165
+ ${ref(this.fileRef)}
166
+ type="file"
167
+ />
168
+ </div>
169
+ ${this.files.length ? this.renderFileList(this.files) : nothing}
170
+ </div>`;
171
+ }
172
+ }
173
+ IxFileUploader.styles = [IxFileUploaderStyles];
174
+ /** @nocollapse */
175
+ IxFileUploader.formAssociated = true;
176
+ __decorate([
177
+ property({ type: Boolean })
178
+ ], IxFileUploader.prototype, "allowMultipleFiles", void 0);
179
+ __decorate([
180
+ property()
181
+ ], IxFileUploader.prototype, "bodyText", void 0);
182
+ __decorate([
183
+ property({ type: Array })
184
+ ], IxFileUploader.prototype, "extensions", void 0);
185
+ __decorate([
186
+ property()
187
+ ], IxFileUploader.prototype, "headerText", void 0);
188
+ __decorate([
189
+ property({ type: Number })
190
+ ], IxFileUploader.prototype, "maxFileCount", void 0);
191
+ __decorate([
192
+ property()
193
+ ], IxFileUploader.prototype, "maxFileSizeUnit", void 0);
194
+ __decorate([
195
+ property({ type: Number })
196
+ ], IxFileUploader.prototype, "maxFileSizeValue", void 0);
197
+ __decorate([
198
+ property()
199
+ ], IxFileUploader.prototype, "name", void 0);
200
+ __decorate([
201
+ state()
202
+ ], IxFileUploader.prototype, "files", void 0);
203
+ //# sourceMappingURL=IxFileUploader.js.map
@@ -0,0 +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';\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() 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<File> = [];\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 });\n\n this.updateState(results);\n\n this.onFilesUploaded(results);\n }\n\n private updateState(results: Array<FileUploadResult> = []): void {\n const filesToUpload: Array<File> = [];\n\n results.forEach(result => {\n if (result.uploaded) {\n filesToUpload.push(result.file);\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 fileNameToDelete = e.detail.file?.name;\n\n this.files = [...this.files].filter(file => file.name !== fileNameToDelete);\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<File> = []): TemplateResult<1> {\n const sortedFiles = sortFilesAscending(files);\n\n const chips = sortedFiles.map(\n (file: File) => 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"]}
@@ -0,0 +1,12 @@
1
+ declare enum DataStorageUnit {
2
+ B = "B",
3
+ KB = "KB",
4
+ MB = "MB",
5
+ GB = "GB",
6
+ TB = "TB",
7
+ PB = "PB",
8
+ EB = "EB",
9
+ ZB = "ZB",
10
+ YB = "YB"
11
+ }
12
+ export default DataStorageUnit;
@@ -0,0 +1,15 @@
1
+ /* eslint-disable no-shadow */
2
+ var DataStorageUnit;
3
+ (function (DataStorageUnit) {
4
+ DataStorageUnit["B"] = "B";
5
+ DataStorageUnit["KB"] = "KB";
6
+ DataStorageUnit["MB"] = "MB";
7
+ DataStorageUnit["GB"] = "GB";
8
+ DataStorageUnit["TB"] = "TB";
9
+ DataStorageUnit["PB"] = "PB";
10
+ DataStorageUnit["EB"] = "EB";
11
+ DataStorageUnit["ZB"] = "ZB";
12
+ DataStorageUnit["YB"] = "YB";
13
+ })(DataStorageUnit || (DataStorageUnit = {}));
14
+ export default DataStorageUnit;
15
+ //# sourceMappingURL=data-storage-unit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-storage-unit.js","sourceRoot":"","sources":["../src/data-storage-unit.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,IAAK,eAUJ;AAVD,WAAK,eAAe;IAClB,0BAAO,CAAA;IACP,4BAAS,CAAA;IACT,4BAAS,CAAA;IACT,4BAAS,CAAA;IACT,4BAAS,CAAA;IACT,4BAAS,CAAA;IACT,4BAAS,CAAA;IACT,4BAAS,CAAA;IACT,4BAAS,CAAA;AACX,CAAC,EAVI,eAAe,KAAf,eAAe,QAUnB;AAED,eAAe,eAAe,CAAC","sourcesContent":["/* eslint-disable no-shadow */\nenum DataStorageUnit {\n B = 'B', // Bytes\n KB = 'KB', // Kilobytes\n MB = 'MB', // Megabytes\n GB = 'GB', // Gigabytes\n TB = 'TB', // Terabytes\n PB = 'PB', // Petabytes\n EB = 'EB', // Exabytes\n ZB = 'ZB', // Zettabytes\n YB = 'YB', // Yottabytes\n}\n\nexport default DataStorageUnit;\n"]}
@@ -0,0 +1,3 @@
1
+ export { default as DataStorageUnit } from './data-storage-unit.js';
2
+ export { IxFileUploader } from './IxFileUploader.js';
3
+ export { IxFileUploader as IxFileUploaderReact } from './react/IxFileUploader.js';
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { default as DataStorageUnit } from './data-storage-unit.js';
2
+ export { IxFileUploader } from './IxFileUploader.js';
3
+ export { IxFileUploader as IxFileUploaderReact } from './react/IxFileUploader.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,cAAc,IAAI,mBAAmB,EAAE,MAAM,2BAA2B,CAAC","sourcesContent":["export { default as DataStorageUnit } from './data-storage-unit.js';\nexport { IxFileUploader } from './IxFileUploader.js';\nexport { IxFileUploader as IxFileUploaderReact } from './react/IxFileUploader.js';\n"]}
@@ -0,0 +1,5 @@
1
+ import FileInfo from './file-info.js';
2
+ interface FileChangeInfo extends FileInfo {
3
+ allFiles: Array<File>;
4
+ }
5
+ export default FileChangeInfo;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=file-change-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-change-info.js","sourceRoot":"","sources":["../../src/internal/file-change-info.ts"],"names":[],"mappings":"","sourcesContent":["import FileInfo from './file-info.js';\n\ninterface FileChangeInfo extends FileInfo {\n allFiles: Array<File>;\n}\n\nexport default FileChangeInfo;\n"]}
@@ -0,0 +1,4 @@
1
+ interface FileInfo {
2
+ file?: File;
3
+ }
4
+ export default FileInfo;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=file-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-info.js","sourceRoot":"","sources":["../../src/internal/file-info.ts"],"names":[],"mappings":"","sourcesContent":["interface FileInfo {\n file?: File;\n}\n\nexport default FileInfo;\n"]}
@@ -0,0 +1,6 @@
1
+ interface FileUploadResult {
2
+ file: File;
3
+ message: string;
4
+ uploaded: boolean;
5
+ }
6
+ export default FileUploadResult;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=file-upload-result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-upload-result.js","sourceRoot":"","sources":["../../src/internal/file-upload-result.ts"],"names":[],"mappings":"","sourcesContent":["interface FileUploadResult {\n file: File;\n message: string;\n uploaded: boolean;\n}\n\nexport default FileUploadResult;\n"]}
@@ -0,0 +1,7 @@
1
+ import FileUploadResult from './file-upload-result.js';
2
+ interface FilesUploadedInfo {
3
+ allFiles: Array<File>;
4
+ filesUploaded: Array<FileUploadResult>;
5
+ filesNotUploaded: Array<FileUploadResult>;
6
+ }
7
+ export default FilesUploadedInfo;
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=files-uploaded-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"files-uploaded-info.js","sourceRoot":"","sources":["../../src/internal/files-uploaded-info.ts"],"names":[],"mappings":"","sourcesContent":["import FileUploadResult from './file-upload-result.js';\n\ninterface FilesUploadedInfo {\n allFiles: Array<File>;\n filesUploaded: Array<FileUploadResult>;\n filesNotUploaded: Array<FileUploadResult>;\n}\n\nexport default FilesUploadedInfo;\n"]}
@@ -0,0 +1,11 @@
1
+ import DataStorageUnit from '../data-storage-unit.js';
2
+ export declare const KB = 1024;
3
+ export declare const MB: number;
4
+ export declare const GB: number;
5
+ export declare const TB: number;
6
+ export declare const PB: number;
7
+ export declare const EB: number;
8
+ export declare const ZB: number;
9
+ export declare const YB: number;
10
+ declare const getTotalBytes: (unit: DataStorageUnit) => number;
11
+ export default getTotalBytes;
@@ -0,0 +1,33 @@
1
+ import DataStorageUnit from '../data-storage-unit.js';
2
+ export const KB = 1024;
3
+ export const MB = 1024 * KB;
4
+ export const GB = 1024 * MB;
5
+ export const TB = 1024 * GB;
6
+ export const PB = 1024 * TB;
7
+ export const EB = 1024 * PB;
8
+ export const ZB = 1024 * EB;
9
+ export const YB = 1024 * ZB;
10
+ const getTotalBytes = (unit) => {
11
+ switch (unit) {
12
+ case DataStorageUnit.KB:
13
+ return KB;
14
+ case DataStorageUnit.MB:
15
+ return MB;
16
+ case DataStorageUnit.GB:
17
+ return GB;
18
+ case DataStorageUnit.TB:
19
+ return TB;
20
+ case DataStorageUnit.PB:
21
+ return PB;
22
+ case DataStorageUnit.EB:
23
+ return EB;
24
+ case DataStorageUnit.ZB:
25
+ return ZB;
26
+ case DataStorageUnit.YB:
27
+ return YB;
28
+ default:
29
+ return 0;
30
+ }
31
+ };
32
+ export default getTotalBytes;
33
+ //# sourceMappingURL=get-total-bytes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-total-bytes.js","sourceRoot":"","sources":["../../src/internal/get-total-bytes.ts"],"names":[],"mappings":"AAAA,OAAO,eAAe,MAAM,yBAAyB,CAAC;AAEtD,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC;AACvB,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,EAAE,CAAC;AAC5B,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,EAAE,CAAC;AAC5B,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,EAAE,CAAC;AAC5B,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,EAAE,CAAC;AAC5B,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,EAAE,CAAC;AAC5B,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,EAAE,CAAC;AAC5B,MAAM,CAAC,MAAM,EAAE,GAAG,IAAI,GAAG,EAAE,CAAC;AAE5B,MAAM,aAAa,GAAG,CAAC,IAAqB,EAAU,EAAE;IACtD,QAAQ,IAAI,EAAE;QACZ,KAAK,eAAe,CAAC,EAAE;YACrB,OAAO,EAAE,CAAC;QACZ,KAAK,eAAe,CAAC,EAAE;YACrB,OAAO,EAAE,CAAC;QACZ,KAAK,eAAe,CAAC,EAAE;YACrB,OAAO,EAAE,CAAC;QACZ,KAAK,eAAe,CAAC,EAAE;YACrB,OAAO,EAAE,CAAC;QACZ,KAAK,eAAe,CAAC,EAAE;YACrB,OAAO,EAAE,CAAC;QACZ,KAAK,eAAe,CAAC,EAAE;YACrB,OAAO,EAAE,CAAC;QACZ,KAAK,eAAe,CAAC,EAAE;YACrB,OAAO,EAAE,CAAC;QACZ,KAAK,eAAe,CAAC,EAAE;YACrB,OAAO,EAAE,CAAC;QACZ;YACE,OAAO,CAAC,CAAC;KACZ;AACH,CAAC,CAAC;AAEF,eAAe,aAAa,CAAC","sourcesContent":["import DataStorageUnit from '../data-storage-unit.js';\n\nexport const KB = 1024;\nexport const MB = 1024 * KB;\nexport const GB = 1024 * MB;\nexport const TB = 1024 * GB;\nexport const PB = 1024 * TB;\nexport const EB = 1024 * PB;\nexport const ZB = 1024 * EB;\nexport const YB = 1024 * ZB;\n\nconst getTotalBytes = (unit: DataStorageUnit): number => {\n switch (unit) {\n case DataStorageUnit.KB:\n return KB;\n case DataStorageUnit.MB:\n return MB;\n case DataStorageUnit.GB:\n return GB;\n case DataStorageUnit.TB:\n return TB;\n case DataStorageUnit.PB:\n return PB;\n case DataStorageUnit.EB:\n return EB;\n case DataStorageUnit.ZB:\n return ZB;\n case DataStorageUnit.YB:\n return YB;\n default:\n return 0;\n }\n};\n\nexport default getTotalBytes;\n"]}
@@ -0,0 +1,9 @@
1
+ import FileUploadResult from './file-upload-result.js';
2
+ export interface Config {
3
+ currentFiles: Array<File>;
4
+ extensions: Array<string>;
5
+ filesToProcess: Array<File>;
6
+ maxFileCount: number;
7
+ maxFileSizeInBytes: number;
8
+ }
9
+ export declare const processFiles: (config: Config) => Array<FileUploadResult>;
@@ -0,0 +1,40 @@
1
+ export const processFiles = (config) => {
2
+ const { currentFiles, extensions, filesToProcess, maxFileCount, maxFileSizeInBytes, } = config;
3
+ const results = [];
4
+ 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
5
+ for (const file of filesToProcess) {
6
+ // check file extension
7
+ const fileExtension = file.name.split('.').pop() || '';
8
+ const isAllowedExtension = extensions.includes(fileExtension);
9
+ if (!isAllowedExtension) {
10
+ const message = `File extension for "${file.name}" is not allowed`;
11
+ results.push({ file, message, uploaded: false });
12
+ continue;
13
+ }
14
+ // check for max file size
15
+ if (file.size > maxFileSizeInBytes) {
16
+ const message = `File size ${file.size} bytes is too large; maximum allowed size is ${maxFileSizeInBytes} bytes`;
17
+ results.push({ file, message, uploaded: false });
18
+ continue;
19
+ }
20
+ // check for max file count
21
+ const noMoreFilesAllowed = currentFiles.length + filesToUploadCount >= maxFileCount;
22
+ if (noMoreFilesAllowed) {
23
+ const message = `File not uploaded; it would exceed the maximum number of files (${maxFileCount})`;
24
+ results.push({ file, message, uploaded: false });
25
+ continue;
26
+ }
27
+ // check for duplicate file names
28
+ const isDuplicate = currentFiles.some((f) => f.name === file.name);
29
+ if (isDuplicate) {
30
+ const message = `File not uploaded; there is already a file named ${file.name}`;
31
+ results.push({ file, message, uploaded: false });
32
+ continue;
33
+ }
34
+ // The file passes all validation and can be added
35
+ results.push({ file, message: 'File uploaded', uploaded: true });
36
+ filesToUploadCount += 1;
37
+ }
38
+ return results;
39
+ };
40
+ //# sourceMappingURL=process-files.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-files.js","sourceRoot":"","sources":["../../src/internal/process-files.ts"],"names":[],"mappings":"AAUA,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAc,EAA2B,EAAE;IACtE,MAAM,EACJ,YAAY,EACZ,UAAU,EACV,cAAc,EACd,YAAY,EACZ,kBAAkB,GACnB,GAAG,MAAM,CAAC;IAEX,MAAM,OAAO,GAA4B,EAAE,CAAC;IAE5C,IAAI,kBAAkB,GAAG,CAAC,CAAC,CAAC,4HAA4H;IAExJ,KAAK,MAAM,IAAI,IAAI,cAAc,EAAE;QACjC,uBAAuB;QACvB,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC;QACvD,MAAM,kBAAkB,GAAG,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAC9D,IAAI,CAAC,kBAAkB,EAAE;YACvB,MAAM,OAAO,GAAG,uBAAuB,IAAI,CAAC,IAAI,kBAAkB,CAAC;YACnE,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;YACjD,SAAS;SACV;QAED,0BAA0B;QAC1B,IAAI,IAAI,CAAC,IAAI,GAAG,kBAAkB,EAAE;YAClC,MAAM,OAAO,GAAG,aAAa,IAAI,CAAC,IAAI,gDAAgD,kBAAkB,QAAQ,CAAC;YACjH,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;YACjD,SAAS;SACV;QAED,2BAA2B;QAC3B,MAAM,kBAAkB,GACtB,YAAY,CAAC,MAAM,GAAG,kBAAkB,IAAI,YAAY,CAAC;QAC3D,IAAI,kBAAkB,EAAE;YACtB,MAAM,OAAO,GAAG,mEAAmE,YAAY,GAAG,CAAC;YACnG,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;YACjD,SAAS;SACV;QAED,iCAAiC;QACjC,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAO,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC;QACzE,IAAI,WAAW,EAAE;YACf,MAAM,OAAO,GAAG,oDAAoD,IAAI,CAAC,IAAI,EAAE,CAAC;YAChF,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;YACjD,SAAS;SACV;QAED,kDAAkD;QAClD,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,kBAAkB,IAAI,CAAC,CAAC;KACzB;IAED,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC","sourcesContent":["import FileUploadResult from './file-upload-result.js';\n\nexport interface Config {\n currentFiles: Array<File>;\n extensions: Array<string>;\n filesToProcess: Array<File>;\n maxFileCount: number;\n maxFileSizeInBytes: number;\n}\n\nexport const processFiles = (config: Config): Array<FileUploadResult> => {\n const {\n currentFiles,\n extensions,\n filesToProcess,\n maxFileCount,\n maxFileSizeInBytes,\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 (const file of filesToProcess) {\n // check file extension\n const fileExtension = file.name.split('.').pop() || '';\n const isAllowedExtension = extensions.includes(fileExtension);\n if (!isAllowedExtension) {\n const message = `File extension for \"${file.name}\" is not allowed`;\n results.push({ file, message, uploaded: false });\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 });\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 });\n continue;\n }\n\n // check for duplicate file names\n const isDuplicate = currentFiles.some((f: File) => f.name === file.name);\n if (isDuplicate) {\n const message = `File not uploaded; there is already a file named ${file.name}`;\n results.push({ file, message, uploaded: false });\n continue;\n }\n\n // The file passes all validation and can be added\n results.push({ file, message: 'File uploaded', uploaded: true });\n filesToUploadCount += 1;\n }\n\n return results;\n};\n"]}
@@ -0,0 +1,2 @@
1
+ declare const sortFilesAscending: (filesToSort?: Array<File>) => Array<File>;
2
+ export default sortFilesAscending;
@@ -0,0 +1,13 @@
1
+ const sortFilesAscending = (filesToSort = []) => filesToSort.sort((file1, file2) => {
2
+ const file1Name = file1.name.toLocaleLowerCase();
3
+ const file2Name = file2.name.toLocaleLowerCase();
4
+ if (file1Name < file2Name) {
5
+ return -1;
6
+ }
7
+ if (file2Name > file1Name) {
8
+ return 1;
9
+ }
10
+ return 0;
11
+ });
12
+ export default sortFilesAscending;
13
+ //# sourceMappingURL=sort-files-ascending.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sort-files-ascending.js","sourceRoot":"","sources":["../../src/internal/sort-files-ascending.ts"],"names":[],"mappings":"AAAA,MAAM,kBAAkB,GAAG,CAAC,cAA2B,EAAE,EAAe,EAAE,CACxE,WAAW,CAAC,IAAI,CAAC,CAAC,KAAW,EAAE,KAAW,EAAE,EAAE;IAC5C,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;IACjD,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;IAEjD,IAAI,SAAS,GAAG,SAAS,EAAE;QACzB,OAAO,CAAC,CAAC,CAAC;KACX;IACD,IAAI,SAAS,GAAG,SAAS,EAAE;QACzB,OAAO,CAAC,CAAC;KACV;IAED,OAAO,CAAC,CAAC;AACX,CAAC,CAAC,CAAC;AAEL,eAAe,kBAAkB,CAAC","sourcesContent":["const sortFilesAscending = (filesToSort: Array<File> = []): Array<File> =>\n filesToSort.sort((file1: File, file2: File) => {\n const file1Name = file1.name.toLocaleLowerCase();\n const file2Name = file2.name.toLocaleLowerCase();\n\n if (file1Name < file2Name) {\n return -1;\n }\n if (file2Name > file1Name) {\n return 1;\n }\n\n return 0;\n });\n\nexport default sortFilesAscending;\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import { IxFileChip } from './IxFileChip.js';
2
+ customElements.define('ix-file-chip', IxFileChip);
3
+ //# sourceMappingURL=ix-file-chip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ix-file-chip.js","sourceRoot":"","sources":["../src/ix-file-chip.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,cAAc,CAAC,MAAM,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC","sourcesContent":["import { IxFileChip } from './IxFileChip.js';\n\ncustomElements.define('ix-file-chip', IxFileChip);\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import { IxFileUploader } from './IxFileUploader.js';
2
+ customElements.define('ix-file-uploader', IxFileUploader);
3
+ //# sourceMappingURL=ix-file-uploader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ix-file-uploader.js","sourceRoot":"","sources":["../src/ix-file-uploader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,cAAc,CAAC,MAAM,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAC","sourcesContent":["import { IxFileUploader } from './IxFileUploader.js';\n\ncustomElements.define('ix-file-uploader', IxFileUploader);\n"]}
@@ -0,0 +1,2 @@
1
+ import { IxFileUploader as IxFileUploaderLit } from '../IxFileUploader.js';
2
+ export declare const IxFileUploader: import("@lit/react").ReactWebComponent<IxFileUploaderLit, {}>;
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { createComponent } from '@lit/react';
3
+ import { IxFileUploader as IxFileUploaderLit } from '../IxFileUploader.js';
4
+ customElements.define('ix-file-uploader', IxFileUploaderLit);
5
+ export const IxFileUploader = createComponent({
6
+ tagName: 'ix-file-uploader',
7
+ elementClass: IxFileUploaderLit,
8
+ react: React,
9
+ });
10
+ //# sourceMappingURL=IxFileUploader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IxFileUploader.js","sourceRoot":"","sources":["../../src/react/IxFileUploader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,EAAE,cAAc,IAAI,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAE3E,cAAc,CAAC,MAAM,CAAC,kBAAkB,EAAE,iBAAiB,CAAC,CAAC;AAE7D,MAAM,CAAC,MAAM,cAAc,GAAG,eAAe,CAAC;IAC5C,OAAO,EAAE,kBAAkB;IAC3B,YAAY,EAAE,iBAAiB;IAC/B,KAAK,EAAE,KAAK;CACb,CAAC,CAAC","sourcesContent":["import React from 'react';\nimport { createComponent } from '@lit/react';\n\nimport { IxFileUploader as IxFileUploaderLit } from '../IxFileUploader.js';\n\ncustomElements.define('ix-file-uploader', IxFileUploaderLit);\n\nexport const IxFileUploader = createComponent({\n tagName: 'ix-file-uploader',\n elementClass: IxFileUploaderLit,\n react: React,\n});\n"]}
@@ -0,0 +1,2 @@
1
+ declare const IxFileChipStyles: import("lit").CSSResult;
2
+ export default IxFileChipStyles;
@@ -0,0 +1,13 @@
1
+ import { css } from 'lit';
2
+ const IxFileChipStyles = css `
3
+ .file-chip {
4
+ align-items: center;
5
+ background: #f5f7ff;
6
+ cursor: pointer;
7
+ display: flex;
8
+ flex: auto;
9
+ padding: 8px;
10
+ }
11
+ `;
12
+ export default IxFileChipStyles;
13
+ //# sourceMappingURL=ix-file-chip-styles.js.map
@@ -0,0 +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;;;;;;;;;CAS3B,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: 8px;\n }\n`;\n\nexport default IxFileChipStyles;\n"]}
@@ -0,0 +1,2 @@
1
+ declare const IxFileUploaderStyles: import("lit").CSSResult;
2
+ export default IxFileUploaderStyles;
@@ -0,0 +1,74 @@
1
+ import { css } from 'lit';
2
+ const IxFileUploaderStyles = css `
3
+ .ix-file-uploader {
4
+ align-items: center;
5
+ align-self: stretch;
6
+ display: flex;
7
+ flex-direction: column;
8
+ justify-content: center;
9
+ min-width: 320px;
10
+ padding: 16px;
11
+ }
12
+ .dropzone {
13
+ background: var(--Background, #f5f7ff);
14
+ border: 1px dashed var(--Secondary-Main, #378aca);
15
+ border-radius: 3px;
16
+ cursor: pointer;
17
+ display: flex;
18
+ flex-direction: column;
19
+ gap: 4px;
20
+ padding: 16px;
21
+ }
22
+ .ix-file-uploader__label {
23
+ color: var(--Text-Dark, #092241);
24
+ font-family: Red Hat Display;
25
+ font-size: 12px;
26
+ font-style: normal;
27
+ font-weight: 700;
28
+ line-height: 16px;
29
+ letter-spacing: 1.25px;
30
+ text-align: center;
31
+ text-transform: uppercase;
32
+ }
33
+ .ix-file-uploader_help-text {
34
+ color: var(--Text-Dark, #092241);
35
+ font-family: Open Sans;
36
+ font-size: 12px;
37
+ font-style: normal;
38
+ font-weight: 400;
39
+ line-height: 16px;
40
+ letter-spacing: 0.4px;
41
+ text-align: center;
42
+ }
43
+ .uploaded-file-list {
44
+ display: flex;
45
+ flex-wrap: wrap;
46
+ gap: 8px;
47
+ list-style: none;
48
+ margin: 0;
49
+ margin-top: 32px;
50
+ padding: 0;
51
+ }
52
+ .file-input {
53
+ /*
54
+ Per MDN -> https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file
55
+ "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."
56
+ */
57
+ opacity: 0;
58
+
59
+ /*
60
+ Adapted styles from https://tailwindcss.com/docs/screen-readers
61
+ */
62
+ border-width: 0;
63
+ clip: rect(0, 0, 0, 0);
64
+ height: 1px;
65
+ margin: -1px;
66
+ overflow: hidden;
67
+ padding: 0;
68
+ position: absolute;
69
+ white-space: nowrap;
70
+ width: 1px;
71
+ }
72
+ `;
73
+ export default IxFileUploaderStyles;
74
+ //# sourceMappingURL=ix-file-uploader-styles.js.map
@@ -0,0 +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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsE/B,CAAC;AAEF,eAAe,oBAAoB,CAAC","sourcesContent":["import { css } from 'lit';\n\nconst IxFileUploaderStyles = css`\n .ix-file-uploader {\n align-items: center;\n align-self: stretch;\n display: flex;\n flex-direction: column;\n justify-content: center;\n min-width: 320px;\n padding: 16px;\n }\n .dropzone {\n background: var(--Background, #f5f7ff);\n border: 1px dashed var(--Secondary-Main, #378aca);\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(--Text-Dark, #092241);\n font-family: Red Hat Display;\n font-size: 12px;\n font-style: normal;\n font-weight: 700;\n line-height: 16px;\n letter-spacing: 1.25px;\n text-align: center;\n text-transform: uppercase;\n }\n .ix-file-uploader_help-text {\n color: var(--Text-Dark, #092241);\n font-family: Open Sans;\n font-size: 12px;\n font-style: normal;\n font-weight: 400;\n line-height: 16px;\n letter-spacing: 0.4px;\n text-align: center;\n }\n .uploaded-file-list {\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n list-style: none;\n margin: 0;\n margin-top: 32px;\n padding: 0;\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 position: absolute;\n white-space: nowrap;\n width: 1px;\n }\n`;\n\nexport default IxFileUploaderStyles;\n"]}
package/package.json ADDED
@@ -0,0 +1,109 @@
1
+ {
2
+ "name": "@digital-realty/ix-file-uploader",
3
+ "description": "Webcomponent ix-file-uploader following open-wc recommendations",
4
+ "license": "MIT",
5
+ "author": "Digital Realty",
6
+ "version": "1.0.1",
7
+ "type": "module",
8
+ "main": "dist/index.js",
9
+ "module": "dist/index.js",
10
+ "exports": {
11
+ ".": "./dist/index.js",
12
+ "./ix-file-uploader.js": "./dist/ix-file-uploader.js",
13
+ "./FileUploadResult": "./dist/file-upoad-result.js",
14
+ "./IxFileUploader": "./dist/react/IxFileUploader.js"
15
+ },
16
+ "publishConfig": {
17
+ "access": "public"
18
+ },
19
+ "scripts": {
20
+ "analyze": "cem analyze --litelement",
21
+ "build": "tsc && npm run analyze -- --exclude dist",
22
+ "format": "eslint --ext .ts,.html . --fix --ignore-path .gitignore && prettier \"**/*.ts\" --write --ignore-path .gitignore",
23
+ "lint": "eslint --ext .ts,.html . --ignore-path .gitignore && prettier \"**/*.ts\" --check --ignore-path .gitignore",
24
+ "prepublish": "tsc && npm run analyze -- --exclude dist",
25
+ "start": "tsc && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"wds\"",
26
+ "test": "tsc && wtr --coverage",
27
+ "test:watch": "tsc && concurrently -k -r \"tsc --watch --preserveWatchOutput\" \"wtr --watch\""
28
+ },
29
+ "dependencies": {
30
+ "@digital-realty/ix-button": "^3.2.13",
31
+ "@digital-realty/ix-icon-button": "*",
32
+ "@digital-realty/theme": "*",
33
+ "@lit-labs/react": "^2.1.0",
34
+ "@lit/react": "^1.0.2",
35
+ "@material/web": "^1.0.0",
36
+ "lit": "^2.0.2",
37
+ "react": "^18.2.0"
38
+ },
39
+ "devDependencies": {
40
+ "@custom-elements-manifest/analyzer": "^0.4.17",
41
+ "@open-wc/eslint-config": "^9.2.1",
42
+ "@open-wc/testing": "^3.1.6",
43
+ "@typescript-eslint/eslint-plugin": "^5.48.0",
44
+ "@typescript-eslint/parser": "^5.48.0",
45
+ "@web/dev-server": "^0.1.34",
46
+ "@web/test-runner": "^0.14.0",
47
+ "concurrently": "^5.3.0",
48
+ "eslint": "^8.31.0",
49
+ "eslint-config-prettier": "^8.3.0",
50
+ "husky": "^4.3.8",
51
+ "lint-staged": "^10.5.4",
52
+ "prettier": "^2.4.1",
53
+ "tslib": "^2.3.1",
54
+ "typescript": "^4.5.2"
55
+ },
56
+ "customElements": "custom-elements.json",
57
+ "eslintConfig": {
58
+ "parser": "@typescript-eslint/parser",
59
+ "extends": [
60
+ "@open-wc",
61
+ "prettier"
62
+ ],
63
+ "plugins": [
64
+ "@typescript-eslint"
65
+ ],
66
+ "rules": {
67
+ "@typescript-eslint/no-unused-vars": [
68
+ "error",
69
+ {
70
+ "argsIgnorePattern": "^_",
71
+ "varsIgnorePattern": "^_"
72
+ }
73
+ ],
74
+ "import/extensions": [
75
+ "error",
76
+ "always",
77
+ {
78
+ "ignorePackages": true
79
+ }
80
+ ],
81
+ "import/no-unresolved": "off",
82
+ "no-continue": "off",
83
+ "no-unused-vars": "off"
84
+ }
85
+ },
86
+ "prettier": {
87
+ "arrowParens": "avoid",
88
+ "singleQuote": true
89
+ },
90
+ "husky": {
91
+ "hooks": {
92
+ "pre-commit": "lint-staged"
93
+ }
94
+ },
95
+ "lint-staged": {
96
+ "*.ts": [
97
+ "eslint --fix",
98
+ "prettier --write"
99
+ ]
100
+ },
101
+ "files": [
102
+ "/dist",
103
+ "!/dist/test",
104
+ "package.json",
105
+ "README.md",
106
+ "LICENSE"
107
+ ],
108
+ "gitHead": "1b89f4799af29a2ed1c0946843cb4b694a5d8cae"
109
+ }