@sehv-oss/basketball-upload 1.0.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.
@@ -0,0 +1,567 @@
1
+ //#region src/file-types/types.d.ts
2
+ /**
3
+ * What the body of a file card shows:
4
+ * - `lines`: the paper with grey text lines of the design.
5
+ * - `thumbnail`: a preview of the file itself (images), falling back to `lines`.
6
+ * - a function: any node you build, placed in the `file-artwork` part.
7
+ */
8
+ type FileArtwork = 'lines' | 'thumbnail' | ((file: File) => Node);
9
+ /**
10
+ * How files of one type look on the court and in the upload list.
11
+ */
12
+ interface FileType {
13
+ /**
14
+ * Stable id: lowercase letters, digits and dashes, starting with a letter.
15
+ * Becomes the `data-kind` attribute, the parts `file-<kind>` and
16
+ * `item-icon-<kind>`, and the token `--basketball-upload-file-<kind>`.
17
+ */
18
+ readonly kind: string;
19
+ /**
20
+ * `accept` syntax (`.pdf`, `application/pdf`, `image/*`, comma separated), or a predicate.
21
+ */
22
+ readonly match: string | ((file: File) => boolean);
23
+ /**
24
+ * Badge text. Defaults to the extension in capitals, at most 4 characters.
25
+ */
26
+ readonly label?: string | ((file: File) => string) | undefined;
27
+ /**
28
+ * Badge color: any CSS color, `light-dark()` included.
29
+ */
30
+ readonly color?: string | undefined;
31
+ /**
32
+ * Defaults to `lines`.
33
+ */
34
+ readonly artwork?: FileArtwork | undefined;
35
+ }
36
+ /**
37
+ * A file type applied to one file, as `resolveFileType` returns it: every
38
+ * default filled in.
39
+ */
40
+ interface ResolvedFileType {
41
+ /**
42
+ * `kind` of the matching type, or `file` when none matched.
43
+ */
44
+ readonly kind: string;
45
+ /**
46
+ * Badge text for this file.
47
+ */
48
+ readonly label: string;
49
+ /**
50
+ * `null` uses the neutral `--basketball-upload-file-badge` token.
51
+ */
52
+ readonly color: string | null;
53
+ /**
54
+ * What the body of the card shows.
55
+ */
56
+ readonly artwork: FileArtwork;
57
+ }
58
+ //#endregion
59
+ //#region src/upload/types.d.ts
60
+ /**
61
+ * - `ready`: accepted without an uploader; the file only travels with its form.
62
+ * - `queued`: waiting for a free upload slot.
63
+ * - `uploading` / `uploaded` / `error`: the uploader's progress and outcome.
64
+ */
65
+ type UploadStatus = 'ready' | 'queued' | 'uploading' | 'uploaded' | 'error';
66
+ /**
67
+ * A file in the basket and its upload. Items are immutable: every change
68
+ * replaces the item with a new one, under the same `id`.
69
+ */
70
+ interface UploadItem {
71
+ /**
72
+ * Unique within the element, for `retryItem()` and `removeItem()`.
73
+ */
74
+ readonly id: string;
75
+ readonly file: File;
76
+ readonly status: UploadStatus;
77
+ /**
78
+ * From 0 to 1.
79
+ */
80
+ readonly progress: number;
81
+ /**
82
+ * Whatever the uploader resolved with.
83
+ */
84
+ readonly response: unknown;
85
+ /**
86
+ * Whatever the uploader rejected with.
87
+ */
88
+ readonly error: unknown;
89
+ }
90
+ /**
91
+ * Second argument of an `Uploader`.
92
+ */
93
+ interface UploadContext {
94
+ /**
95
+ * Aborted when the item is removed or the queue is cleared.
96
+ */
97
+ readonly signal: AbortSignal;
98
+ /**
99
+ * `total` defaults to the size of the file.
100
+ */
101
+ readonly onProgress: (loaded: number, total?: number) => void;
102
+ }
103
+ /**
104
+ * Sends one file. Resolve when it is stored, reject when it failed.
105
+ */
106
+ type Uploader = (file: File, context: UploadContext) => Promise<unknown>;
107
+ //#endregion
108
+ //#region src/element/messages.d.ts
109
+ /**
110
+ * Why a file was turned away:
111
+ * - `type`: it does not match `accept`.
112
+ * - `size`: it is larger than `max-size`.
113
+ * - `count`: it is one file more than `max-files` allows, or than one without
114
+ * `multiple`.
115
+ */
116
+ type RejectReason = 'type' | 'size' | 'count';
117
+ /**
118
+ * Visible copy and accessible names. The defaults are the copy of the
119
+ * reference design; override any of them with the `messages` property, or the
120
+ * first four with slots.
121
+ */
122
+ interface Messages {
123
+ /**
124
+ * Heading of the element. The `title` slot replaces it.
125
+ */
126
+ title: string;
127
+ /**
128
+ * Line under the heading. The `description` slot replaces it.
129
+ */
130
+ description: string;
131
+ /**
132
+ * Main text of the dropzone. The `prompt` slot replaces it.
133
+ */
134
+ prompt: string;
135
+ /**
136
+ * Text under the prompt. The `hint` slot replaces it.
137
+ */
138
+ hint: string;
139
+ /**
140
+ * Accessible name of the dropzone button.
141
+ */
142
+ dropzone: string;
143
+ /**
144
+ * Label of the pill that counts the files in the basket.
145
+ */
146
+ counter: string;
147
+ /**
148
+ * Accessible name of a card waiting on the court.
149
+ */
150
+ shoot: (name: string) => string;
151
+ /**
152
+ * Status of a file in the basket when there is no uploader.
153
+ */
154
+ ready: string;
155
+ /**
156
+ * Status of a file waiting for a free upload slot.
157
+ */
158
+ queued: string;
159
+ /**
160
+ * Status of a file being uploaded.
161
+ */
162
+ uploading: string;
163
+ /**
164
+ * Status of a file the uploader stored.
165
+ */
166
+ uploaded: string;
167
+ /**
168
+ * Status of a file whose upload failed.
169
+ */
170
+ failed: string;
171
+ /**
172
+ * Accessible name and tooltip of the retry button of a row.
173
+ */
174
+ retry: (name: string) => string;
175
+ /**
176
+ * Accessible name of the progress bar of a row.
177
+ */
178
+ progress: (name: string) => string;
179
+ /**
180
+ * Validation message when `required` and empty.
181
+ */
182
+ required: string;
183
+ /**
184
+ * Announced when a file goes through the net.
185
+ */
186
+ scored: (name: string) => string;
187
+ /**
188
+ * Announced when a shot misses.
189
+ */
190
+ missed: (name: string) => string;
191
+ /**
192
+ * Announced when a file is turned away.
193
+ */
194
+ rejected: (name: string, reason: RejectReason) => string;
195
+ /**
196
+ * Announced when an upload succeeds.
197
+ */
198
+ complete: (name: string) => string;
199
+ /**
200
+ * Announced when an upload fails.
201
+ */
202
+ error: (name: string) => string;
203
+ }
204
+ /**
205
+ * The copy of the reference design, in English.
206
+ */
207
+ export declare const defaultMessages: Messages;
208
+ //#endregion
209
+ //#region src/element/basketball-upload-element.d.ts
210
+ /**
211
+ * Color scheme of the element. `system` follows `prefers-color-scheme`.
212
+ */
213
+ type Theme = 'light' | 'dark' | 'system';
214
+ /**
215
+ * How a shot ended: through the net (a dunk included), or back on the court.
216
+ */
217
+ type ShotResult = 'score' | 'miss';
218
+ /**
219
+ * `CustomEvent`s dispatched by `<basketball-upload>`, keyed by event name. They bubble.
220
+ */
221
+ interface BasketballUploadEventMap {
222
+ /**
223
+ * A file did not pass `accept`, `max-size` or `max-files`, and stays out.
224
+ */
225
+ 'file-reject': CustomEvent<{
226
+ file: File;
227
+ reason: RejectReason;
228
+ }>;
229
+ /**
230
+ * A card went through the net, dunks included, or a shot missed and the
231
+ * card is back on the court.
232
+ */
233
+ shot: CustomEvent<{
234
+ file: File;
235
+ result: ShotResult;
236
+ }>;
237
+ /**
238
+ * The uploader was called for an item.
239
+ */
240
+ 'upload-start': CustomEvent<{
241
+ item: UploadItem;
242
+ }>;
243
+ /**
244
+ * The uploader reported progress; `item.progress` has the new value.
245
+ */
246
+ 'upload-progress': CustomEvent<{
247
+ item: UploadItem;
248
+ }>;
249
+ /**
250
+ * An upload resolved; `item.response` has its value.
251
+ */
252
+ 'upload-success': CustomEvent<{
253
+ item: UploadItem;
254
+ }>;
255
+ /**
256
+ * An upload rejected; `item.error` has the reason. Aborted uploads (removed
257
+ * items, `clear()`) do not fire it.
258
+ */
259
+ 'upload-error': CustomEvent<{
260
+ item: UploadItem;
261
+ }>;
262
+ /**
263
+ * Files entered or left the basket, or one changed status. Progress alone
264
+ * does not fire it: `upload-progress` does.
265
+ */
266
+ change: CustomEvent<{
267
+ items: readonly UploadItem[];
268
+ }>;
269
+ }
270
+ /**
271
+ * `HTMLElement` is missing where there is no DOM (SSR). Extending a stand-in
272
+ * keeps this module importable there; the class is only ever instantiated by
273
+ * `customElements.define`, which those environments do not have either.
274
+ */
275
+ declare const BaseElement: typeof HTMLElement;
276
+ /**
277
+ * `<basketball-upload>`: a file upload where the dropzone is a backboard.
278
+ * Drop files on it, or drop them on the court and take the shot.
279
+ */
280
+ export declare class BasketballUploadElement extends BaseElement {
281
+ #private;
282
+ static readonly formAssociated = true;
283
+ static readonly observedAttributes: readonly ['concurrency', 'disabled', 'name', 'required'];
284
+ constructor();
285
+ /**
286
+ * `light`, `dark`, or `system` (the default) to follow `prefers-color-scheme`.
287
+ */
288
+ get theme(): Theme;
289
+ set theme(value: Theme | null | undefined);
290
+ /**
291
+ * Accepted files, with the syntax of `<input type="file" accept>`.
292
+ */
293
+ get accept(): string;
294
+ set accept(value: string | null | undefined);
295
+ /**
296
+ * Several files at a time. Without it, a new file replaces the previous one.
297
+ */
298
+ get multiple(): boolean;
299
+ set multiple(value: boolean | null | undefined);
300
+ /**
301
+ * Largest accepted file, in bytes.
302
+ */
303
+ get maxSize(): number | null;
304
+ set maxSize(value: number | null | undefined);
305
+ /**
306
+ * Most files at once, staged and in the basket.
307
+ */
308
+ get maxFiles(): number | null;
309
+ set maxFiles(value: number | null | undefined);
310
+ /**
311
+ * Form field the files are submitted under.
312
+ */
313
+ get name(): string;
314
+ set name(value: string | null | undefined);
315
+ /**
316
+ * The form is invalid while the basket is empty.
317
+ */
318
+ get required(): boolean;
319
+ set required(value: boolean | null | undefined);
320
+ /**
321
+ * Ignores files and shots. A disabled `<fieldset>` does the same, without
322
+ * changing this property.
323
+ */
324
+ get disabled(): boolean;
325
+ set disabled(value: boolean | null | undefined);
326
+ /**
327
+ * No shooting: every file goes straight into the basket.
328
+ */
329
+ get instant(): boolean;
330
+ set instant(value: boolean | null | undefined);
331
+ /**
332
+ * Uploads running at the same time.
333
+ */
334
+ get concurrency(): number;
335
+ set concurrency(value: number | null | undefined);
336
+ /**
337
+ * Sends each file in the basket. Without one, files only travel with their form.
338
+ */
339
+ get uploader(): Uploader | null;
340
+ set uploader(value: Uploader | null | undefined);
341
+ /**
342
+ * Copy and accessible names. Assign a partial object to override some: it is
343
+ * merged over the defaults, not over the previous value, and keys set to
344
+ * `undefined` keep their default.
345
+ */
346
+ get messages(): Messages;
347
+ set messages(value: Partial<Messages> | null | undefined);
348
+ /**
349
+ * File types for this element only, checked before the registered ones.
350
+ */
351
+ get fileTypes(): readonly FileType[];
352
+ set fileTypes(value: readonly FileType[] | null | undefined);
353
+ /**
354
+ * Files in the basket and their uploads.
355
+ */
356
+ get items(): readonly UploadItem[];
357
+ /**
358
+ * Files in the basket: the value submitted with the form.
359
+ */
360
+ get files(): readonly File[];
361
+ /**
362
+ * The `<form>` the element belongs to, or `null`.
363
+ */
364
+ get form(): HTMLFormElement | null;
365
+ /**
366
+ * As on native controls: `valueMissing` while `required` and empty.
367
+ * `undefined` where `ElementInternals` is missing.
368
+ */
369
+ get validity(): ValidityState | undefined;
370
+ /**
371
+ * `messages.required` while `required` and empty, otherwise empty.
372
+ */
373
+ get validationMessage(): string;
374
+ /**
375
+ * Whether the form validates the element, as on native controls: not while
376
+ * disabled.
377
+ */
378
+ get willValidate(): boolean;
379
+ /**
380
+ * Whether the element is valid, firing `invalid` when it is not. Always
381
+ * valid where `ElementInternals` is missing.
382
+ */
383
+ checkValidity(): boolean;
384
+ /**
385
+ * Like `checkValidity()`, and shows the message on the dropzone when invalid.
386
+ */
387
+ reportValidity(): boolean;
388
+ /**
389
+ * Opens the file picker. The chosen files land on the court (or in the basket, with `instant`).
390
+ */
391
+ openPicker(): void;
392
+ /**
393
+ * Puts files on the court, ready to be shot (with `instant`, straight into
394
+ * the basket). Files that do not pass `accept`, `max-size` or `max-files`
395
+ * fire `file-reject` instead.
396
+ */
397
+ stage(files: Iterable<File>): void;
398
+ /**
399
+ * Puts files straight into the basket. Files that do not pass `accept`,
400
+ * `max-size` or `max-files` fire `file-reject` instead.
401
+ */
402
+ dunk(files: Iterable<File>): void;
403
+ /**
404
+ * Shoots the card on top of the court with a perfect shot. Returns `false`
405
+ * when it cannot: no card on the court, disabled, another card held or in
406
+ * the air, or the element not laid out.
407
+ */
408
+ shoot(): boolean;
409
+ /**
410
+ * Uploads a failed file again. Returns `false` when `id` is not an item in
411
+ * error, or there is no `uploader`.
412
+ */
413
+ retryItem(id: string): boolean;
414
+ /**
415
+ * Takes a file out of the basket, aborting its upload. Returns `false` when
416
+ * there is no item with this `id`.
417
+ */
418
+ removeItem(id: string): boolean;
419
+ /**
420
+ * Empties the court and the basket, aborting uploads.
421
+ */
422
+ clear(): void;
423
+ connectedCallback(): void;
424
+ disconnectedCallback(): void;
425
+ attributeChangedCallback(name: string, _oldValue: string | null, value: string | null): void;
426
+ formResetCallback(): void;
427
+ formDisabledCallback(disabled: boolean): void;
428
+ }
429
+ export interface BasketballUploadElement {
430
+ /**
431
+ * Typed for the events of `BasketballUploadEventMap`.
432
+ */
433
+ addEventListener<TType extends keyof BasketballUploadEventMap>(type: TType, listener: (this: BasketballUploadElement, event: BasketballUploadEventMap[TType]) => void, options?: boolean | AddEventListenerOptions): void;
434
+ /**
435
+ * Any other event, as on `HTMLElement`.
436
+ */
437
+ addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
438
+ /**
439
+ * Typed for the events of `BasketballUploadEventMap`.
440
+ */
441
+ removeEventListener<TType extends keyof BasketballUploadEventMap>(type: TType, listener: (this: BasketballUploadElement, event: BasketballUploadEventMap[TType]) => void, options?: boolean | EventListenerOptions): void;
442
+ /**
443
+ * Any other event, as on `HTMLElement`.
444
+ */
445
+ removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
446
+ }
447
+ declare global {
448
+ interface HTMLElementTagNameMap {
449
+ 'basketball-upload': BasketballUploadElement;
450
+ }
451
+ }
452
+ //#endregion
453
+ //#region src/element/register.d.ts
454
+ /**
455
+ * Options of `registerBasketballUpload`.
456
+ */
457
+ interface RegisterBasketballUploadOptions {
458
+ /**
459
+ * Custom element name. Defaults to `basketball-upload`.
460
+ */
461
+ tagName?: string | undefined;
462
+ }
463
+ /**
464
+ * Name the element is registered with when no `tagName` is given.
465
+ */
466
+ export declare const DEFAULT_TAG_NAME = "basketball-upload";
467
+ /**
468
+ * Defines the custom element. Idempotent, and a no-op where custom elements
469
+ * do not exist (SSR), so it is safe to call from any module.
470
+ */
471
+ export declare function registerBasketballUpload(options?: RegisterBasketballUploadOptions): void;
472
+ //#endregion
473
+ //#region src/file-types/defaults.d.ts
474
+ /**
475
+ * Built-in file types, checked after the ones you register.
476
+ */
477
+ export declare const defaultFileTypes: readonly FileType[];
478
+ //#endregion
479
+ //#region src/file-types/registry.d.ts
480
+ /**
481
+ * Adds a file type for every `<basketball-upload>` on the page. It wins over the
482
+ * built-in types and over the ones registered before it; types set on an
483
+ * element (`fileTypes`) still win over it. Returns a function that removes it.
484
+ */
485
+ export declare function registerFileType(type: FileType): () => void;
486
+ /**
487
+ * The look of a file: the first match among `instanceTypes`, then the
488
+ * registered types, then the built-in ones, then a neutral `file`.
489
+ */
490
+ export declare function resolveFileType(file: File, instanceTypes?: readonly FileType[]): ResolvedFileType;
491
+ //#endregion
492
+ //#region src/upload/accept.d.ts
493
+ /**
494
+ * The parts of a `File` that `matchesAccept` reads.
495
+ */
496
+ interface FileLike {
497
+ readonly name: string;
498
+ readonly type: string;
499
+ }
500
+ /**
501
+ * Whether a file matches an `accept` string, with the semantics of
502
+ * `<input type="file" accept>`: comma separated extensions (`.pdf`), MIME
503
+ * types (`application/pdf`) and wildcards (`image/*`). Empty accepts all.
504
+ */
505
+ export declare function matchesAccept(file: FileLike, accept: string | null | undefined): boolean;
506
+ //#endregion
507
+ //#region src/upload/format.d.ts
508
+ /**
509
+ * Human readable size in decimal units, the way file managers show it: `2_400_000` → `2.4 MB`.
510
+ * `locale` formats the number (`2,4 MB` in `de`); it defaults to the runtime's.
511
+ */
512
+ export declare function formatBytes(bytes: number, locale?: string): string;
513
+ //#endregion
514
+ //#region src/upload/xhr.d.ts
515
+ /**
516
+ * Options of `createXhrUploader`.
517
+ */
518
+ interface XhrUploaderOptions {
519
+ /**
520
+ * Endpoint, or a function of the file for one URL per file.
521
+ */
522
+ url: string | URL | ((file: File) => string | URL);
523
+ /**
524
+ * Defaults to `POST`.
525
+ */
526
+ method?: string | undefined;
527
+ /**
528
+ * Form field the file is sent under, as `multipart/form-data`. Defaults to
529
+ * `file`. `null` sends the file itself as the request body.
530
+ */
531
+ fieldName?: string | null | undefined;
532
+ /**
533
+ * Extra form fields, sent before the file. Ignored when `fieldName` is `null`.
534
+ */
535
+ fields?: Record<string, string | Blob> | ((file: File) => Record<string, string | Blob>) | undefined;
536
+ /**
537
+ * Request headers, or a function of the file.
538
+ */
539
+ headers?: Record<string, string> | ((file: File) => Record<string, string>) | undefined;
540
+ /**
541
+ * Sends cookies with cross-origin requests. Defaults to `false`.
542
+ */
543
+ withCredentials?: boolean | undefined;
544
+ }
545
+ /**
546
+ * Rejection reason of `createXhrUploader` for a non-2xx response or a network error.
547
+ */
548
+ export declare class UploadError extends Error {
549
+ /**
550
+ * HTTP status, or 0 when the request did not complete.
551
+ */
552
+ readonly status: number;
553
+ /**
554
+ * Response text, or an empty string when the request did not complete.
555
+ */
556
+ readonly body: string;
557
+ constructor(status: number, body: string);
558
+ }
559
+ /**
560
+ * An `Uploader` built on `XMLHttpRequest`, the one browser API that reports
561
+ * the progress of a request body. Resolves with the parsed JSON response (or
562
+ * its text), rejects with an `UploadError`, or with the abort reason.
563
+ */
564
+ export declare function createXhrUploader(options: XhrUploaderOptions): Uploader;
565
+ //#endregion
566
+ export type { BasketballUploadEventMap, FileArtwork, FileType, Messages, RegisterBasketballUploadOptions, RejectReason, ResolvedFileType, ShotResult, Theme, UploadContext, UploadItem, UploadStatus, Uploader, XhrUploaderOptions };
567
+ //# sourceMappingURL=basketball-upload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"basketball-upload.d.ts","names":[],"sources":["../src/file-types/types.ts","../src/upload/types.ts","../src/element/messages.ts","../src/element/basketball-upload-element.ts","../src/element/register.ts","../src/file-types/defaults.ts","../src/file-types/registry.ts","../src/upload/accept.ts","../src/upload/format.ts","../src/upload/xhr.ts"],"mappings":"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"}