@dodlhuat/basix 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/css/accordion.scss +31 -22
- package/css/alert.scss +79 -27
- package/css/button.scss +151 -102
- package/css/card.scss +11 -12
- package/css/carousel.scss +123 -87
- package/css/chart.scss +9 -11
- package/css/chat-bubbles.scss +2 -2
- package/css/checkbox.scss +72 -55
- package/css/chips.scss +52 -52
- package/css/code-viewer.scss +73 -98
- package/css/datepicker.scss +20 -0
- package/css/dropdown.scss +151 -137
- package/css/editor.scss +9 -6
- package/css/file-uploader.scss +187 -195
- package/css/flyout-menu.scss +20 -13
- package/css/form.scss +168 -115
- package/css/gallery.scss +62 -63
- package/css/grid.scss +0 -1
- package/css/modal.scss +117 -72
- package/css/placeholder.scss +17 -12
- package/css/properties.scss +6 -0
- package/css/push-menu.scss +70 -23
- package/css/radiobutton.scss +86 -64
- package/css/range-slider.scss +136 -0
- package/css/scrollbar.scss +69 -69
- package/css/spinner.scss +41 -66
- package/css/style.css +4351 -3735
- package/css/style.css.map +1 -1
- package/css/style.scss +2 -1
- package/css/switch.scss +43 -42
- package/css/table.scss +61 -40
- package/css/tabs.scss +12 -7
- package/css/timeline.scss +72 -69
- package/css/timepicker.scss +151 -72
- package/css/toast.scss +49 -48
- package/css/tooltip.scss +112 -122
- package/css/tree.scss +135 -192
- package/css/typography.scss +70 -9
- package/css/virtual-dropdown.scss +201 -142
- package/js/carousel.js +45 -18
- package/js/carousel.ts +217 -173
- package/js/datepicker.js +505 -497
- package/js/datepicker.ts +9 -0
- package/js/editor.js +398 -415
- package/js/file-uploader.js +142 -128
- package/js/file-uploader.ts +364 -350
- package/js/gallery.js +22 -15
- package/js/gallery.ts +17 -12
- package/js/index.js +718 -720
- package/js/index.ts +7 -8
- package/js/push-menu.js +113 -101
- package/js/push-menu.ts +17 -2
- package/js/range-slider.js +26 -0
- package/js/range-slider.ts +33 -0
- package/js/timepicker.js +144 -98
- package/js/timepicker.ts +194 -131
- package/js/tree.js +56 -28
- package/js/tree.ts +239 -218
- package/package.json +1 -1
- package/css/accordion.css +0 -109
- package/css/accordion.css.map +0 -1
- package/css/alert.css +0 -57
- package/css/alert.css.map +0 -1
- package/css/button.css +0 -69
- package/css/button.css.map +0 -1
- package/css/card.css +0 -144
- package/css/card.css.map +0 -1
- package/css/carousel.css +0 -118
- package/css/carousel.css.map +0 -1
- package/css/chart.css +0 -159
- package/css/chart.css.map +0 -1
- package/css/chat-bubbles.css +0 -97
- package/css/chat-bubbles.css.map +0 -1
- package/css/checkbox.css +0 -77
- package/css/checkbox.css.map +0 -1
- package/css/chips.css +0 -72
- package/css/chips.css.map +0 -1
- package/css/code-viewer.css +0 -97
- package/css/code-viewer.css.map +0 -1
- package/css/colors.css +0 -63
- package/css/colors.css.map +0 -1
- package/css/datepicker.css +0 -264
- package/css/datepicker.css.map +0 -1
- package/css/defaults.css +0 -118
- package/css/defaults.css.map +0 -1
- package/css/dropdown.css +0 -146
- package/css/dropdown.css.map +0 -1
- package/css/editor.css +0 -413
- package/css/file-uploader.css +0 -194
- package/css/file-uploader.css.map +0 -1
- package/css/flyout-menu.css +0 -345
- package/css/flyout-menu.css.map +0 -1
- package/css/form-builder.css +0 -9
- package/css/form-builder.css.map +0 -1
- package/css/form-builder.scss +0 -11
- package/css/form.css +0 -130
- package/css/form.css.map +0 -1
- package/css/gallery.css +0 -91
- package/css/gallery.css.map +0 -1
- package/css/grid.css +0 -44
- package/css/grid.css.map +0 -1
- package/css/icons.css +0 -327
- package/css/icons.css.map +0 -1
- package/css/modal.css +0 -97
- package/css/modal.css.map +0 -1
- package/css/parameters.css +0 -1
- package/css/parameters.css.map +0 -1
- package/css/placeholder.css +0 -50
- package/css/placeholder.css.map +0 -1
- package/css/progress.css +0 -51
- package/css/progress.css.map +0 -1
- package/css/properties.css +0 -31
- package/css/properties.css.map +0 -1
- package/css/push-menu.css +0 -145
- package/css/push-menu.css.map +0 -1
- package/css/radiobutton.css +0 -91
- package/css/radiobutton.css.map +0 -1
- package/css/reset.css +0 -46
- package/css/reset.css.map +0 -1
- package/css/scrollbar.css +0 -91
- package/css/scrollbar.css.map +0 -1
- package/css/spinner.css +0 -118
- package/css/spinner.css.map +0 -1
- package/css/switch.css +0 -66
- package/css/switch.css.map +0 -1
- package/css/table.css +0 -201
- package/css/table.css.map +0 -1
- package/css/tabs.css +0 -135
- package/css/tabs.css.map +0 -1
- package/css/timeline.css +0 -69
- package/css/timeline.css.map +0 -1
- package/css/toast.css +0 -98
- package/css/toast.css.map +0 -1
- package/css/tooltip.css +0 -151
- package/css/tooltip.css.map +0 -1
- package/css/tree.css +0 -199
- package/css/tree.css.map +0 -1
- package/css/typography.css +0 -137
- package/css/typography.css.map +0 -1
- package/css/virtual-dropdown.css +0 -149
- package/css/virtual-dropdown.css.map +0 -1
package/js/file-uploader.js
CHANGED
|
@@ -25,7 +25,7 @@ class FileUploader {
|
|
|
25
25
|
const target = e.target;
|
|
26
26
|
if (target.files) {
|
|
27
27
|
this.handleFiles(target.files);
|
|
28
|
-
target.value = '';
|
|
28
|
+
target.value = '';
|
|
29
29
|
}
|
|
30
30
|
};
|
|
31
31
|
this.handleUploadClick = async () => {
|
|
@@ -38,9 +38,10 @@ class FileUploader {
|
|
|
38
38
|
this.uploadBtn.textContent = 'Upload Complete';
|
|
39
39
|
setTimeout(() => {
|
|
40
40
|
this.dispatchUploadCompletedEvent(results);
|
|
41
|
-
this.
|
|
42
|
-
this.
|
|
43
|
-
|
|
41
|
+
this.fileList.innerHTML = '';
|
|
42
|
+
this.files.clear();
|
|
43
|
+
this.updateUploadButton();
|
|
44
|
+
}, 1500);
|
|
44
45
|
};
|
|
45
46
|
const container = typeof elementOrSelector === 'string'
|
|
46
47
|
? document.querySelector(elementOrSelector)
|
|
@@ -68,17 +69,18 @@ class FileUploader {
|
|
|
68
69
|
init() {
|
|
69
70
|
this.setupEventListeners();
|
|
70
71
|
}
|
|
72
|
+
fileKey(file) {
|
|
73
|
+
return `${file.name}-${file.size}-${file.lastModified}`;
|
|
74
|
+
}
|
|
71
75
|
setupEventListeners() {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
this.dropZone.addEventListener(eventName, this.preventDefaults);
|
|
76
|
+
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(event => {
|
|
77
|
+
this.dropZone.addEventListener(event, this.preventDefaults);
|
|
75
78
|
});
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
this.dropZone.addEventListener(eventName, this.handleDragEnter);
|
|
79
|
+
['dragenter', 'dragover'].forEach(event => {
|
|
80
|
+
this.dropZone.addEventListener(event, this.handleDragEnter);
|
|
79
81
|
});
|
|
80
|
-
['dragleave', 'drop'].forEach(
|
|
81
|
-
this.dropZone.addEventListener(
|
|
82
|
+
['dragleave', 'drop'].forEach(event => {
|
|
83
|
+
this.dropZone.addEventListener(event, this.handleDragLeave);
|
|
82
84
|
});
|
|
83
85
|
this.dropZone.addEventListener('drop', this.handleDrop);
|
|
84
86
|
this.dropZone.addEventListener('click', this.handleDropZoneClick);
|
|
@@ -87,159 +89,162 @@ class FileUploader {
|
|
|
87
89
|
}
|
|
88
90
|
handleFiles(fileList) {
|
|
89
91
|
Array.from(fileList).forEach(file => {
|
|
90
|
-
|
|
92
|
+
const key = this.fileKey(file);
|
|
93
|
+
if (this.validateFile(file) && !this.files.has(key)) {
|
|
91
94
|
const element = this.addFileToUI(file);
|
|
92
|
-
this.files.set(
|
|
95
|
+
this.files.set(key, { file, element });
|
|
93
96
|
}
|
|
94
97
|
});
|
|
95
98
|
this.updateUploadButton();
|
|
96
99
|
}
|
|
97
100
|
validateFile(file) {
|
|
98
101
|
if (this.maxFileSize && file.size > this.maxFileSize) {
|
|
99
|
-
|
|
102
|
+
this.container.dispatchEvent(new CustomEvent('file-validation-error', {
|
|
103
|
+
detail: { file, reason: 'size' },
|
|
104
|
+
bubbles: true,
|
|
105
|
+
}));
|
|
100
106
|
return false;
|
|
101
107
|
}
|
|
102
108
|
if (this.allowedTypes && !this.allowedTypes.includes(file.type)) {
|
|
103
|
-
|
|
109
|
+
this.container.dispatchEvent(new CustomEvent('file-validation-error', {
|
|
110
|
+
detail: { file, reason: 'type' },
|
|
111
|
+
bubbles: true,
|
|
112
|
+
}));
|
|
104
113
|
return false;
|
|
105
114
|
}
|
|
106
115
|
return true;
|
|
107
116
|
}
|
|
108
117
|
addFileToUI(file) {
|
|
118
|
+
const key = this.fileKey(file);
|
|
109
119
|
const item = document.createElement('div');
|
|
110
120
|
item.className = 'file-item';
|
|
111
121
|
const escapedFileName = this.escapeHtml(file.name);
|
|
112
|
-
item.innerHTML = `
|
|
113
|
-
<div class="file-item-header">
|
|
114
|
-
<div class="file-info">
|
|
115
|
-
<div class="file-icon">
|
|
116
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
117
|
-
<path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path>
|
|
118
|
-
<polyline points="13 2 13 9 20 9"></polyline>
|
|
119
|
-
</svg>
|
|
120
|
-
</div>
|
|
121
|
-
<div class="file-details">
|
|
122
|
-
<span class="file-name" title="${escapedFileName}">${escapedFileName}</span>
|
|
123
|
-
<span class="file-size">${this.formatSize(file.size)}</span>
|
|
124
|
-
</div>
|
|
125
|
-
</div>
|
|
126
|
-
<button class="remove-btn" type="button" aria-label="Remove file">
|
|
127
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
128
|
-
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
129
|
-
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
130
|
-
</svg>
|
|
131
|
-
</button>
|
|
132
|
-
</div>
|
|
133
|
-
<div class="progress-container"
|
|
134
|
-
<div class="progress-bar"></div>
|
|
135
|
-
</div>
|
|
136
|
-
<div class="status-text"
|
|
122
|
+
item.innerHTML = `
|
|
123
|
+
<div class="file-item-header">
|
|
124
|
+
<div class="file-info">
|
|
125
|
+
<div class="file-icon">
|
|
126
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
127
|
+
<path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path>
|
|
128
|
+
<polyline points="13 2 13 9 20 9"></polyline>
|
|
129
|
+
</svg>
|
|
130
|
+
</div>
|
|
131
|
+
<div class="file-details">
|
|
132
|
+
<span class="file-name" title="${escapedFileName}">${escapedFileName}</span>
|
|
133
|
+
<span class="file-size">${this.formatSize(file.size)}</span>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
<button class="remove-btn" type="button" aria-label="Remove file">
|
|
137
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
138
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
139
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
140
|
+
</svg>
|
|
141
|
+
</button>
|
|
142
|
+
</div>
|
|
143
|
+
<div class="progress-container">
|
|
144
|
+
<div class="progress-bar"></div>
|
|
145
|
+
</div>
|
|
146
|
+
<div class="status-text">Waiting...</div>
|
|
137
147
|
`;
|
|
138
148
|
const removeBtn = item.querySelector('.remove-btn');
|
|
139
149
|
if (removeBtn) {
|
|
140
150
|
removeBtn.addEventListener('click', (e) => {
|
|
141
151
|
e.stopPropagation();
|
|
142
|
-
this.removeFile(
|
|
152
|
+
this.removeFile(key);
|
|
143
153
|
});
|
|
144
154
|
}
|
|
145
155
|
this.fileList.appendChild(item);
|
|
146
156
|
return item;
|
|
147
157
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
progressContainer.style.display = 'block';
|
|
158
|
-
statusText.style.display = 'block';
|
|
159
|
-
removeBtn.style.display = 'none';
|
|
160
|
-
const abortController = new AbortController();
|
|
161
|
-
this.abortControllers.set(file.name, abortController);
|
|
162
|
-
try {
|
|
163
|
-
const formData = new FormData();
|
|
164
|
-
formData.append('file', file);
|
|
165
|
-
const response = await fetch(this.uploadUrl, {
|
|
166
|
-
method: 'POST',
|
|
167
|
-
body: formData,
|
|
168
|
-
signal: abortController.signal,
|
|
169
|
-
});
|
|
170
|
-
// Note: Fetch API doesn't support upload progress natively
|
|
171
|
-
// For progress tracking, you'd need to use XMLHttpRequest or a library
|
|
172
|
-
progressBar.style.width = '100%';
|
|
173
|
-
statusText.textContent = '100%';
|
|
174
|
-
if (response.ok) {
|
|
175
|
-
statusText.textContent = 'Completed';
|
|
176
|
-
statusText.classList.add('success');
|
|
177
|
-
progressBar.style.backgroundColor = 'var(--success-color)';
|
|
178
|
-
return await response.json();
|
|
179
|
-
}
|
|
180
|
-
else {
|
|
181
|
-
throw new Error(`Upload failed: ${response.statusText}`);
|
|
158
|
+
uploadFile(file, element) {
|
|
159
|
+
return new Promise((resolve, reject) => {
|
|
160
|
+
const progressContainer = element.querySelector('.progress-container');
|
|
161
|
+
const progressBar = element.querySelector('.progress-bar');
|
|
162
|
+
const statusText = element.querySelector('.status-text');
|
|
163
|
+
const removeBtn = element.querySelector('.remove-btn');
|
|
164
|
+
if (!progressContainer || !progressBar || !statusText || !removeBtn) {
|
|
165
|
+
reject(new Error('Required UI elements not found'));
|
|
166
|
+
return;
|
|
182
167
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
168
|
+
progressContainer.style.display = 'block';
|
|
169
|
+
statusText.style.display = 'block';
|
|
170
|
+
statusText.textContent = '0%';
|
|
171
|
+
removeBtn.style.display = 'none';
|
|
172
|
+
const xhr = new XMLHttpRequest();
|
|
173
|
+
const key = this.fileKey(file);
|
|
174
|
+
this.abortControllers.set(key, () => xhr.abort());
|
|
175
|
+
xhr.upload.addEventListener('progress', (e) => {
|
|
176
|
+
if (e.lengthComputable) {
|
|
177
|
+
const pct = Math.round((e.loaded / e.total) * 100);
|
|
178
|
+
progressBar.style.width = pct + '%';
|
|
179
|
+
statusText.textContent = pct + '%';
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
xhr.addEventListener('load', () => {
|
|
183
|
+
this.abortControllers.delete(key);
|
|
184
|
+
if (xhr.status >= 200 && xhr.status < 300) {
|
|
185
|
+
progressBar.style.width = '100%';
|
|
186
|
+
progressBar.style.backgroundColor = 'var(--success)';
|
|
187
|
+
statusText.textContent = 'Completed';
|
|
188
|
+
statusText.classList.add('success');
|
|
189
|
+
try {
|
|
190
|
+
resolve(JSON.parse(xhr.responseText));
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
resolve(xhr.responseText);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
progressBar.style.backgroundColor = 'var(--error)';
|
|
198
|
+
statusText.textContent = 'Failed';
|
|
199
|
+
statusText.classList.add('error');
|
|
200
|
+
removeBtn.style.display = 'flex';
|
|
201
|
+
reject(new Error(`Upload failed: ${xhr.statusText}`));
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
xhr.addEventListener('error', () => {
|
|
205
|
+
this.abortControllers.delete(key);
|
|
206
|
+
progressBar.style.backgroundColor = 'var(--error)';
|
|
207
|
+
statusText.textContent = 'Network Error';
|
|
208
|
+
statusText.classList.add('error');
|
|
209
|
+
removeBtn.style.display = 'flex';
|
|
210
|
+
reject(new Error('Network error'));
|
|
211
|
+
});
|
|
212
|
+
xhr.addEventListener('abort', () => {
|
|
213
|
+
this.abortControllers.delete(key);
|
|
186
214
|
statusText.textContent = 'Cancelled';
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
}
|
|
196
|
-
finally {
|
|
197
|
-
this.abortControllers.delete(file.name);
|
|
198
|
-
}
|
|
215
|
+
statusText.classList.add('error');
|
|
216
|
+
removeBtn.style.display = 'flex';
|
|
217
|
+
reject(new Error('Upload aborted'));
|
|
218
|
+
});
|
|
219
|
+
const formData = new FormData();
|
|
220
|
+
formData.append('file', file);
|
|
221
|
+
xhr.open('POST', this.uploadUrl);
|
|
222
|
+
xhr.send(formData);
|
|
223
|
+
});
|
|
199
224
|
}
|
|
200
|
-
removeFile(
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
const fileData = this.files.get(fileName);
|
|
225
|
+
removeFile(key) {
|
|
226
|
+
const abort = this.abortControllers.get(key);
|
|
227
|
+
if (abort)
|
|
228
|
+
abort();
|
|
229
|
+
const fileData = this.files.get(key);
|
|
207
230
|
if (fileData) {
|
|
208
231
|
fileData.element.remove();
|
|
209
|
-
this.files.delete(
|
|
232
|
+
this.files.delete(key);
|
|
210
233
|
this.updateUploadButton();
|
|
211
234
|
}
|
|
212
235
|
}
|
|
213
236
|
updateUploadButton() {
|
|
214
237
|
this.uploadBtn.disabled = this.files.size === 0;
|
|
215
|
-
this.uploadBtn.textContent =
|
|
216
|
-
this.files.size
|
|
217
|
-
|
|
218
|
-
: 'Upload Files';
|
|
238
|
+
this.uploadBtn.textContent = this.files.size > 0
|
|
239
|
+
? `Upload ${this.files.size} File${this.files.size === 1 ? '' : 's'}`
|
|
240
|
+
: 'Upload Files';
|
|
219
241
|
}
|
|
220
242
|
dispatchUploadCompletedEvent(results) {
|
|
221
243
|
const files = Array.from(this.files.values()).map(({ file }) => file);
|
|
222
|
-
|
|
223
|
-
detail: {
|
|
224
|
-
fileCount: this.files.size,
|
|
225
|
-
files,
|
|
226
|
-
results,
|
|
227
|
-
},
|
|
244
|
+
this.container.dispatchEvent(new CustomEvent('upload-completed', {
|
|
245
|
+
detail: { fileCount: this.files.size, files, results },
|
|
228
246
|
bubbles: true,
|
|
229
|
-
});
|
|
230
|
-
this.container.dispatchEvent(event);
|
|
231
|
-
}
|
|
232
|
-
cleanupAfterUpload() {
|
|
233
|
-
const progressContainers = this.fileList.querySelectorAll('.progress-container');
|
|
234
|
-
progressContainers.forEach(el => el.remove());
|
|
235
|
-
const statusTexts = this.fileList.querySelectorAll('.status-text');
|
|
236
|
-
statusTexts.forEach(el => el.remove());
|
|
237
|
-
const removeBtns = this.fileList.querySelectorAll('.remove-btn');
|
|
238
|
-
removeBtns.forEach(btn => (btn.style.display = 'flex'));
|
|
239
|
-
}
|
|
240
|
-
resetUploadState() {
|
|
241
|
-
this.files.clear();
|
|
242
|
-
this.updateUploadButton();
|
|
247
|
+
}));
|
|
243
248
|
}
|
|
244
249
|
formatSize(bytes) {
|
|
245
250
|
if (bytes === 0)
|
|
@@ -255,13 +260,22 @@ class FileUploader {
|
|
|
255
260
|
return div.innerHTML;
|
|
256
261
|
}
|
|
257
262
|
destroy() {
|
|
258
|
-
|
|
259
|
-
this.abortControllers.forEach(controller => controller.abort());
|
|
263
|
+
this.abortControllers.forEach(abort => abort());
|
|
260
264
|
this.abortControllers.clear();
|
|
261
|
-
|
|
265
|
+
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(event => {
|
|
266
|
+
this.dropZone.removeEventListener(event, this.preventDefaults);
|
|
267
|
+
});
|
|
268
|
+
['dragenter', 'dragover'].forEach(event => {
|
|
269
|
+
this.dropZone.removeEventListener(event, this.handleDragEnter);
|
|
270
|
+
});
|
|
271
|
+
['dragleave', 'drop'].forEach(event => {
|
|
272
|
+
this.dropZone.removeEventListener(event, this.handleDragLeave);
|
|
273
|
+
});
|
|
274
|
+
this.dropZone.removeEventListener('drop', this.handleDrop);
|
|
275
|
+
this.dropZone.removeEventListener('click', this.handleDropZoneClick);
|
|
276
|
+
this.fileInput.removeEventListener('change', this.handleFileInputChange);
|
|
277
|
+
this.uploadBtn.removeEventListener('click', this.handleUploadClick);
|
|
262
278
|
this.files.clear();
|
|
263
|
-
// Remove event listeners would require storing bound handlers
|
|
264
|
-
// For now, removing elements will clean up
|
|
265
279
|
this.fileList.innerHTML = '';
|
|
266
280
|
}
|
|
267
281
|
}
|