@tekus/design-system 5.34.0 → 5.36.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/fesm2022/tekus-design-system-components-action-group.mjs +1 -1
- package/fesm2022/tekus-design-system-components-action-group.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-button.mjs +24 -3
- package/fesm2022/tekus-design-system-components-button.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-card.mjs +1 -1
- package/fesm2022/tekus-design-system-components-card.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-carousel.mjs +234 -0
- package/fesm2022/tekus-design-system-components-carousel.mjs.map +1 -0
- package/fesm2022/tekus-design-system-components-color-picker.mjs +1 -1
- package/fesm2022/tekus-design-system-components-color-picker.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-drawer.mjs +1 -1
- package/fesm2022/tekus-design-system-components-drawer.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-dropdown.mjs +1 -1
- package/fesm2022/tekus-design-system-components-dropdown.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-fallback-view.mjs +1 -1
- package/fesm2022/tekus-design-system-components-fallback-view.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-header.mjs +29 -0
- package/fesm2022/tekus-design-system-components-header.mjs.map +1 -0
- package/fesm2022/tekus-design-system-components-icon.mjs +2 -2
- package/fesm2022/tekus-design-system-components-icon.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-modal.mjs +51 -31
- package/fesm2022/tekus-design-system-components-modal.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-process-steps.mjs +132 -0
- package/fesm2022/tekus-design-system-components-process-steps.mjs.map +1 -0
- package/fesm2022/tekus-design-system-components-sidebar-layout.mjs +20 -6
- package/fesm2022/tekus-design-system-components-sidebar-layout.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-stepper.mjs +1 -1
- package/fesm2022/tekus-design-system-components-stepper.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-table.mjs +1 -1
- package/fesm2022/tekus-design-system-components-table.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-toast.mjs +1 -1
- package/fesm2022/tekus-design-system-components-toast.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-toolbar.mjs +1 -1
- package/fesm2022/tekus-design-system-components-toolbar.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-topbar.mjs +1 -1
- package/fesm2022/tekus-design-system-components-topbar.mjs.map +1 -1
- package/fesm2022/tekus-design-system-components-uploader.mjs +1256 -0
- package/fesm2022/tekus-design-system-components-uploader.mjs.map +1 -0
- package/package.json +17 -1
- package/types/tekus-design-system-components-button.d.ts +20 -1
- package/types/tekus-design-system-components-carousel.d.ts +200 -0
- package/types/tekus-design-system-components-header.d.ts +33 -0
- package/types/tekus-design-system-components-modal.d.ts +31 -13
- package/types/tekus-design-system-components-process-steps.d.ts +72 -0
- package/types/tekus-design-system-components-sidebar-layout.d.ts +11 -1
- package/types/tekus-design-system-components-uploader.d.ts +524 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
import * as _tekus_design_system_components_uploader from '@tekus/design-system/components/uploader';
|
|
2
|
+
import * as _angular_core from '@angular/core';
|
|
3
|
+
import { ResourceRef, Signal, ElementRef, Provider, OnDestroy, InjectionToken } from '@angular/core';
|
|
4
|
+
import { Observable } from 'rxjs';
|
|
5
|
+
import { ProcessStep, ProcessStepsStatus } from '@tekus/design-system/components/process-steps';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* An item's lifecycle state: `idle` (no file yet) → `analyzing` (client-side
|
|
9
|
+
* preview/metadata) → `transforming` (`hooks.onTransform`) → `ready` →
|
|
10
|
+
* `queued` (waiting for `concurrencyLimit`) → `loading` (uploading, and/or
|
|
11
|
+
* `polling`) → terminal `success`/`error`/`invalid` (rejected by `restrictions`
|
|
12
|
+
* or `hooks.validate` before ever uploading).
|
|
13
|
+
*/
|
|
14
|
+
type UploaderStatus = 'idle' | 'analyzing' | 'transforming' | 'ready' | 'invalid' | 'queued' | 'loading' | 'success' | 'error';
|
|
15
|
+
/**
|
|
16
|
+
* Stable, non-namespaced identifiers for errors raised internally by the
|
|
17
|
+
* uploader engine. Passed as-is to `UploadFlowConfig.resolveText`, if
|
|
18
|
+
* provided by the consumer, instead of an i18n-shaped key.
|
|
19
|
+
*/
|
|
20
|
+
type UploaderErrorCode = 'FILE_CORRUPT' | 'INVALID_FORMAT' | 'FILE_TOO_LARGE' | 'ANALYSIS_FAILED' | 'PROCESS_FAILED' | 'EXTERNAL_VALIDATION_FAILED' | 'POLLING_FAILED' | 'NO_UPLOAD_STRATEGY_CONFIGURED';
|
|
21
|
+
/** Client-side-derived metadata about a file, gathered during `analyzing`. */
|
|
22
|
+
interface MediaMetadata {
|
|
23
|
+
readonly width?: number;
|
|
24
|
+
readonly height?: number;
|
|
25
|
+
readonly durationMs?: number;
|
|
26
|
+
readonly aspectRatio?: number;
|
|
27
|
+
readonly mimeType?: string;
|
|
28
|
+
readonly size?: number;
|
|
29
|
+
}
|
|
30
|
+
/** Result of the internal preview/metadata pass (`IUploaderPreviewProvider`). */
|
|
31
|
+
interface MediaAnalysis {
|
|
32
|
+
readonly previewUrl: string;
|
|
33
|
+
readonly previewBlob: Blob | undefined;
|
|
34
|
+
readonly previewBase64: string;
|
|
35
|
+
readonly metadata: MediaMetadata;
|
|
36
|
+
readonly analysisError?: boolean;
|
|
37
|
+
readonly technicalError?: string;
|
|
38
|
+
readonly errorDetail?: unknown;
|
|
39
|
+
}
|
|
40
|
+
/** One extension/size rule — use `FileRestrictions.rules` for per-type size limits. */
|
|
41
|
+
interface RestrictionRule {
|
|
42
|
+
extensions: string[];
|
|
43
|
+
maxSizeMB?: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* File-level validation, checked before anything else runs. Prefer `rules`
|
|
47
|
+
* (per-extension `maxSizeMB`) over the legacy `allowedExtensions`/`maxSizeMB`
|
|
48
|
+
* pair when different file types need different size limits — `rules` takes
|
|
49
|
+
* priority over the legacy fields when both are set.
|
|
50
|
+
*/
|
|
51
|
+
interface FileRestrictions {
|
|
52
|
+
rules?: RestrictionRule[];
|
|
53
|
+
maxSizeMB?: number;
|
|
54
|
+
allowedExtensions?: string[];
|
|
55
|
+
}
|
|
56
|
+
/** Returned by `PollingConfig.checkStatus` on every tick. */
|
|
57
|
+
interface PollingResponse {
|
|
58
|
+
/** Keep returning `'loading'` to keep polling; any other value stops it. */
|
|
59
|
+
readonly status: UploaderStatus;
|
|
60
|
+
/** Overrides the item's numeric progress, if provided. */
|
|
61
|
+
readonly progress?: number;
|
|
62
|
+
/** Thrown as the item's error when `status` is `'error'` — an `UploaderErrorCode` or any string. */
|
|
63
|
+
readonly error?: string;
|
|
64
|
+
/** Overrides the item's status text — hidden by the file-card while `status` is `'loading'`. */
|
|
65
|
+
readonly statusText?: string;
|
|
66
|
+
/**
|
|
67
|
+
* When provided, `tk-uploader` renders a `tk-process-steps` for this item
|
|
68
|
+
* automatically (below its file-card) — `config.polling` is the data
|
|
69
|
+
* source, `tk-process-steps` is just how the engine shows it. Omit these
|
|
70
|
+
* for a plain `progress`/`statusText` polling flow with no step list.
|
|
71
|
+
* Only rendered while `multiple` is `false` — with `multiple` on, the
|
|
72
|
+
* uploader falls back to the plain progress bar for every item.
|
|
73
|
+
*/
|
|
74
|
+
readonly steps?: ProcessStep[];
|
|
75
|
+
readonly stepsStatus?: ProcessStepsStatus;
|
|
76
|
+
readonly stepsTitle?: string;
|
|
77
|
+
readonly stepsDescription?: string;
|
|
78
|
+
/**
|
|
79
|
+
* Starts `tk-process-steps`'s own countdown once set (typically alongside
|
|
80
|
+
* a terminal `stepsStatus` like `error`) — `tk-uploader` never acts on it
|
|
81
|
+
* finishing by itself, it only emits `stepsCountdownFinished` with this
|
|
82
|
+
* item's id so the consumer decides what to do (close a modal, remove the
|
|
83
|
+
* item, show a toast, etc.).
|
|
84
|
+
*/
|
|
85
|
+
readonly stepsCountdownSeconds?: number;
|
|
86
|
+
readonly stepsCountdownLabel?: string;
|
|
87
|
+
}
|
|
88
|
+
/** A single decoded preview frame — `url`/`blob`/`base64` of the same image. */
|
|
89
|
+
interface PreviewFrame {
|
|
90
|
+
url: string;
|
|
91
|
+
blob: Blob;
|
|
92
|
+
base64: string;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Where a file was in its lifecycle when its remove button was clicked.
|
|
96
|
+
* `tk-uploader` never confirms or blocks removal itself — it only reports
|
|
97
|
+
* this, so the consumer can decide whether a confirmation makes sense (e.g.
|
|
98
|
+
* for `in-progress`) before calling `UploaderQueueService.removeFromQueue`.
|
|
99
|
+
*/
|
|
100
|
+
type UploaderRemovePhase = 'pre-upload' | 'in-progress' | 'post-upload';
|
|
101
|
+
interface UploaderRemoveRequest {
|
|
102
|
+
readonly id: string;
|
|
103
|
+
readonly phase: UploaderRemovePhase;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** A single file's live state in the queue — what `UploaderQueueService` tracks and updates. */
|
|
107
|
+
interface UploadItem<T = unknown> {
|
|
108
|
+
id: string;
|
|
109
|
+
file: File;
|
|
110
|
+
/** 0-100. */
|
|
111
|
+
progress: number;
|
|
112
|
+
status: UploaderStatus;
|
|
113
|
+
/** Set when `status` is `'error'`/`'invalid'` — an `UploaderErrorCode` or any string. */
|
|
114
|
+
error?: string;
|
|
115
|
+
previewUrl?: string;
|
|
116
|
+
previewBlob?: Blob;
|
|
117
|
+
previewBase64?: string;
|
|
118
|
+
metadata?: MediaMetadata;
|
|
119
|
+
/** Whatever `hooks.onTransform` returned — the shape every `steps`/`multipart` function receives. */
|
|
120
|
+
payload?: T;
|
|
121
|
+
/** Internal, non-namespaced key behind `statusText` (see `UploaderQueueService`'s `STATUS_KEY_MAP`). */
|
|
122
|
+
statusKey: string;
|
|
123
|
+
/** Resolved via `config.resolveText`, if provided — hidden by the file-card while `status` is `'loading'`. */
|
|
124
|
+
statusText: string;
|
|
125
|
+
steps?: ProcessStep[];
|
|
126
|
+
stepsStatus?: ProcessStepsStatus;
|
|
127
|
+
stepsTitle?: string;
|
|
128
|
+
stepsDescription?: string;
|
|
129
|
+
stepsCountdownSeconds?: number;
|
|
130
|
+
stepsCountdownLabel?: string;
|
|
131
|
+
}
|
|
132
|
+
/** One state transition, recorded for every item — not currently surfaced anywhere by default. */
|
|
133
|
+
interface AuditEntry {
|
|
134
|
+
itemId: string;
|
|
135
|
+
from: UploaderStatus | 'none';
|
|
136
|
+
to: UploaderStatus;
|
|
137
|
+
timestamp: number;
|
|
138
|
+
key: string;
|
|
139
|
+
errorDetail?: unknown;
|
|
140
|
+
}
|
|
141
|
+
/** Backing store for the queue — `UploaderStore`'s contract, injectable via `UPLOADER_STORE`. */
|
|
142
|
+
interface IUploaderStore<T = unknown> {
|
|
143
|
+
readonly uploadQueue: Signal<UploadItem<T>[]>;
|
|
144
|
+
add(item: UploadItem<T>): void;
|
|
145
|
+
update(id: string, updates: Partial<UploadItem<T>>): void;
|
|
146
|
+
remove(id: string): void;
|
|
147
|
+
clear(): void;
|
|
148
|
+
}
|
|
149
|
+
/** Generates a client-side preview/metadata pass for a file — injectable via `UPLOADER_PREVIEW_PROVIDER`. */
|
|
150
|
+
interface IUploaderPreviewProvider {
|
|
151
|
+
generatePreview(file: File): ResourceRef<MediaAnalysis | undefined>;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* HTTP transport for the consumer's own `steps`/`multipart.uploadPart`
|
|
155
|
+
* functions — injectable via `UPLOADER_TRANSPORT`. `tk-uploader` never calls
|
|
156
|
+
* this itself; it's registered purely for the consumer's convenience.
|
|
157
|
+
*/
|
|
158
|
+
interface IUploaderTransport {
|
|
159
|
+
upload(url: string, file: File | Blob, method?: 'PUT' | 'POST', headers?: Record<string, string | string[]> | null, reportProgress?: boolean, observe?: 'events' | 'body', withCredentials?: boolean): Observable<unknown>;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Consumer-defined bag threaded through a single item's whole flow — every
|
|
164
|
+
* `steps`/`multipart`/`polling` function receives the same `context` object
|
|
165
|
+
* and can merge data into it for later stages to read.
|
|
166
|
+
*/
|
|
167
|
+
type UploadContext<C extends Record<string, unknown> = Record<string, unknown>> = C;
|
|
168
|
+
/** Params passed to `MultipartConfig.init`. */
|
|
169
|
+
interface InitParams<T = unknown> {
|
|
170
|
+
readonly file: File;
|
|
171
|
+
readonly payload: T | undefined;
|
|
172
|
+
}
|
|
173
|
+
/** Params passed to `MultipartConfig.uploadPart`. */
|
|
174
|
+
interface UploadPartParams<T = unknown, C extends Record<string, unknown> = Record<string, unknown>> extends InitParams<T> {
|
|
175
|
+
readonly chunk: Blob;
|
|
176
|
+
readonly partNumber: number;
|
|
177
|
+
readonly context: UploadContext<C>;
|
|
178
|
+
readonly metadata?: MediaMetadata;
|
|
179
|
+
}
|
|
180
|
+
/** Params passed to `MultipartConfig.complete`. */
|
|
181
|
+
interface CompleteParams<T = unknown, C extends Record<string, unknown> = Record<string, unknown>> {
|
|
182
|
+
readonly file: File;
|
|
183
|
+
readonly context: UploadContext<C>;
|
|
184
|
+
readonly payload: T | undefined;
|
|
185
|
+
}
|
|
186
|
+
/** Params passed to each `UploadStep` in `config.steps`. */
|
|
187
|
+
interface StepParams<T = unknown, C extends Record<string, unknown> = Record<string, unknown>> {
|
|
188
|
+
readonly file: File;
|
|
189
|
+
readonly context: UploadContext<C>;
|
|
190
|
+
readonly payload: T | undefined;
|
|
191
|
+
readonly item?: UploadItem<T>;
|
|
192
|
+
}
|
|
193
|
+
/** Params passed to `hooks.validate`. */
|
|
194
|
+
interface ValidateParams {
|
|
195
|
+
readonly file: File;
|
|
196
|
+
readonly metadata: MediaMetadata;
|
|
197
|
+
}
|
|
198
|
+
/** Params passed to `PollingConfig.checkStatus`. */
|
|
199
|
+
interface CheckStatusParams<T = unknown, C extends Record<string, unknown> = Record<string, unknown>> {
|
|
200
|
+
readonly context: UploadContext<C>;
|
|
201
|
+
readonly payload: T | undefined;
|
|
202
|
+
}
|
|
203
|
+
/** Params passed to `hooks.onStepComplete`. */
|
|
204
|
+
interface OnStepCompleteParams<C extends Record<string, unknown> = Record<string, unknown>> {
|
|
205
|
+
readonly stepIndex: number;
|
|
206
|
+
readonly context: UploadContext<C>;
|
|
207
|
+
}
|
|
208
|
+
/** Params passed to `hooks.onSuccess`. */
|
|
209
|
+
interface OnSuccessParams<T = unknown, C extends Record<string, unknown> = Record<string, unknown>> {
|
|
210
|
+
readonly context: UploadContext<C>;
|
|
211
|
+
readonly payload: T | undefined;
|
|
212
|
+
}
|
|
213
|
+
/** Params passed to `hooks.onError`. */
|
|
214
|
+
interface OnErrorParams<C extends Record<string, unknown> = Record<string, unknown>> {
|
|
215
|
+
readonly error: unknown;
|
|
216
|
+
readonly context?: UploadContext<C>;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* One stage of a `config.steps` flow — run in order, one after another.
|
|
221
|
+
* Whatever it resolves to is merged into `context`, so later steps (and
|
|
222
|
+
* `hooks.onStepComplete`/`onSuccess`) can read what earlier steps put there.
|
|
223
|
+
* Used whenever `config.multipart` isn't set.
|
|
224
|
+
*/
|
|
225
|
+
type UploadStep<T = unknown, C extends Record<string, unknown> = Record<string, unknown>> = (params: StepParams<T, C>) => Observable<Partial<C>>;
|
|
226
|
+
/** Chunked upload flow — replaces `config.steps` for large files uploaded in parts. */
|
|
227
|
+
interface MultipartConfig<T = unknown, C extends Record<string, unknown> = Record<string, unknown>> {
|
|
228
|
+
/** Size of each chunk, in megabytes. */
|
|
229
|
+
readonly chunkSizeMB: number;
|
|
230
|
+
/** Starts the multipart upload; whatever it resolves to is merged into `context`. */
|
|
231
|
+
readonly init: (params: InitParams<T>) => Observable<Partial<C>>;
|
|
232
|
+
/**
|
|
233
|
+
* Uploads a single chunk. May emit a `number` (0-100 progress for that
|
|
234
|
+
* chunk) and/or a `Partial<C>` to merge into `context` — a `string` is
|
|
235
|
+
* accepted but ignored.
|
|
236
|
+
*/
|
|
237
|
+
readonly uploadPart: (params: {
|
|
238
|
+
readonly file: File;
|
|
239
|
+
readonly chunk: Blob;
|
|
240
|
+
readonly partNumber: number;
|
|
241
|
+
readonly context: UploadContext<C>;
|
|
242
|
+
readonly metadata?: MediaMetadata;
|
|
243
|
+
}) => Observable<number | string | Partial<C>>;
|
|
244
|
+
/** Finalizes the multipart upload once every chunk has resolved. */
|
|
245
|
+
readonly complete: (params: {
|
|
246
|
+
readonly context: UploadContext<C>;
|
|
247
|
+
readonly payload?: T;
|
|
248
|
+
}) => Observable<boolean>;
|
|
249
|
+
}
|
|
250
|
+
/** Keeps asking the backend for status after the byte upload itself succeeds. */
|
|
251
|
+
interface PollingConfig<T = unknown, C extends Record<string, unknown> = Record<string, unknown>> {
|
|
252
|
+
/**
|
|
253
|
+
* Called on every tick. See `PollingResponse` — extend the returned object
|
|
254
|
+
* with `steps`/`stepsStatus`/`stepsTitle`/`stepsDescription` to have
|
|
255
|
+
* `tk-uploader` render a `tk-process-steps` for that item automatically.
|
|
256
|
+
*/
|
|
257
|
+
readonly checkStatus: (params: CheckStatusParams<T, C>) => Observable<PollingResponse>;
|
|
258
|
+
/** Milliseconds between ticks. Defaults to `UPLOADER_DEFAULTS.pollingIntervalMs`. */
|
|
259
|
+
readonly intervalMs?: number;
|
|
260
|
+
}
|
|
261
|
+
/** Lifecycle callbacks — the engine's only way to talk back to the consumer. */
|
|
262
|
+
interface UploadHooks<T = unknown, C extends Record<string, unknown> = Record<string, unknown>> {
|
|
263
|
+
/** Fires as soon as a file is added to the queue, before validation/analysis. */
|
|
264
|
+
readonly onFileAdded?: (file: File) => void;
|
|
265
|
+
/** Extra validation beyond `restrictions` — return `false`/an error string/code to reject. */
|
|
266
|
+
readonly validate?: (params: ValidateParams) => Observable<boolean | string> | boolean | string;
|
|
267
|
+
/** Fires right before a `ready` item actually starts uploading. */
|
|
268
|
+
readonly onBeforeStart?: (file: File) => void;
|
|
269
|
+
/** Fires after each `steps` entry resolves — see `OnStepCompleteParams`. */
|
|
270
|
+
readonly onStepComplete?: (params: OnStepCompleteParams<C>) => void;
|
|
271
|
+
/** Fires once the upload (and `polling`, if configured) finishes successfully. */
|
|
272
|
+
readonly onSuccess?: (params: OnSuccessParams<T, C>) => void;
|
|
273
|
+
/**
|
|
274
|
+
* Cheap, client-side transform run after `validate` passes, before the item is
|
|
275
|
+
* queued/started. Whatever it returns becomes `item.payload` — the shape every
|
|
276
|
+
* `steps`/`multipart` function receives as `payload`.
|
|
277
|
+
*/
|
|
278
|
+
readonly onTransform?: (item: UploadItem<unknown>) => Promise<T> | T;
|
|
279
|
+
/** Fires whenever a `steps`/`multipart`/`polling` observable errors. */
|
|
280
|
+
readonly onError?: (params: OnErrorParams<C>) => void;
|
|
281
|
+
/** Fires once every item in the queue has reached a terminal state. */
|
|
282
|
+
readonly onAllComplete?: () => void;
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Everything `tk-uploader` needs to run a flow — supplied entirely by the
|
|
286
|
+
* consumer. The component itself has no business logic: validation, upload
|
|
287
|
+
* mechanics (`steps` vs `multipart`), post-upload `polling` and every
|
|
288
|
+
* lifecycle callback are all config, so the same component works for a
|
|
289
|
+
* single synchronous `POST`, a chunked multipart upload, or a long-running
|
|
290
|
+
* job that has to be polled for completion.
|
|
291
|
+
*/
|
|
292
|
+
interface UploadFlowConfig<T = unknown, C extends Record<string, unknown> = Record<string, unknown>> {
|
|
293
|
+
/** File-level validation, checked before anything else runs. */
|
|
294
|
+
readonly restrictions?: FileRestrictions;
|
|
295
|
+
/** Sequential upload flow — ignored if `multipart` is set. */
|
|
296
|
+
readonly steps?: UploadStep<T, C>[];
|
|
297
|
+
/** Whether `ready` items start uploading on their own, instead of waiting for a manual trigger. */
|
|
298
|
+
readonly autoStart?: Signal<boolean> | boolean;
|
|
299
|
+
/** Chunked upload flow — takes priority over `steps` when set. */
|
|
300
|
+
readonly multipart?: MultipartConfig<T, C>;
|
|
301
|
+
/** Max items allowed in `loading` at once — a throughput gate, not an admission cap (see `multiple`). */
|
|
302
|
+
readonly concurrencyLimit?: number;
|
|
303
|
+
/** Divides the 0-100 progress range across a larger choreography this flow is only part of. */
|
|
304
|
+
readonly totalSteps?: number;
|
|
305
|
+
/** Post-upload status checks — see `PollingConfig`. */
|
|
306
|
+
readonly polling?: PollingConfig<T, C>;
|
|
307
|
+
/** Lifecycle callbacks — see `UploadHooks`. */
|
|
308
|
+
readonly hooks?: UploadHooks<T, C>;
|
|
309
|
+
/**
|
|
310
|
+
* Resolves a plain `UploaderErrorCode`/status-key string into consumer-facing
|
|
311
|
+
* text — e.g. wiring it to an i18n service. Omit to surface the raw code.
|
|
312
|
+
*/
|
|
313
|
+
readonly resolveText?: (key: string) => string;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Terminal "existing file" card rendered instead of the idle dropzone while
|
|
318
|
+
* the queue is empty (e.g. edit mode: an already-loaded entity) — the whole
|
|
319
|
+
* card is clickable to re-open the picker for a new version, same as any
|
|
320
|
+
* idle uploader. Purely presentational: `tk-uploader` never mutates it.
|
|
321
|
+
*/
|
|
322
|
+
interface LoaderPlaceholder<T> {
|
|
323
|
+
id: string | number;
|
|
324
|
+
/** Carried along unchanged — read it back from wherever this placeholder came from. */
|
|
325
|
+
payload: T;
|
|
326
|
+
title: string;
|
|
327
|
+
statusText: string;
|
|
328
|
+
status: UploaderStatus;
|
|
329
|
+
progress?: number;
|
|
330
|
+
previewUrl?: string | null;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Drag-and-drop upload zone with a queue of file cards. Fully agnostic: it
|
|
335
|
+
* has no opinion on *how* a file gets uploaded — validation, upload
|
|
336
|
+
* mechanics, post-upload polling and every lifecycle callback are supplied
|
|
337
|
+
* by the consumer through `config` (`UploadFlowConfig`). Requires
|
|
338
|
+
* `provideUploader()` in the providers of the hosting component (or a parent).
|
|
339
|
+
*/
|
|
340
|
+
declare class UploaderComponent<T = unknown, C extends Record<string, unknown> = Record<string, unknown>> {
|
|
341
|
+
private readonly queueService;
|
|
342
|
+
/** Idle-state heading, shown before any file is selected. */
|
|
343
|
+
title: _angular_core.InputSignal<string>;
|
|
344
|
+
/** Whether more than one file can be added to the queue at once. */
|
|
345
|
+
multiple: _angular_core.InputSignal<boolean>;
|
|
346
|
+
/** Idle-state helper text. */
|
|
347
|
+
subtitle: _angular_core.InputSignal<string>;
|
|
348
|
+
/** Optional helper line shown below the drop zone while it's empty. */
|
|
349
|
+
helperText: _angular_core.InputSignal<string | null>;
|
|
350
|
+
/** Label for the optional link appended to `helperText`. */
|
|
351
|
+
helperLinkText: _angular_core.InputSignal<string | null>;
|
|
352
|
+
/** URL for the optional link appended to `helperText`. */
|
|
353
|
+
helperLinkUrl: _angular_core.InputSignal<string | null>;
|
|
354
|
+
/** Everything this instance needs to run its flow — see `UploadFlowConfig`. */
|
|
355
|
+
config: _angular_core.InputSignal<UploadFlowConfig<T, C>>;
|
|
356
|
+
/**
|
|
357
|
+
* Terminal "existing file" card shown instead of the idle dropzone while
|
|
358
|
+
* the queue is empty (e.g. edit mode: an already-loaded entity) — see
|
|
359
|
+
* `LoaderPlaceholder`.
|
|
360
|
+
*/
|
|
361
|
+
placeholder: _angular_core.InputSignal<LoaderPlaceholder<unknown> | null>;
|
|
362
|
+
/**
|
|
363
|
+
* Ids the consumer is currently waiting on its own confirmation for (see
|
|
364
|
+
* `removeRequested`). Matching cards disable their remove button so the
|
|
365
|
+
* user can't double-trigger a request while a decision is pending — this
|
|
366
|
+
* component still has no opinion on what that confirmation looks like.
|
|
367
|
+
*/
|
|
368
|
+
pendingRemovalIds: _angular_core.InputSignal<readonly string[]>;
|
|
369
|
+
/**
|
|
370
|
+
* Tooltip/accessible label for a real queue item's remove button — `tk-uploader` has no
|
|
371
|
+
* copy of its own (same reasoning as `UploadFlowConfig.resolveText`), so the button stays
|
|
372
|
+
* unlabeled unless the consumer supplies text here.
|
|
373
|
+
*/
|
|
374
|
+
removeLabel: _angular_core.InputSignal<string | undefined>;
|
|
375
|
+
/** Tooltip/accessible label for the `placeholder` card's trailing (re-upload) button. */
|
|
376
|
+
placeholderReplaceLabel: _angular_core.InputSignal<string | undefined>;
|
|
377
|
+
/** Emitted with the raw `File`(s) as soon as they're picked/dropped — `File[]` when `multiple`, a single `File` otherwise. */
|
|
378
|
+
fileSelected: _angular_core.OutputEmitterRef<File | File[]>;
|
|
379
|
+
/**
|
|
380
|
+
* Emitted when a file-card's remove button is clicked — `tk-uploader` never
|
|
381
|
+
* removes the item itself. Inspect `phase` to decide whether to confirm
|
|
382
|
+
* (typically for `in-progress`) before calling
|
|
383
|
+
* `UploaderQueueService.removeFromQueue(id)`.
|
|
384
|
+
*/
|
|
385
|
+
removeRequested: _angular_core.OutputEmitterRef<UploaderRemoveRequest>;
|
|
386
|
+
/**
|
|
387
|
+
* Emitted when an item's `tk-process-steps` countdown (`stepsCountdownSeconds`)
|
|
388
|
+
* reaches zero — `tk-uploader` never acts on it itself (doesn't remove the
|
|
389
|
+
* item, doesn't close anything). The consumer decides what that means: close
|
|
390
|
+
* a modal, remove the item, show a toast, etc.
|
|
391
|
+
*/
|
|
392
|
+
stepsCountdownFinished: _angular_core.OutputEmitterRef<string>;
|
|
393
|
+
protected fileInput: _angular_core.Signal<ElementRef<HTMLInputElement>>;
|
|
394
|
+
protected queue: _angular_core.Signal<_tekus_design_system_components_uploader.UploadItem<unknown>[]>;
|
|
395
|
+
protected isDragging: _angular_core.WritableSignal<boolean>;
|
|
396
|
+
/**
|
|
397
|
+
* Files already in a terminal state (`success` / `error` / `invalid`) are
|
|
398
|
+
* done — they don't consume capacity anymore even though they stay visible
|
|
399
|
+
* in the queue until manually removed. Capacity is about what's still
|
|
400
|
+
* in-flight, not the size of the visible history.
|
|
401
|
+
*/
|
|
402
|
+
private readonly activeCount;
|
|
403
|
+
isAtCapacity: _angular_core.Signal<boolean>;
|
|
404
|
+
/**
|
|
405
|
+
* Native `accept` attribute for the hidden `<input type="file">`, derived
|
|
406
|
+
* from `config.restrictions` (`rules[].extensions` or `allowedExtensions`)
|
|
407
|
+
* — the same list that actually validates a file — so there is a single
|
|
408
|
+
* source of truth instead of a separate, independently-settable input that
|
|
409
|
+
* could drift out of sync with it. This is only a hint for the OS file
|
|
410
|
+
* picker: it does not filter drag & drop and does not validate anything.
|
|
411
|
+
*/
|
|
412
|
+
protected accept: _angular_core.Signal<string>;
|
|
413
|
+
private dragCounter;
|
|
414
|
+
onDragOver(event: DragEvent): void;
|
|
415
|
+
onDragEnter(event: DragEvent): void;
|
|
416
|
+
onDragLeave(event: DragEvent): void;
|
|
417
|
+
onDrop(event: DragEvent): void;
|
|
418
|
+
onFileChange(event: Event): void;
|
|
419
|
+
onCancelItem(id: string): void;
|
|
420
|
+
protected isPendingRemoval(id: string): boolean;
|
|
421
|
+
protected stepsTitleFor(stepsTitle: string | undefined): string;
|
|
422
|
+
/** Opens the OS file picker programmatically — a no-op while `isAtCapacity()`. */
|
|
423
|
+
triggerBrowse(): void;
|
|
424
|
+
private handleFiles;
|
|
425
|
+
private emitFileSelection;
|
|
426
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UploaderComponent<any, any>, never>;
|
|
427
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<UploaderComponent<any, any>, "tk-uploader", never, { "title": { "alias": "title"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "subtitle": { "alias": "subtitle"; "required": false; "isSignal": true; }; "helperText": { "alias": "helperText"; "required": false; "isSignal": true; }; "helperLinkText": { "alias": "helperLinkText"; "required": false; "isSignal": true; }; "helperLinkUrl": { "alias": "helperLinkUrl"; "required": false; "isSignal": true; }; "config": { "alias": "config"; "required": true; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "pendingRemovalIds": { "alias": "pendingRemovalIds"; "required": false; "isSignal": true; }; "removeLabel": { "alias": "removeLabel"; "required": false; "isSignal": true; }; "placeholderReplaceLabel": { "alias": "placeholderReplaceLabel"; "required": false; "isSignal": true; }; }, { "fileSelected": "fileSelected"; "removeRequested": "removeRequested"; "stepsCountdownFinished": "stepsCountdownFinished"; }, never, never, true, never>;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Registers every service `tk-uploader` depends on (queue, preview,
|
|
432
|
+
* transport) — add to the `providers` of the component that hosts
|
|
433
|
+
* `tk-uploader` (or a parent). Each instance gets its own queue.
|
|
434
|
+
*/
|
|
435
|
+
declare function provideUploader(): Provider[];
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* The engine — orchestrates the whole upload flow (validation, analysis,
|
|
439
|
+
* transform, `steps`/`multipart`, `polling`, lifecycle hooks) driven purely
|
|
440
|
+
* by the `UploadFlowConfig` passed to `addToQueue`. Not `providedIn: 'root'`;
|
|
441
|
+
* `provideUploader()` gives each `tk-uploader` its own instance.
|
|
442
|
+
*/
|
|
443
|
+
declare class UploaderQueueService<C extends Record<string, unknown> = Record<string, unknown>> implements OnDestroy {
|
|
444
|
+
private readonly store;
|
|
445
|
+
private readonly previewProvider;
|
|
446
|
+
private readonly injector;
|
|
447
|
+
private readonly activeSubscriptions;
|
|
448
|
+
private readonly isManualTriggered;
|
|
449
|
+
private currentConfig?;
|
|
450
|
+
readonly uploadQueue: _angular_core.Signal<UploadItem<unknown>[]>;
|
|
451
|
+
/** Every state transition recorded so far — not currently surfaced anywhere by default. */
|
|
452
|
+
readonly auditHistory: _angular_core.WritableSignal<AuditEntry[]>;
|
|
453
|
+
/** Whether any item is actively `loading` right now. */
|
|
454
|
+
readonly isUploading: _angular_core.Signal<boolean>;
|
|
455
|
+
/** Whether any item is mid-flight (`analyzing`/`transforming`/`loading`) — client-side or network work in progress. */
|
|
456
|
+
readonly isBusy: _angular_core.Signal<boolean>;
|
|
457
|
+
/** `!isBusy()` — whether it's safe to close/navigate away without losing in-flight work. */
|
|
458
|
+
readonly canSafetyClose: _angular_core.Signal<boolean>;
|
|
459
|
+
ngOnDestroy(): void;
|
|
460
|
+
/**
|
|
461
|
+
* Adds one or more files to the queue and starts them through validation →
|
|
462
|
+
* analysis → transform → (auto-start or wait for `startUpload`/`startAllReady`).
|
|
463
|
+
* `config` becomes `currentConfig`, reused by every later call until the next `addToQueue`.
|
|
464
|
+
*/
|
|
465
|
+
addToQueue<T = unknown>(files: File | File[], config: UploadFlowConfig<T, C>): void;
|
|
466
|
+
private runAnalysis;
|
|
467
|
+
private handleAnalysisResult;
|
|
468
|
+
private validateExternalRestrictions;
|
|
469
|
+
private runTransformation;
|
|
470
|
+
/** Manually starts a single `ready` item (when `autoStart` is `false`). */
|
|
471
|
+
startUpload(id: string): void;
|
|
472
|
+
/** Manually starts every `ready` item at once (when `autoStart` is `false`). */
|
|
473
|
+
startAllReady(): void;
|
|
474
|
+
private checkConcurrencyAndProcess;
|
|
475
|
+
private processUpload;
|
|
476
|
+
private startUploadFlow;
|
|
477
|
+
private getExecutionStream;
|
|
478
|
+
private finalizeItem;
|
|
479
|
+
private extractErrorCode;
|
|
480
|
+
private getErrorText;
|
|
481
|
+
private resolveUploaderKeyText;
|
|
482
|
+
private handleError;
|
|
483
|
+
private checkAllComplete;
|
|
484
|
+
/**
|
|
485
|
+
* Removes an item outright — revokes its preview blob URL and cancels any
|
|
486
|
+
* in-flight upload subscription first. This is outside `UploadFlowConfig`'s
|
|
487
|
+
* contract on purpose: `tk-uploader` only ever reports a removal request
|
|
488
|
+
* (see `UploaderRemoveRequest`/`removeRequested`), the consumer decides
|
|
489
|
+
* whether/when to actually call this.
|
|
490
|
+
*
|
|
491
|
+
* Deliberately does NOT cancel a still-pending `${id}_analysis` subscription:
|
|
492
|
+
* doing so would drop the analysis result (and any blob URL it already created)
|
|
493
|
+
* on the floor with nothing left to revoke it. Letting it resolve naturally lets
|
|
494
|
+
* `handleAnalysisResult`'s own "item still in the queue?" check catch it instead.
|
|
495
|
+
*/
|
|
496
|
+
removeFromQueue(id: string): void;
|
|
497
|
+
private revokeItemPreview;
|
|
498
|
+
private cancelSubscription;
|
|
499
|
+
/** Cancels an item's in-flight subscription without removing it — `startUpload` resumes it. */
|
|
500
|
+
pauseUpload(id: string): void;
|
|
501
|
+
/** Revokes every preview blob URL, cancels every in-flight subscription, and empties the store. */
|
|
502
|
+
clearQueue(): void;
|
|
503
|
+
private getStatusKey;
|
|
504
|
+
private getStatusText;
|
|
505
|
+
private patchItem;
|
|
506
|
+
private addAuditEntry;
|
|
507
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<UploaderQueueService<any>, never>;
|
|
508
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<UploaderQueueService<any>>;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/** Queue backing store — provided by `provideUploader()`, actively injected by `UploaderQueueService`. */
|
|
512
|
+
declare const UPLOADER_STORE: InjectionToken<IUploaderStore<unknown>>;
|
|
513
|
+
/** Client-side preview/metadata generator — provided by `provideUploader()`, actively injected internally. */
|
|
514
|
+
declare const UPLOADER_PREVIEW_PROVIDER: InjectionToken<IUploaderPreviewProvider>;
|
|
515
|
+
/**
|
|
516
|
+
* HTTP transport — provided by `provideUploader()`, but never injected
|
|
517
|
+
* internally. Registered purely so the consumer's own `steps`/
|
|
518
|
+
* `multipart.uploadPart` functions can `inject(UPLOADER_TRANSPORT)` instead
|
|
519
|
+
* of instantiating `HttpClient` themselves.
|
|
520
|
+
*/
|
|
521
|
+
declare const UPLOADER_TRANSPORT: InjectionToken<IUploaderTransport>;
|
|
522
|
+
|
|
523
|
+
export { UPLOADER_PREVIEW_PROVIDER, UPLOADER_STORE, UPLOADER_TRANSPORT, UploaderComponent, UploaderQueueService, provideUploader };
|
|
524
|
+
export type { AuditEntry, CheckStatusParams, CompleteParams, FileRestrictions, IUploaderPreviewProvider, IUploaderStore, IUploaderTransport, InitParams, LoaderPlaceholder, MediaAnalysis, MediaMetadata, MultipartConfig, OnErrorParams, OnStepCompleteParams, OnSuccessParams, PollingConfig, PollingResponse, PreviewFrame, RestrictionRule, StepParams, UploadContext, UploadFlowConfig, UploadHooks, UploadItem, UploadPartParams, UploadStep, UploaderErrorCode, UploaderRemovePhase, UploaderRemoveRequest, UploaderStatus, ValidateParams };
|