secure-ui-components 0.1.0-beta.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.
- package/LICENSE +21 -0
- package/README.md +310 -0
- package/dist/components/secure-datetime/secure-datetime.css +263 -0
- package/dist/components/secure-datetime/secure-datetime.d.ts +124 -0
- package/dist/components/secure-datetime/secure-datetime.d.ts.map +1 -0
- package/dist/components/secure-datetime/secure-datetime.js +610 -0
- package/dist/components/secure-datetime/secure-datetime.js.map +1 -0
- package/dist/components/secure-file-upload/secure-file-upload.css +334 -0
- package/dist/components/secure-file-upload/secure-file-upload.d.ts +150 -0
- package/dist/components/secure-file-upload/secure-file-upload.d.ts.map +1 -0
- package/dist/components/secure-file-upload/secure-file-upload.js +911 -0
- package/dist/components/secure-file-upload/secure-file-upload.js.map +1 -0
- package/dist/components/secure-form/secure-form.css +62 -0
- package/dist/components/secure-form/secure-form.d.ts +128 -0
- package/dist/components/secure-form/secure-form.d.ts.map +1 -0
- package/dist/components/secure-form/secure-form.js +697 -0
- package/dist/components/secure-form/secure-form.js.map +1 -0
- package/dist/components/secure-input/secure-input.css +168 -0
- package/dist/components/secure-input/secure-input.d.ts +114 -0
- package/dist/components/secure-input/secure-input.d.ts.map +1 -0
- package/dist/components/secure-input/secure-input.js +785 -0
- package/dist/components/secure-input/secure-input.js.map +1 -0
- package/dist/components/secure-select/secure-select.css +195 -0
- package/dist/components/secure-select/secure-select.d.ts +149 -0
- package/dist/components/secure-select/secure-select.d.ts.map +1 -0
- package/dist/components/secure-select/secure-select.js +634 -0
- package/dist/components/secure-select/secure-select.js.map +1 -0
- package/dist/components/secure-submit-button/secure-submit-button.css +135 -0
- package/dist/components/secure-submit-button/secure-submit-button.d.ts +61 -0
- package/dist/components/secure-submit-button/secure-submit-button.d.ts.map +1 -0
- package/dist/components/secure-submit-button/secure-submit-button.js +399 -0
- package/dist/components/secure-submit-button/secure-submit-button.js.map +1 -0
- package/dist/components/secure-table/secure-table.css +341 -0
- package/dist/components/secure-table/secure-table.d.ts +64 -0
- package/dist/components/secure-table/secure-table.d.ts.map +1 -0
- package/dist/components/secure-table/secure-table.js +567 -0
- package/dist/components/secure-table/secure-table.js.map +1 -0
- package/dist/components/secure-textarea/secure-textarea.css +153 -0
- package/dist/components/secure-textarea/secure-textarea.d.ts +111 -0
- package/dist/components/secure-textarea/secure-textarea.d.ts.map +1 -0
- package/dist/components/secure-textarea/secure-textarea.js +477 -0
- package/dist/components/secure-textarea/secure-textarea.js.map +1 -0
- package/dist/core/base-component.d.ts +134 -0
- package/dist/core/base-component.d.ts.map +1 -0
- package/dist/core/base-component.js +303 -0
- package/dist/core/base-component.js.map +1 -0
- package/dist/core/base.css +37 -0
- package/dist/core/security-config.d.ts +89 -0
- package/dist/core/security-config.d.ts.map +1 -0
- package/dist/core/security-config.js +273 -0
- package/dist/core/security-config.js.map +1 -0
- package/dist/core/types.d.ts +212 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +7 -0
- package/dist/core/types.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/package.json +89 -0
- package/dist/styles/tokens.css +257 -0
- package/package.json +118 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secure File Upload Component Styles
|
|
3
|
+
* Bulma-inspired design using design tokens for full customizability
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/* Container */
|
|
7
|
+
.file-upload-container {
|
|
8
|
+
position: relative;
|
|
9
|
+
margin-bottom: var(--secure-ui-form-gap);
|
|
10
|
+
font-family: var(--secure-ui-font-family-base);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/* Label */
|
|
14
|
+
label {
|
|
15
|
+
display: block;
|
|
16
|
+
margin-bottom: var(--secure-ui-form-label-margin-bottom);
|
|
17
|
+
font-size: var(--secure-ui-label-font-size);
|
|
18
|
+
font-weight: var(--secure-ui-label-font-weight);
|
|
19
|
+
color: var(--secure-ui-label-color);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.label-suffix {
|
|
23
|
+
font-weight: var(--secure-ui-font-weight-normal);
|
|
24
|
+
color: var(--secure-ui-color-text-secondary);
|
|
25
|
+
font-size: var(--secure-ui-font-size-xs);
|
|
26
|
+
margin-left: var(--secure-ui-space-1);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.security-badge {
|
|
30
|
+
display: inline-block;
|
|
31
|
+
padding: var(--secure-ui-badge-padding);
|
|
32
|
+
margin-left: var(--secure-ui-space-2);
|
|
33
|
+
font-size: var(--secure-ui-badge-font-size);
|
|
34
|
+
font-weight: var(--secure-ui-font-weight-semibold);
|
|
35
|
+
border-radius: var(--secure-ui-badge-border-radius);
|
|
36
|
+
text-transform: uppercase;
|
|
37
|
+
background-color: var(--secure-ui-color-bg-tertiary);
|
|
38
|
+
color: var(--secure-ui-color-text-secondary);
|
|
39
|
+
border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* Bulma-style file wrapper */
|
|
43
|
+
.drop-zone {
|
|
44
|
+
position: relative;
|
|
45
|
+
display: inline-flex;
|
|
46
|
+
align-items: stretch;
|
|
47
|
+
justify-content: flex-start;
|
|
48
|
+
border-radius: var(--secure-ui-input-border-radius);
|
|
49
|
+
cursor: pointer;
|
|
50
|
+
width: 100%;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.drop-zone.drag-over {
|
|
54
|
+
transform: scale(1.01);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.drop-zone.error .file-cta {
|
|
58
|
+
border-color: var(--secure-ui-color-error);
|
|
59
|
+
color: var(--secure-ui-color-error);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/* Hidden native file input — positioned over the entire drop zone */
|
|
63
|
+
.file-input {
|
|
64
|
+
position: absolute;
|
|
65
|
+
top: 0;
|
|
66
|
+
left: 0;
|
|
67
|
+
width: 100%;
|
|
68
|
+
height: 100%;
|
|
69
|
+
opacity: 0;
|
|
70
|
+
cursor: pointer;
|
|
71
|
+
z-index: 1;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* Suppress the native (now invisible) focus ring on the input itself */
|
|
75
|
+
.file-input:focus {
|
|
76
|
+
outline: none;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Show a visible focus ring on the CTA when the hidden input has keyboard focus
|
|
80
|
+
(WCAG 2.4.7, 2.4.11) — also triggers on programmatic focus */
|
|
81
|
+
.drop-zone:focus-within .file-cta {
|
|
82
|
+
outline: 2px solid var(--secure-ui-color-border-focus);
|
|
83
|
+
outline-offset: 2px;
|
|
84
|
+
box-shadow: var(--secure-ui-shadow-focus);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@media (forced-colors: active) {
|
|
88
|
+
.drop-zone:focus-within .file-cta {
|
|
89
|
+
outline: 2px solid ButtonText;
|
|
90
|
+
box-shadow: none;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.drop-zone-content {
|
|
95
|
+
display: flex;
|
|
96
|
+
align-items: stretch;
|
|
97
|
+
width: 100%;
|
|
98
|
+
pointer-events: none;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* Call-to-action button (Choose file) */
|
|
102
|
+
.file-cta {
|
|
103
|
+
display: flex;
|
|
104
|
+
align-items: center;
|
|
105
|
+
justify-content: center;
|
|
106
|
+
padding: var(--secure-ui-input-padding-y) var(--secure-ui-input-padding-x);
|
|
107
|
+
background-color: var(--secure-ui-color-bg-secondary);
|
|
108
|
+
border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color);
|
|
109
|
+
border-radius: var(--secure-ui-input-border-radius);
|
|
110
|
+
color: var(--secure-ui-color-text-primary);
|
|
111
|
+
font-size: var(--secure-ui-input-font-size);
|
|
112
|
+
font-weight: var(--secure-ui-font-weight-medium);
|
|
113
|
+
white-space: nowrap;
|
|
114
|
+
transition: all var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.drop-zone:hover .file-cta {
|
|
118
|
+
background-color: var(--secure-ui-color-bg-tertiary);
|
|
119
|
+
border-color: var(--secure-ui-input-border-color-hover);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.drop-zone:active .file-cta {
|
|
123
|
+
background-color: var(--secure-ui-color-bg-tertiary);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.drop-zone.drag-over .file-cta {
|
|
127
|
+
background-color: var(--secure-ui-color-primary-light, rgba(102, 126, 234, 0.1));
|
|
128
|
+
border-color: var(--secure-ui-color-primary);
|
|
129
|
+
color: var(--secure-ui-color-primary);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* Upload icon */
|
|
133
|
+
.drop-icon {
|
|
134
|
+
font-size: var(--secure-ui-font-size-base);
|
|
135
|
+
margin-right: var(--secure-ui-space-2);
|
|
136
|
+
display: flex;
|
|
137
|
+
align-items: center;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/* Button text */
|
|
141
|
+
.drop-text {
|
|
142
|
+
font-size: var(--secure-ui-font-size-base);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/* File name display area */
|
|
146
|
+
.file-name-display {
|
|
147
|
+
display: flex;
|
|
148
|
+
align-items: center;
|
|
149
|
+
flex: 1;
|
|
150
|
+
padding: var(--secure-ui-input-padding-y) var(--secure-ui-input-padding-x);
|
|
151
|
+
border: var(--secure-ui-input-border-width) solid var(--secure-ui-input-border-color);
|
|
152
|
+
border-left: none;
|
|
153
|
+
border-radius: 0 var(--secure-ui-input-border-radius) var(--secure-ui-input-border-radius) 0;
|
|
154
|
+
background-color: var(--secure-ui-input-bg);
|
|
155
|
+
color: var(--secure-ui-input-placeholder-color);
|
|
156
|
+
font-size: var(--secure-ui-input-font-size);
|
|
157
|
+
max-width: 100%;
|
|
158
|
+
overflow: hidden;
|
|
159
|
+
text-overflow: ellipsis;
|
|
160
|
+
white-space: nowrap;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.file-name-display.has-file {
|
|
164
|
+
color: var(--secure-ui-input-text-color);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/* When has file name, adjust CTA border radius */
|
|
168
|
+
.drop-zone-content.has-name .file-cta {
|
|
169
|
+
border-radius: var(--secure-ui-input-border-radius) 0 0 var(--secure-ui-input-border-radius);
|
|
170
|
+
border-right: none;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/* Accepted types hint */
|
|
174
|
+
.drop-hint {
|
|
175
|
+
display: block;
|
|
176
|
+
text-align: right;
|
|
177
|
+
margin-top: var(--secure-ui-space-1);
|
|
178
|
+
font-size: var(--secure-ui-font-size-xs);
|
|
179
|
+
color: var(--secure-ui-color-text-secondary);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/* Preview container for selected files */
|
|
183
|
+
.preview-container {
|
|
184
|
+
margin-top: var(--secure-ui-space-3);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.file-preview {
|
|
188
|
+
display: flex;
|
|
189
|
+
align-items: center;
|
|
190
|
+
padding: var(--secure-ui-space-3);
|
|
191
|
+
background-color: var(--secure-ui-color-bg-secondary);
|
|
192
|
+
border: var(--secure-ui-border-width-thin) solid var(--secure-ui-color-border);
|
|
193
|
+
border-radius: var(--secure-ui-input-border-radius);
|
|
194
|
+
margin-bottom: var(--secure-ui-space-2);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.file-name {
|
|
198
|
+
flex: 1;
|
|
199
|
+
font-size: var(--secure-ui-font-size-sm);
|
|
200
|
+
color: var(--secure-ui-color-text-primary);
|
|
201
|
+
overflow: hidden;
|
|
202
|
+
text-overflow: ellipsis;
|
|
203
|
+
white-space: nowrap;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.file-size {
|
|
207
|
+
font-size: var(--secure-ui-font-size-xs);
|
|
208
|
+
color: var(--secure-ui-color-text-secondary);
|
|
209
|
+
margin-left: var(--secure-ui-space-3);
|
|
210
|
+
white-space: nowrap;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.remove-file {
|
|
214
|
+
background: none;
|
|
215
|
+
border: none;
|
|
216
|
+
color: var(--secure-ui-color-error);
|
|
217
|
+
font-size: var(--secure-ui-font-size-base);
|
|
218
|
+
cursor: pointer;
|
|
219
|
+
padding: var(--secure-ui-space-1) var(--secure-ui-space-2);
|
|
220
|
+
margin-left: var(--secure-ui-space-2);
|
|
221
|
+
border-radius: var(--secure-ui-border-radius-sm);
|
|
222
|
+
transition: background-color var(--secure-ui-transition-base) var(--secure-ui-transition-ease-in-out);
|
|
223
|
+
pointer-events: auto;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
.remove-file:hover {
|
|
227
|
+
background-color: var(--secure-ui-color-error-light, rgba(239, 68, 68, 0.1));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/* Error container */
|
|
231
|
+
.error-container {
|
|
232
|
+
position: absolute;
|
|
233
|
+
bottom: -1rem;
|
|
234
|
+
left: 0;
|
|
235
|
+
display: var(--error-display);
|
|
236
|
+
margin-top: var(--secure-ui-form-error-margin-top);
|
|
237
|
+
padding: var(--secure-ui-space-2) var(--secure-ui-space-3);
|
|
238
|
+
background-color: var(--secure-ui-color-error-light, rgba(239, 68, 68, 0.1));
|
|
239
|
+
border-radius: var(--secure-ui-border-radius-sm);
|
|
240
|
+
color: var(--secure-ui-color-error);
|
|
241
|
+
font-size: var(--secure-ui-error-font-size);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/* .error-container:not(.hidden) {
|
|
245
|
+
display: block;
|
|
246
|
+
} */
|
|
247
|
+
|
|
248
|
+
.error-container.hidden {
|
|
249
|
+
max-height: 0;
|
|
250
|
+
opacity: 0;
|
|
251
|
+
transform: translateY(-4px);
|
|
252
|
+
margin-top: 0;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/* Security Tier Styles */
|
|
256
|
+
/* :host([security-tier="public"]) .file-cta {
|
|
257
|
+
border-color: var(--secure-ui-tier-public);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
:host([security-tier="public"]) .file-name-display {
|
|
261
|
+
border-color: var(--secure-ui-tier-public);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
:host([security-tier="authenticated"]) .file-cta {
|
|
265
|
+
border-color: var(--secure-ui-tier-authenticated);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
:host([security-tier="authenticated"]) .file-name-display {
|
|
269
|
+
border-color: var(--secure-ui-tier-authenticated);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
:host([security-tier="authenticated"]) .security-badge {
|
|
273
|
+
background-color: rgba(33, 150, 243, 0.1);
|
|
274
|
+
color: var(--secure-ui-tier-authenticated);
|
|
275
|
+
border-color: var(--secure-ui-tier-authenticated);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
:host([security-tier="sensitive"]) .file-cta {
|
|
279
|
+
border-color: var(--secure-ui-tier-sensitive);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
:host([security-tier="sensitive"]) .file-name-display {
|
|
283
|
+
border-color: var(--secure-ui-tier-sensitive);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
:host([security-tier="sensitive"]) .security-badge {
|
|
287
|
+
background-color: rgba(255, 152, 0, 0.1);
|
|
288
|
+
color: var(--secure-ui-tier-sensitive);
|
|
289
|
+
border-color: var(--secure-ui-tier-sensitive);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
:host([security-tier="critical"]) .file-cta {
|
|
293
|
+
border-color: var(--secure-ui-tier-critical);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
:host([security-tier="critical"]) .file-name-display {
|
|
297
|
+
border-color: var(--secure-ui-tier-critical);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
:host([security-tier="critical"]) .security-badge {
|
|
301
|
+
background-color: rgba(244, 67, 54, 0.1);
|
|
302
|
+
color: var(--secure-ui-tier-critical);
|
|
303
|
+
border-color: var(--secure-ui-tier-critical);
|
|
304
|
+
} */
|
|
305
|
+
|
|
306
|
+
/* Disabled state */
|
|
307
|
+
.drop-zone.disabled {
|
|
308
|
+
opacity: var(--secure-ui-input-disabled-opacity);
|
|
309
|
+
cursor: not-allowed;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.drop-zone.disabled .file-cta {
|
|
313
|
+
background-color: var(--secure-ui-input-disabled-bg);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/* Scanning state */
|
|
317
|
+
.drop-zone.scanning {
|
|
318
|
+
pointer-events: none;
|
|
319
|
+
opacity: 0.7;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.drop-zone.scanning .file-cta {
|
|
323
|
+
border-color: var(--secure-ui-color-primary);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
.drop-zone.scanning .file-name-display {
|
|
327
|
+
color: var(--secure-ui-color-primary);
|
|
328
|
+
animation: scanning-pulse 1.2s ease-in-out infinite;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
@keyframes scanning-pulse {
|
|
332
|
+
0%, 100% { opacity: 0.5; }
|
|
333
|
+
50% { opacity: 1; }
|
|
334
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Secure File Upload Component
|
|
3
|
+
*
|
|
4
|
+
* A security-first file upload component that implements progressive enhancement,
|
|
5
|
+
* file type validation, size limits, scan hook integration, and audit logging.
|
|
6
|
+
*
|
|
7
|
+
* Progressive Enhancement Strategy:
|
|
8
|
+
* 1. Without JavaScript: Falls back to native HTML5 file input
|
|
9
|
+
* 2. With JavaScript: Enhances with validation, preview, drag-drop, security checks
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* <secure-file-upload
|
|
13
|
+
* security-tier="sensitive"
|
|
14
|
+
* name="document"
|
|
15
|
+
* label="Upload Document"
|
|
16
|
+
* accept=".pdf,.doc,.docx"
|
|
17
|
+
* max-size="5242880"
|
|
18
|
+
* required
|
|
19
|
+
* ></secure-file-upload>
|
|
20
|
+
*
|
|
21
|
+
* Security Features:
|
|
22
|
+
* - File type validation (MIME type and extension)
|
|
23
|
+
* - File size limits based on security tier
|
|
24
|
+
* - Scan hook integration (e.g. server-side malware scanning)
|
|
25
|
+
* - Content validation before upload
|
|
26
|
+
* - Rate limiting on uploads
|
|
27
|
+
* - Comprehensive audit logging
|
|
28
|
+
* - Drag-and-drop with validation
|
|
29
|
+
* - Preview for safe file types
|
|
30
|
+
*
|
|
31
|
+
* @module secure-file-upload
|
|
32
|
+
* @license MIT
|
|
33
|
+
*/
|
|
34
|
+
import { SecureBaseComponent } from '../../core/base-component.js';
|
|
35
|
+
/**
|
|
36
|
+
* Result returned by a scan hook function.
|
|
37
|
+
*/
|
|
38
|
+
export interface ScanHookResult {
|
|
39
|
+
/** Whether the file passed the scan */
|
|
40
|
+
valid: boolean;
|
|
41
|
+
/** Reason for rejection (when valid is false) */
|
|
42
|
+
reason?: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A function that scans a file and returns a pass/fail result.
|
|
46
|
+
* Typically sends the file to a server-side scanning endpoint.
|
|
47
|
+
*/
|
|
48
|
+
export type ScanHookFn = (file: File) => Promise<ScanHookResult>;
|
|
49
|
+
/**
|
|
50
|
+
* Secure File Upload Web Component
|
|
51
|
+
*
|
|
52
|
+
* Provides a security-hardened file upload field with progressive enhancement.
|
|
53
|
+
* The component works as a standard file input without JavaScript and
|
|
54
|
+
* enhances with security features when JavaScript is available.
|
|
55
|
+
*
|
|
56
|
+
* @extends SecureBaseComponent
|
|
57
|
+
*/
|
|
58
|
+
export declare class SecureFileUpload extends SecureBaseComponent {
|
|
59
|
+
#private;
|
|
60
|
+
/**
|
|
61
|
+
* Observed attributes for this component
|
|
62
|
+
*
|
|
63
|
+
* @static
|
|
64
|
+
*/
|
|
65
|
+
static get observedAttributes(): string[];
|
|
66
|
+
/**
|
|
67
|
+
* Constructor
|
|
68
|
+
*/
|
|
69
|
+
constructor();
|
|
70
|
+
/**
|
|
71
|
+
* Render the file upload component
|
|
72
|
+
*
|
|
73
|
+
* Security Note: We use a native <input type="file"> element wrapped in our
|
|
74
|
+
* web component to ensure progressive enhancement. The native input works
|
|
75
|
+
* without JavaScript, and we enhance it with security features when JS is available.
|
|
76
|
+
*
|
|
77
|
+
* @protected
|
|
78
|
+
*/
|
|
79
|
+
protected render(): DocumentFragment | HTMLElement | null;
|
|
80
|
+
/**
|
|
81
|
+
* Handle attribute changes
|
|
82
|
+
*
|
|
83
|
+
* @protected
|
|
84
|
+
*/
|
|
85
|
+
protected handleAttributeChange(name: string, _oldValue: string | null, newValue: string | null): void;
|
|
86
|
+
/**
|
|
87
|
+
* Get selected files
|
|
88
|
+
*
|
|
89
|
+
* @public
|
|
90
|
+
*/
|
|
91
|
+
get files(): FileList | null;
|
|
92
|
+
/**
|
|
93
|
+
* Get the input name
|
|
94
|
+
*
|
|
95
|
+
* @public
|
|
96
|
+
*/
|
|
97
|
+
get name(): string;
|
|
98
|
+
/**
|
|
99
|
+
* Check if the upload is valid
|
|
100
|
+
*
|
|
101
|
+
* @public
|
|
102
|
+
*/
|
|
103
|
+
get valid(): boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Clear selected files
|
|
106
|
+
*
|
|
107
|
+
* @public
|
|
108
|
+
*/
|
|
109
|
+
clear(): void;
|
|
110
|
+
/**
|
|
111
|
+
* Register a scan hook function for server-side file scanning.
|
|
112
|
+
*
|
|
113
|
+
* The hook receives each selected file and must return a Promise that
|
|
114
|
+
* resolves to `{ valid: boolean; reason?: string }`. When `valid` is
|
|
115
|
+
* false the file is rejected and the reason is shown to the user.
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```js
|
|
119
|
+
* const upload = document.querySelector('secure-file-upload');
|
|
120
|
+
* upload.setScanHook(async (file) => {
|
|
121
|
+
* const form = new FormData();
|
|
122
|
+
* form.append('file', file);
|
|
123
|
+
* const res = await fetch('/api/scan', { method: 'POST', body: form });
|
|
124
|
+
* const { clean, threat } = await res.json();
|
|
125
|
+
* return { valid: clean, reason: threat };
|
|
126
|
+
* });
|
|
127
|
+
* ```
|
|
128
|
+
*
|
|
129
|
+
* @public
|
|
130
|
+
*/
|
|
131
|
+
setScanHook(hook: ScanHookFn): void;
|
|
132
|
+
/**
|
|
133
|
+
* Check whether a scan hook is registered
|
|
134
|
+
*
|
|
135
|
+
* @public
|
|
136
|
+
*/
|
|
137
|
+
get hasScanHook(): boolean;
|
|
138
|
+
/**
|
|
139
|
+
* Check whether a scan is currently in progress
|
|
140
|
+
*
|
|
141
|
+
* @public
|
|
142
|
+
*/
|
|
143
|
+
get scanning(): boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Cleanup on disconnect
|
|
146
|
+
*/
|
|
147
|
+
disconnectedCallback(): void;
|
|
148
|
+
}
|
|
149
|
+
export default SecureFileUpload;
|
|
150
|
+
//# sourceMappingURL=secure-file-upload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secure-file-upload.d.ts","sourceRoot":"","sources":["../../../src/components/secure-file-upload/secure-file-upload.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAGnE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,uCAAuC;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,iDAAiD;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;AAEjE;;;;;;;;GAQG;AACH,qBAAa,gBAAiB,SAAQ,mBAAmB;;IAyEvD;;;;OAIG;IACH,MAAM,KAAK,kBAAkB,IAAI,MAAM,EAAE,CAWxC;IAED;;OAEG;;IAKH;;;;;;;;OAQG;IACH,SAAS,CAAC,MAAM,IAAI,gBAAgB,GAAG,WAAW,GAAG,IAAI;IAkvBzD;;;;OAIG;IACH,SAAS,CAAC,qBAAqB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IActG;;;;OAIG;IACH,IAAI,KAAK,IAAI,QAAQ,GAAG,IAAI,CAE3B;IAED;;;;OAIG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;;OAIG;IACH,IAAI,KAAK,IAAI,OAAO,CAQnB;IAED;;;;OAIG;IACH,KAAK,IAAI,IAAI;IAIb;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI;IAUnC;;;;OAIG;IACH,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED;;;;OAIG;IACH,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED;;OAEG;IACH,oBAAoB,IAAI,IAAI;CAS7B;AAKD,eAAe,gBAAgB,CAAC"}
|