ng-hub-ui-forms 22.4.0 → 22.6.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 +71 -3
- package/fesm2022/ng-hub-ui-forms.mjs +1157 -45
- package/fesm2022/ng-hub-ui-forms.mjs.map +1 -1
- package/ng-hub-ui-forms-22.6.0.tgz +0 -0
- package/package.json +6 -2
- package/{src/lib/styles → styles}/_tokens.scss +89 -5
- package/{src/lib/styles → styles}/index.scss +3 -0
- package/styles/mixins/_file-input-theme.scss +199 -0
- package/styles/mixins/_forms-theme.scss +67 -0
- package/{src/lib/styles → styles}/mixins/_segmented-theme.scss +1 -1
- package/types/ng-hub-ui-forms.d.ts +668 -16
- package/ng-hub-ui-forms-22.4.0.tgz +0 -0
- /package/{src/lib/styles → styles}/_field.scss +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
|
-
import { OnInit, AfterContentInit, OnDestroy, TemplateRef, ElementRef, InjectionToken, EnvironmentProviders, PipeTransform, NgZone, ViewContainerRef } from '@angular/core';
|
|
2
|
+
import { OnInit, AfterContentInit, OnDestroy, TemplateRef, ElementRef, InjectionToken, EnvironmentProviders, Type, PipeTransform, NgZone, ViewContainerRef } from '@angular/core';
|
|
3
3
|
import { NgControl, ControlContainer, ControlValueAccessor, ValidationErrors, AbstractControl, ValidatorFn } from '@angular/forms';
|
|
4
|
-
import { Subject, OperatorFunction } from 'rxjs';
|
|
4
|
+
import { Subject, Observable, OperatorFunction } from 'rxjs';
|
|
5
5
|
import * as ng_hub_ui_forms from 'ng-hub-ui-forms';
|
|
6
6
|
import { SafeUrl } from '@angular/platform-browser';
|
|
7
7
|
|
|
@@ -283,6 +283,85 @@ declare const defaultHubDatepickerLabels: HubDatepickerLabels;
|
|
|
283
283
|
/** Built-in datepicker defaults. */
|
|
284
284
|
declare const defaultHubDatepickerConfig: HubDatepickerConfig;
|
|
285
285
|
|
|
286
|
+
/** Why a file was refused by `<hub-file-input>` before it ever reached the form value. */
|
|
287
|
+
type HubFileRejectionReason = 'accept' | 'maxSize' | 'minSize' | 'maxFiles' | 'maxTotalSize' | 'duplicate';
|
|
288
|
+
/** A file the component refused, together with the constraint that refused it. */
|
|
289
|
+
interface HubFileRejection {
|
|
290
|
+
/** The refused file. */
|
|
291
|
+
file: File;
|
|
292
|
+
/** The constraint that refused it. */
|
|
293
|
+
reason: HubFileRejectionReason;
|
|
294
|
+
/** The configured limit that was violated (`accept` string, byte count, file count), when applicable. */
|
|
295
|
+
limit: string | number | null;
|
|
296
|
+
}
|
|
297
|
+
/** Lifecycle of a single accepted file. `uploading`/`done`/`error` only occur when an uploader is registered. */
|
|
298
|
+
type HubFileStatus = 'ready' | 'uploading' | 'done' | 'error';
|
|
299
|
+
/**
|
|
300
|
+
* The rich, per-file state exposed by `<hub-file-input>` through its `files()` signal.
|
|
301
|
+
*
|
|
302
|
+
* This is deliberately **not** the form-control value: the control holds plain `File` objects so it
|
|
303
|
+
* can be handed straight to a `FormData`. Preview URLs, upload status and progress live here.
|
|
304
|
+
*/
|
|
305
|
+
interface HubFileItem {
|
|
306
|
+
/** Stable id for the lifetime of the item; used by `remove`, `cancel` and `retry`. */
|
|
307
|
+
readonly id: string;
|
|
308
|
+
/** The underlying native file. */
|
|
309
|
+
readonly file: File;
|
|
310
|
+
/** Object URL of the thumbnail, for image files in a browser. `null` otherwise. */
|
|
311
|
+
readonly previewUrl: string | null;
|
|
312
|
+
/** Current lifecycle status. */
|
|
313
|
+
readonly status: HubFileStatus;
|
|
314
|
+
/**
|
|
315
|
+
* Upload progress from 0 to 100, or `null` when the total size is unknown — the case when the
|
|
316
|
+
* transport does not report a total (e.g. `HttpClient` emits `total: undefined`). A `null`
|
|
317
|
+
* progress must render as an indeterminate bar, never as 0%.
|
|
318
|
+
*/
|
|
319
|
+
readonly progress: number | null;
|
|
320
|
+
/** The error thrown by the uploader, when `status` is `'error'`. */
|
|
321
|
+
readonly error: unknown | null;
|
|
322
|
+
}
|
|
323
|
+
/** How the accepted files are previewed below the dropzone. */
|
|
324
|
+
type HubFilePreview = 'none' | 'list' | 'grid';
|
|
325
|
+
/** The active restrictions of a `<hub-file-input>`, handed to the `constraints` label. */
|
|
326
|
+
interface HubFileConstraints {
|
|
327
|
+
/** The `accept` specification, or `null` when everything is allowed. */
|
|
328
|
+
accept: string | null;
|
|
329
|
+
/** Maximum size per file in bytes, or `null`. */
|
|
330
|
+
maxSize: number | null;
|
|
331
|
+
/** Maximum number of files, or `null`. */
|
|
332
|
+
maxFiles: number | null;
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Localizable, overridable labels for `<hub-file-input>`.
|
|
336
|
+
*
|
|
337
|
+
* Set them globally through {@link provideHubForms}; they cover both visible text and the
|
|
338
|
+
* accessible names of the internal buttons.
|
|
339
|
+
*/
|
|
340
|
+
interface HubFileInputLabels {
|
|
341
|
+
/** Text of the button that opens the native file dialog. */
|
|
342
|
+
browse: string;
|
|
343
|
+
/** Invitation rendered inside the dropzone. */
|
|
344
|
+
dropHere: string;
|
|
345
|
+
/** Accessible name of the per-file remove button. */
|
|
346
|
+
remove: string;
|
|
347
|
+
/** Text + accessible name of the "remove all" button. */
|
|
348
|
+
clear: string;
|
|
349
|
+
/** Accessible name of the per-file retry button (uploader only). */
|
|
350
|
+
retry: string;
|
|
351
|
+
/** Accessible name of the per-file cancel button (uploader only). */
|
|
352
|
+
cancel: string;
|
|
353
|
+
/** Screen-reader summary of the current selection. */
|
|
354
|
+
filesSelected: (count: number) => string;
|
|
355
|
+
/** Renders a byte count as human-readable text. */
|
|
356
|
+
formatSize: (bytes: number) => string;
|
|
357
|
+
/** Renders the reason a file was refused; announced in the live region. */
|
|
358
|
+
rejection: (rejection: HubFileRejection) => string;
|
|
359
|
+
/** Renders the hint that summarizes the active restrictions under the dropzone. */
|
|
360
|
+
constraints: (constraints: HubFileConstraints) => string;
|
|
361
|
+
}
|
|
362
|
+
/** Built-in (English) file-input labels. */
|
|
363
|
+
declare const defaultHubFileInputLabels: HubFileInputLabels;
|
|
364
|
+
|
|
286
365
|
/**
|
|
287
366
|
* Global configuration contract for `ng-hub-ui-forms`.
|
|
288
367
|
*/
|
|
@@ -303,6 +382,8 @@ interface HubFormsConfig {
|
|
|
303
382
|
showValid: boolean;
|
|
304
383
|
/** Global datepicker defaults (locale labels, formats, first day of week…). */
|
|
305
384
|
datepicker: HubDatepickerConfig;
|
|
385
|
+
/** Global file-input labels (button text, accessible names, size and rejection formatting). */
|
|
386
|
+
fileInput: HubFileInputLabels;
|
|
306
387
|
}
|
|
307
388
|
/**
|
|
308
389
|
* Default configuration used when {@link provideHubForms} is not called.
|
|
@@ -338,6 +419,105 @@ type DeepPartial<T> = {
|
|
|
338
419
|
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
|
|
339
420
|
};
|
|
340
421
|
|
|
422
|
+
/**
|
|
423
|
+
* An event emitted while a single file is being uploaded.
|
|
424
|
+
*
|
|
425
|
+
* `progress` carries the raw `loaded`/`total` byte counts rather than a percentage, so a transport
|
|
426
|
+
* that does not know the total (`HttpClient` emits `total: undefined` when the request body is
|
|
427
|
+
* streamed) can say so with `total: null` instead of pretending the upload sits at 0%.
|
|
428
|
+
*/
|
|
429
|
+
type HubFileUploadEvent = {
|
|
430
|
+
status: 'progress';
|
|
431
|
+
loaded: number;
|
|
432
|
+
total: number | null;
|
|
433
|
+
} | {
|
|
434
|
+
status: 'done';
|
|
435
|
+
response?: unknown;
|
|
436
|
+
} | {
|
|
437
|
+
status: 'error';
|
|
438
|
+
error: unknown;
|
|
439
|
+
};
|
|
440
|
+
/**
|
|
441
|
+
* Contract every uploader must satisfy to plug into `<hub-file-input>`.
|
|
442
|
+
*
|
|
443
|
+
* The library ships the **mechanism**, never a transport: endpoints, field names, headers and retry
|
|
444
|
+
* policies belong to the application. Register an implementation with {@link provideHubFileUploader}.
|
|
445
|
+
*
|
|
446
|
+
* The returned observable **must be cold**: one subscription equals one request. `<hub-file-input>`
|
|
447
|
+
* cancels an upload by unsubscribing (which aborts the underlying `XMLHttpRequest` when the
|
|
448
|
+
* implementation is built on `HttpClient`) and retries it by re-subscribing. An uploader that
|
|
449
|
+
* returns a hot or shared observable silently breaks cancellation.
|
|
450
|
+
*
|
|
451
|
+
* @example
|
|
452
|
+
* ```ts
|
|
453
|
+
* @Injectable({ providedIn: 'root' })
|
|
454
|
+
* export class ApiFileUploader implements HubFileUploader {
|
|
455
|
+
* readonly #http = inject(HttpClient);
|
|
456
|
+
*
|
|
457
|
+
* upload(file: File): Observable<HubFileUploadEvent> {
|
|
458
|
+
* const body = new FormData();
|
|
459
|
+
* body.append('file', file);
|
|
460
|
+
*
|
|
461
|
+
* return this.#http.post('/api/files', body, { reportProgress: true, observe: 'events' }).pipe(
|
|
462
|
+
* map((event) => {
|
|
463
|
+
* if (event.type === HttpEventType.UploadProgress) {
|
|
464
|
+
* return { status: 'progress', loaded: event.loaded, total: event.total ?? null } as const;
|
|
465
|
+
* }
|
|
466
|
+
* if (event.type === HttpEventType.Response) {
|
|
467
|
+
* return { status: 'done', response: event.body } as const;
|
|
468
|
+
* }
|
|
469
|
+
* return null;
|
|
470
|
+
* }),
|
|
471
|
+
* filter((event) => event !== null),
|
|
472
|
+
* catchError((error) => of({ status: 'error', error } as const))
|
|
473
|
+
* );
|
|
474
|
+
* }
|
|
475
|
+
* }
|
|
476
|
+
* ```
|
|
477
|
+
*/
|
|
478
|
+
interface HubFileUploader {
|
|
479
|
+
/**
|
|
480
|
+
* Uploads a single file.
|
|
481
|
+
*
|
|
482
|
+
* @param file - The file to upload.
|
|
483
|
+
* @param context - The id of the {@link HubFileItem} the file belongs to, for correlation.
|
|
484
|
+
* @returns A cold observable emitting progress, then either `done` or `error`.
|
|
485
|
+
*/
|
|
486
|
+
upload(file: File, context: {
|
|
487
|
+
id: string;
|
|
488
|
+
}): Observable<HubFileUploadEvent>;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Injection token holding the {@link HubFileUploader} that `<hub-file-input>` delegates uploads to.
|
|
493
|
+
*
|
|
494
|
+
* It has **no default**: when nothing is registered, the component resolves it as `null` and behaves
|
|
495
|
+
* as a pure picker — no automatic upload, no progress bar, no cancel or retry. Register one with
|
|
496
|
+
* {@link provideHubFileUploader}.
|
|
497
|
+
*/
|
|
498
|
+
declare const HUB_FILE_UPLOADER: InjectionToken<HubFileUploader>;
|
|
499
|
+
/**
|
|
500
|
+
* Registers the uploader that `<hub-file-input>` uses to send files.
|
|
501
|
+
*
|
|
502
|
+
* The library defines the contract, not the transport: an uploader that knows your endpoint, field
|
|
503
|
+
* name, headers and retry policy is application code. Implement {@link HubFileUploader} there and
|
|
504
|
+
* hand it over here.
|
|
505
|
+
*
|
|
506
|
+
* Passing a class provides it in the same injector and aliases the token to that single instance, so
|
|
507
|
+
* the uploader can inject `HttpClient` and hold its own state.
|
|
508
|
+
*
|
|
509
|
+
* @param uploader - The uploader class (dependency-injected) or a ready-made instance.
|
|
510
|
+
* @returns Environment providers to add to `bootstrapApplication` (or a route's `providers`).
|
|
511
|
+
*
|
|
512
|
+
* @example
|
|
513
|
+
* ```ts
|
|
514
|
+
* bootstrapApplication(App, {
|
|
515
|
+
* providers: [provideHttpClient(), provideHubFileUploader(ApiFileUploader)]
|
|
516
|
+
* });
|
|
517
|
+
* ```
|
|
518
|
+
*/
|
|
519
|
+
declare function provideHubFileUploader(uploader: HubFileUploader | Type<HubFileUploader>): EnvironmentProviders;
|
|
520
|
+
|
|
341
521
|
/**
|
|
342
522
|
* Possible display types for form helper text.
|
|
343
523
|
*/
|
|
@@ -432,9 +612,13 @@ type HubInputValue = number | string | boolean | File | FileList | null;
|
|
|
432
612
|
* `invalidFeedbackTemplateFn` input, or projected `hubValidationError` templates.
|
|
433
613
|
*
|
|
434
614
|
* Formats: `text`, `number`, `password`, `email`, `tel`, `url`, `color`, `checkbox`, `switch`,
|
|
435
|
-
* `counter`. Label types: `stacked`, `floating`, `horizontal`. Text-like formats support
|
|
436
|
-
* append addons (input groups). Numeric formats auto-attach `min`/`max` validators when
|
|
437
|
-
* reactive control.
|
|
615
|
+
* `counter` and `file`. Label types: `stacked`, `floating`, `horizontal`. Text-like formats support
|
|
616
|
+
* prepend / append addons (input groups). Numeric formats auto-attach `min`/`max` validators when
|
|
617
|
+
* bound to a reactive control.
|
|
618
|
+
*
|
|
619
|
+
* The `file` format is **deprecated since 22.6.0** in favour of `<hub-file-input>`: it is a bare
|
|
620
|
+
* picker that cannot enforce `accept` on a drop, and has no size limits, no preview and no per-file
|
|
621
|
+
* removal. It keeps working until the next major.
|
|
438
622
|
*
|
|
439
623
|
* @example
|
|
440
624
|
* ```html
|
|
@@ -520,11 +704,24 @@ declare class HubInputComponent extends HubFieldControl {
|
|
|
520
704
|
readonly search: _angular_core.OutputEmitterRef<string>;
|
|
521
705
|
/** Clears any pending debounce timer when the component is destroyed. */
|
|
522
706
|
private readonly _searchCleanup;
|
|
523
|
-
/**
|
|
707
|
+
/**
|
|
708
|
+
* Accepted file types (file format), e.g. `image/*,.pdf`.
|
|
709
|
+
*
|
|
710
|
+
* @deprecated Since 22.6.0. Use `<hub-file-input>`, which enforces `accept` on drops and pastes
|
|
711
|
+
* too. Removed in the next major.
|
|
712
|
+
*/
|
|
524
713
|
readonly accept: _angular_core.InputSignal<string>;
|
|
525
|
-
/**
|
|
714
|
+
/**
|
|
715
|
+
* Whether multiple files can be selected (file format).
|
|
716
|
+
*
|
|
717
|
+
* @deprecated Since 22.6.0. Use `<hub-file-input>`. Removed in the next major.
|
|
718
|
+
*/
|
|
526
719
|
readonly multiple: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
527
|
-
/**
|
|
720
|
+
/**
|
|
721
|
+
* Text of the file-picker button (file format).
|
|
722
|
+
*
|
|
723
|
+
* @deprecated Since 22.6.0. Use `<hub-file-input>` and its `buttonLabel`. Removed in the next major.
|
|
724
|
+
*/
|
|
528
725
|
readonly buttonLabel: _angular_core.InputSignal<string>;
|
|
529
726
|
/** Reference to the hidden native file input. */
|
|
530
727
|
protected readonly fileInput: _angular_core.Signal<ElementRef<HTMLInputElement> | undefined>;
|
|
@@ -813,14 +1010,20 @@ declare class HubSegmentedComponent extends HubFieldControl {
|
|
|
813
1010
|
/** Visual density. */
|
|
814
1011
|
readonly size: _angular_core.InputSignal<HubSegmentedSize>;
|
|
815
1012
|
/**
|
|
816
|
-
*
|
|
817
|
-
*
|
|
818
|
-
*
|
|
819
|
-
*
|
|
820
|
-
*
|
|
821
|
-
*
|
|
1013
|
+
* Accent for the selected pill. Accepts ANY colour value:
|
|
1014
|
+
* - a built-in semantic name (`primary`, `success`, …) or any registered accent → resolves to
|
|
1015
|
+
* the matching `--hub-sys-color-*` design-system token;
|
|
1016
|
+
* - a literal colour (`#ff0000`, `rgb(...)`, `oklch(...)`, `rebeccapurple`) → used as-is.
|
|
1017
|
+
* Both the sliding indicator and the multiple-mode pill follow it, and the selected label gets a
|
|
1018
|
+
* derived contrast colour automatically. Empty string (default) keeps the neutral white-pill look.
|
|
822
1019
|
*/
|
|
823
1020
|
readonly color: _angular_core.InputSignal<string>;
|
|
1021
|
+
/**
|
|
1022
|
+
* Resolves {@link color} to a paintable accent for the `--hub-segmented-accent` slot: a bareword
|
|
1023
|
+
* becomes a `--hub-sys-color-*` token with the word as raw fallback (so named CSS colours work
|
|
1024
|
+
* too), while a literal `#hex` / `rgb()` / `oklch()` / `var()` is passed through unchanged.
|
|
1025
|
+
*/
|
|
1026
|
+
protected readonly accentVar: _angular_core.Signal<string | null>;
|
|
824
1027
|
/** Label text. */
|
|
825
1028
|
readonly label: _angular_core.InputSignal<string>;
|
|
826
1029
|
/** Label display type (`stacked`, `horizontal`). */
|
|
@@ -1272,6 +1475,304 @@ declare class HubDatepickerComponent extends HubFieldControl {
|
|
|
1272
1475
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubDatepickerComponent, "hub-datepicker", never, { "mode": { "alias": "mode"; "required": false; "isSignal": true; }; "label": { "alias": "label"; "required": false; "isSignal": true; }; "labelType": { "alias": "labelType"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "locale": { "alias": "locale"; "required": false; "isSignal": true; }; "firstDayOfWeek": { "alias": "firstDayOfWeek"; "required": false; "isSignal": true; }; "weekdayFormat": { "alias": "weekdayFormat"; "required": false; "isSignal": true; }; "displayFormat": { "alias": "displayFormat"; "required": false; "isSignal": true; }; "rangeSeparator": { "alias": "rangeSeparator"; "required": false; "isSignal": true; }; "min": { "alias": "min"; "required": false; "isSignal": true; }; "max": { "alias": "max"; "required": false; "isSignal": true; }; "disabledDates": { "alias": "disabledDates"; "required": false; "isSignal": true; }; "clearable": { "alias": "clearable"; "required": false; "isSignal": true; }; "showToday": { "alias": "showToday"; "required": false; "isSignal": true; }; "closeOnSelect": { "alias": "closeOnSelect"; "required": false; "isSignal": true; }; "labels": { "alias": "labels"; "required": false; "isSignal": true; }; "readonly": { "alias": "readonly"; "required": false; "isSignal": true; }; "formText": { "alias": "formText"; "required": false; "isSignal": true; }; "formTextType": { "alias": "formTextType"; "required": false; "isSignal": true; }; "classlist": { "alias": "classlist"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; "opened": "opened"; "closed": "closed"; "viewChange": "viewChange"; "cleared": "cleared"; }, never, never, true, never>;
|
|
1273
1476
|
}
|
|
1274
1477
|
|
|
1478
|
+
/** Context handed to a projected `hubFileIcon` template. */
|
|
1479
|
+
interface HubFileIconContext {
|
|
1480
|
+
/** The item whose icon is being rendered. */
|
|
1481
|
+
$implicit: HubFileItem;
|
|
1482
|
+
}
|
|
1483
|
+
/**
|
|
1484
|
+
* Overrides the glyph `<hub-file-input>` renders next to a non-image file.
|
|
1485
|
+
*
|
|
1486
|
+
* The library never depends on `ng-hub-ui-icons`: it draws a neutral document glyph from the
|
|
1487
|
+
* `--hub-file-input-file-icon` CSS token and lets you project anything richer — a `<hub-icon>` from
|
|
1488
|
+
* any pack, an inline `<svg>`, an emoji — through this template. The item is the implicit context,
|
|
1489
|
+
* so the glyph can vary with `file.type`.
|
|
1490
|
+
*
|
|
1491
|
+
* @example
|
|
1492
|
+
* ```html
|
|
1493
|
+
* <hub-file-input formControlName="attachments" [multiple]="true">
|
|
1494
|
+
* <ng-template hubFileIcon let-item>
|
|
1495
|
+
* <hub-icon [name]="item.file.type === 'application/pdf' ? 'fa:solid:file-pdf' : 'fa:solid:file'" />
|
|
1496
|
+
* </ng-template>
|
|
1497
|
+
* </hub-file-input>
|
|
1498
|
+
* ```
|
|
1499
|
+
*/
|
|
1500
|
+
declare class HubFileIconDirective {
|
|
1501
|
+
/** Template reference for the icon. */
|
|
1502
|
+
readonly template: TemplateRef<HubFileIconContext>;
|
|
1503
|
+
/**
|
|
1504
|
+
* Narrows the implicit context for the template type-checker.
|
|
1505
|
+
*
|
|
1506
|
+
* @param _directive - The directive instance.
|
|
1507
|
+
* @param _context - The candidate context.
|
|
1508
|
+
* @returns Always `true`; exists only to type `let-item`.
|
|
1509
|
+
*/
|
|
1510
|
+
static ngTemplateContextGuard(_directive: HubFileIconDirective, _context: unknown): _context is HubFileIconContext;
|
|
1511
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubFileIconDirective, never>;
|
|
1512
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<HubFileIconDirective, "[hubFileIcon]", never, {}, {}, never, never, true, never>;
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
/** Context handed to a projected `hubFilePreview` template. */
|
|
1516
|
+
interface HubFilePreviewContext {
|
|
1517
|
+
/** The item being rendered. */
|
|
1518
|
+
$implicit: HubFileItem;
|
|
1519
|
+
/** Removes this item from the selection (and cancels its upload, if any). */
|
|
1520
|
+
remove: () => void;
|
|
1521
|
+
/** Re-runs the upload of this item. No-op when no uploader is registered. */
|
|
1522
|
+
retry: () => void;
|
|
1523
|
+
/** Aborts the in-flight upload of this item. No-op when it is not uploading. */
|
|
1524
|
+
cancel: () => void;
|
|
1525
|
+
}
|
|
1526
|
+
/**
|
|
1527
|
+
* Replaces the entire rendering of a selected file in `<hub-file-input>`.
|
|
1528
|
+
*
|
|
1529
|
+
* Where `hubFileIcon` swaps a glyph, this takes over the whole row (or grid tile): thumbnail, name,
|
|
1530
|
+
* size, progress bar and buttons. The template receives the item plus the actions it needs, so a
|
|
1531
|
+
* custom preview keeps working removal, retry and cancel without reaching into the component.
|
|
1532
|
+
*
|
|
1533
|
+
* @example
|
|
1534
|
+
* ```html
|
|
1535
|
+
* <hub-file-input formControlName="attachments" [multiple]="true">
|
|
1536
|
+
* <ng-template hubFilePreview let-item let-remove="remove">
|
|
1537
|
+
* <article class="attachment">
|
|
1538
|
+
* <img *ngIf="item.previewUrl" [src]="item.previewUrl" alt="" />
|
|
1539
|
+
* <span>{{ item.file.name }}</span>
|
|
1540
|
+
* <button type="button" (click)="remove()">Remove</button>
|
|
1541
|
+
* </article>
|
|
1542
|
+
* </ng-template>
|
|
1543
|
+
* </hub-file-input>
|
|
1544
|
+
* ```
|
|
1545
|
+
*/
|
|
1546
|
+
declare class HubFilePreviewDirective {
|
|
1547
|
+
/** Template reference for the item. */
|
|
1548
|
+
readonly template: TemplateRef<HubFilePreviewContext>;
|
|
1549
|
+
/**
|
|
1550
|
+
* Narrows the context for the template type-checker.
|
|
1551
|
+
*
|
|
1552
|
+
* @param _directive - The directive instance.
|
|
1553
|
+
* @param _context - The candidate context.
|
|
1554
|
+
* @returns Always `true`; exists only to type `let-item` and the action bindings.
|
|
1555
|
+
*/
|
|
1556
|
+
static ngTemplateContextGuard(_directive: HubFilePreviewDirective, _context: unknown): _context is HubFilePreviewContext;
|
|
1557
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubFilePreviewDirective, never>;
|
|
1558
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<HubFilePreviewDirective, "[hubFilePreview]", never, {}, {}, never, never, true, never>;
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
/** The value a `<hub-file-input>` writes to its form control. */
|
|
1562
|
+
type HubFileValue = File | File[] | null;
|
|
1563
|
+
/**
|
|
1564
|
+
* Normalizes any file-shaped control value to a plain array.
|
|
1565
|
+
*
|
|
1566
|
+
* Accepts the shapes a control can realistically hold: a single `File` (single mode), an array of
|
|
1567
|
+
* files (multiple mode), a native `FileList` (a control fed straight from a DOM event or from the
|
|
1568
|
+
* deprecated `<hub-input type="file">`), or `null`/`undefined`.
|
|
1569
|
+
*
|
|
1570
|
+
* @param value - The raw control value.
|
|
1571
|
+
* @returns The files it contains, in order; an empty array when it holds none.
|
|
1572
|
+
*/
|
|
1573
|
+
declare function toFileArray(value: unknown): File[];
|
|
1574
|
+
|
|
1575
|
+
/**
|
|
1576
|
+
* Accessible file field with drag-and-drop, clipboard paste, per-file constraints, previews and
|
|
1577
|
+
* optional upload progress.
|
|
1578
|
+
*
|
|
1579
|
+
* A full `ng-hub-ui-forms` field: it extends {@link HubFieldControl}, so it binds with
|
|
1580
|
+
* `formControlName` / `ngModel` and shares the label, helper text and validation chrome with every
|
|
1581
|
+
* other control.
|
|
1582
|
+
*
|
|
1583
|
+
* The **form value stays native** — a `File` in single mode, a `File[]` in multiple mode, `null`
|
|
1584
|
+
* when empty — so it can be handed straight to a `FormData`. The rich per-file state (preview URL,
|
|
1585
|
+
* upload status, progress, error) lives in the {@link files} signal instead of contaminating the
|
|
1586
|
+
* control.
|
|
1587
|
+
*
|
|
1588
|
+
* Constraints declared as inputs (`accept`, `maxSize`, `minSize`, `maxTotalSize`, `maxFiles`) act as
|
|
1589
|
+
* a **filter**: an offending file never reaches the value and surfaces through {@link rejected}.
|
|
1590
|
+
* They are enforced by hand rather than delegated to the native `accept` attribute, which only
|
|
1591
|
+
* filters the operating-system dialog and is bypassed entirely by a drop or a paste. To make the
|
|
1592
|
+
* *control itself* invalid — the right choice when a value can also be patched in programmatically —
|
|
1593
|
+
* add the matching validators (`hubAcceptedFiles`, `hubMaxFileSize`, …).
|
|
1594
|
+
*
|
|
1595
|
+
* Uploading is opt-in and transport-agnostic: register a {@link HubFileUploader} with
|
|
1596
|
+
* `provideHubFileUploader()` and the component drives progress, cancel and retry. With no uploader
|
|
1597
|
+
* registered it is a pure picker.
|
|
1598
|
+
*
|
|
1599
|
+
* @example
|
|
1600
|
+
* ```html
|
|
1601
|
+
* <hub-file-input
|
|
1602
|
+
* formControlName="attachments"
|
|
1603
|
+
* label="Attachments"
|
|
1604
|
+
* [multiple]="true"
|
|
1605
|
+
* accept="image/*,.pdf"
|
|
1606
|
+
* [maxSize]="5 * 1024 * 1024"
|
|
1607
|
+
* [maxFiles]="3"
|
|
1608
|
+
* preview="grid"
|
|
1609
|
+
* (rejected)="notify($event)"
|
|
1610
|
+
* />
|
|
1611
|
+
* ```
|
|
1612
|
+
*/
|
|
1613
|
+
declare class HubFileInputComponent extends HubFieldControl {
|
|
1614
|
+
#private;
|
|
1615
|
+
protected readonly _formTextTypes: typeof FormTextTypes;
|
|
1616
|
+
protected readonly _items: _angular_core.WritableSignal<HubFileItem[]>;
|
|
1617
|
+
/** Releases every object URL and aborts every in-flight upload when the field goes away. */
|
|
1618
|
+
private readonly _cleanup;
|
|
1619
|
+
/** Label text. */
|
|
1620
|
+
readonly label: _angular_core.InputSignal<string>;
|
|
1621
|
+
/** Whether more than one file can be held. Switches the control value to `File[]`. */
|
|
1622
|
+
readonly multiple: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
1623
|
+
/** Accepted file types, e.g. `image/*,.pdf`. Enforced on drop and paste, not just in the dialog. */
|
|
1624
|
+
readonly accept: _angular_core.InputSignal<string>;
|
|
1625
|
+
/** Maximum size per file, in bytes. */
|
|
1626
|
+
readonly maxSize: _angular_core.InputSignal<number | null>;
|
|
1627
|
+
/** Minimum size per file, in bytes. Rejects the 0-byte files a failed export produces. */
|
|
1628
|
+
readonly minSize: _angular_core.InputSignal<number | null>;
|
|
1629
|
+
/** Maximum combined size of every held file, in bytes. */
|
|
1630
|
+
readonly maxTotalSize: _angular_core.InputSignal<number | null>;
|
|
1631
|
+
/** Maximum number of files. Only meaningful with `multiple`. */
|
|
1632
|
+
readonly maxFiles: _angular_core.InputSignal<number | null>;
|
|
1633
|
+
/** Whether files can be dropped onto the field. */
|
|
1634
|
+
readonly dragDrop: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
1635
|
+
/** Whether files can be pasted into the focused field (e.g. a screenshot). */
|
|
1636
|
+
readonly paste: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
1637
|
+
/** How the held files are rendered: not at all, as a list, or as a thumbnail grid. */
|
|
1638
|
+
readonly preview: _angular_core.InputSignal<HubFilePreview>;
|
|
1639
|
+
/** Whether the same file can be selected twice (keyed on name, size and last-modified date). */
|
|
1640
|
+
readonly allowDuplicates: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
1641
|
+
/** Opens the device camera instead of the file browser, on the platforms that support it. */
|
|
1642
|
+
readonly capture: _angular_core.InputSignal<"user" | "environment" | null>;
|
|
1643
|
+
/** Whether a newly accepted file starts uploading immediately. Ignored with no uploader registered. */
|
|
1644
|
+
readonly autoUpload: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
1645
|
+
/** Overrides the "browse" button text coming from the global labels. */
|
|
1646
|
+
readonly buttonLabel: _angular_core.InputSignal<string | null>;
|
|
1647
|
+
/** Overrides the auto-generated hint that summarizes the active constraints. Pass `''` to hide it. */
|
|
1648
|
+
readonly hint: _angular_core.InputSignal<string | null>;
|
|
1649
|
+
/** Helper text shown below the control. */
|
|
1650
|
+
readonly formText: _angular_core.InputSignal<string>;
|
|
1651
|
+
/** Helper text placement. Only `bottom` is supported. */
|
|
1652
|
+
readonly formTextType: _angular_core.InputSignal<FormTextType>;
|
|
1653
|
+
/** Extra CSS classes applied to the host element. */
|
|
1654
|
+
readonly classlist: _angular_core.InputSignal<string>;
|
|
1655
|
+
/** Emits the native value whenever the selection changes. */
|
|
1656
|
+
readonly valueChange: _angular_core.OutputEmitterRef<HubFileValue>;
|
|
1657
|
+
/** Emits the files refused by the declared constraints, with the reason for each. */
|
|
1658
|
+
readonly rejected: _angular_core.OutputEmitterRef<HubFileRejection[]>;
|
|
1659
|
+
/** Emits the file removed from the selection. */
|
|
1660
|
+
readonly fileRemoved: _angular_core.OutputEmitterRef<File>;
|
|
1661
|
+
/** Emits the full item list whenever an upload changes status or progress. */
|
|
1662
|
+
readonly uploadStateChange: _angular_core.OutputEmitterRef<readonly HubFileItem[]>;
|
|
1663
|
+
/** The hidden native file input, kept focusable so the dropzone label activates it. */
|
|
1664
|
+
protected readonly nativeInput: _angular_core.Signal<ElementRef<HTMLInputElement> | undefined>;
|
|
1665
|
+
/** Projected per-file icon template. */
|
|
1666
|
+
protected readonly iconTpt: _angular_core.Signal<HubFileIconDirective | undefined>;
|
|
1667
|
+
/** Projected per-file preview template, replacing the built-in item rendering. */
|
|
1668
|
+
protected readonly previewTpt: _angular_core.Signal<HubFilePreviewDirective | undefined>;
|
|
1669
|
+
/** Whether a drag is currently hovering the dropzone. */
|
|
1670
|
+
protected readonly isDragging: _angular_core.WritableSignal<boolean>;
|
|
1671
|
+
/** Latest message for the screen-reader live region. */
|
|
1672
|
+
protected readonly announcement: _angular_core.WritableSignal<string>;
|
|
1673
|
+
/** The rich, per-file state of the current selection. */
|
|
1674
|
+
readonly files: _angular_core.Signal<HubFileItem[]>;
|
|
1675
|
+
/** Whether at least one file is currently uploading. Gate a submit button on this. */
|
|
1676
|
+
readonly uploading: _angular_core.Signal<boolean>;
|
|
1677
|
+
/** Whether an uploader is registered, which is what enables progress, cancel and retry. */
|
|
1678
|
+
protected readonly hasUploader: boolean;
|
|
1679
|
+
/** The resolved, localizable labels. */
|
|
1680
|
+
protected readonly labels: _angular_core.Signal<ng_hub_ui_forms.HubFileInputLabels>;
|
|
1681
|
+
/** Text of the browse action. */
|
|
1682
|
+
protected readonly browseLabel: _angular_core.Signal<string>;
|
|
1683
|
+
/** The hint summarizing the active constraints. */
|
|
1684
|
+
protected readonly constraintsHint: _angular_core.Signal<string>;
|
|
1685
|
+
/** Whether the dropzone currently accepts a drop. */
|
|
1686
|
+
protected readonly dropEnabled: _angular_core.Signal<boolean>;
|
|
1687
|
+
/**
|
|
1688
|
+
* Derives the native validation errors from the held files rather than from the DOM.
|
|
1689
|
+
*
|
|
1690
|
+
* The hidden native input is emptied after every `change` so the same file can be picked twice,
|
|
1691
|
+
* and it never sees a dropped or pasted file at all. Its `validity` therefore reports
|
|
1692
|
+
* `valueMissing` even when files are held — reading it would mark a satisfied field as required.
|
|
1693
|
+
*
|
|
1694
|
+
* @param _target - Ignored; the file state is the source of truth.
|
|
1695
|
+
*/
|
|
1696
|
+
protected updateNativeErrors(_target?: EventTarget | null): void;
|
|
1697
|
+
/**
|
|
1698
|
+
* Resolves a human-readable message for a failed upload.
|
|
1699
|
+
*
|
|
1700
|
+
* @param item - The item in the `error` state.
|
|
1701
|
+
* @returns The error message.
|
|
1702
|
+
*/
|
|
1703
|
+
protected errorText(item: HubFileItem): string;
|
|
1704
|
+
writeValue(value: HubFileValue | FileList): void;
|
|
1705
|
+
/** Opens the native file dialog. */
|
|
1706
|
+
open(): void;
|
|
1707
|
+
/**
|
|
1708
|
+
* Removes a file from the selection, aborting its upload and releasing its preview.
|
|
1709
|
+
*
|
|
1710
|
+
* @param id - The id of the item to remove.
|
|
1711
|
+
*/
|
|
1712
|
+
remove(id: string): void;
|
|
1713
|
+
/** Removes every file, aborting any upload in flight. */
|
|
1714
|
+
clear(): void;
|
|
1715
|
+
/** Uploads every file that has not been uploaded yet. No-op without a registered uploader. */
|
|
1716
|
+
upload(): void;
|
|
1717
|
+
/**
|
|
1718
|
+
* Aborts an in-flight upload, returning the file to the `ready` state.
|
|
1719
|
+
*
|
|
1720
|
+
* @param id - The id of the uploading item.
|
|
1721
|
+
*/
|
|
1722
|
+
cancel(id: string): void;
|
|
1723
|
+
/**
|
|
1724
|
+
* Re-runs the upload of a file, typically after a failure.
|
|
1725
|
+
*
|
|
1726
|
+
* @param id - The id of the item to upload again.
|
|
1727
|
+
*/
|
|
1728
|
+
retry(id: string): void;
|
|
1729
|
+
/**
|
|
1730
|
+
* Reads the files chosen through the native dialog.
|
|
1731
|
+
*
|
|
1732
|
+
* @param event - The `change` event of the hidden native input.
|
|
1733
|
+
*/
|
|
1734
|
+
protected handleNativeChange(event: Event): void;
|
|
1735
|
+
/**
|
|
1736
|
+
* Accepts files dropped onto the dropzone.
|
|
1737
|
+
*
|
|
1738
|
+
* @param event - The drop event.
|
|
1739
|
+
*/
|
|
1740
|
+
protected handleDrop(event: DragEvent): void;
|
|
1741
|
+
/**
|
|
1742
|
+
* Highlights the dropzone once a drag carrying files enters it.
|
|
1743
|
+
*
|
|
1744
|
+
* @param event - The dragenter event.
|
|
1745
|
+
*/
|
|
1746
|
+
protected handleDragEnter(event: DragEvent): void;
|
|
1747
|
+
/**
|
|
1748
|
+
* Keeps the drop target alive. A `dragover` that does not call `preventDefault` refuses the drop.
|
|
1749
|
+
*
|
|
1750
|
+
* @param event - The dragover event.
|
|
1751
|
+
*/
|
|
1752
|
+
protected handleDragOver(event: DragEvent): void;
|
|
1753
|
+
/**
|
|
1754
|
+
* Un-highlights the dropzone, but only once the drag has left it *and* all of its children.
|
|
1755
|
+
*
|
|
1756
|
+
* @param event - The dragleave event.
|
|
1757
|
+
*/
|
|
1758
|
+
protected handleDragLeave(event: DragEvent): void;
|
|
1759
|
+
/**
|
|
1760
|
+
* Accepts files pasted into the focused field, e.g. a screenshot from the clipboard.
|
|
1761
|
+
*
|
|
1762
|
+
* @param event - The paste event.
|
|
1763
|
+
*/
|
|
1764
|
+
protected handlePaste(event: ClipboardEvent): void;
|
|
1765
|
+
/**
|
|
1766
|
+
* Builds the context handed to a projected `hubFilePreview` template.
|
|
1767
|
+
*
|
|
1768
|
+
* @param item - The item being rendered.
|
|
1769
|
+
* @returns The template context, complete with the actions the item needs.
|
|
1770
|
+
*/
|
|
1771
|
+
protected previewContext(item: HubFileItem): HubFilePreviewContext;
|
|
1772
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<HubFileInputComponent, never>;
|
|
1773
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<HubFileInputComponent, "hub-file-input", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "multiple": { "alias": "multiple"; "required": false; "isSignal": true; }; "accept": { "alias": "accept"; "required": false; "isSignal": true; }; "maxSize": { "alias": "maxSize"; "required": false; "isSignal": true; }; "minSize": { "alias": "minSize"; "required": false; "isSignal": true; }; "maxTotalSize": { "alias": "maxTotalSize"; "required": false; "isSignal": true; }; "maxFiles": { "alias": "maxFiles"; "required": false; "isSignal": true; }; "dragDrop": { "alias": "dragDrop"; "required": false; "isSignal": true; }; "paste": { "alias": "paste"; "required": false; "isSignal": true; }; "preview": { "alias": "preview"; "required": false; "isSignal": true; }; "allowDuplicates": { "alias": "allowDuplicates"; "required": false; "isSignal": true; }; "capture": { "alias": "capture"; "required": false; "isSignal": true; }; "autoUpload": { "alias": "autoUpload"; "required": false; "isSignal": true; }; "buttonLabel": { "alias": "buttonLabel"; "required": false; "isSignal": true; }; "hint": { "alias": "hint"; "required": false; "isSignal": true; }; "formText": { "alias": "formText"; "required": false; "isSignal": true; }; "formTextType": { "alias": "formTextType"; "required": false; "isSignal": true; }; "classlist": { "alias": "classlist"; "required": false; "isSignal": true; }; }, { "valueChange": "valueChange"; "rejected": "rejected"; "fileRemoved": "fileRemoved"; "uploadStateChange": "uploadStateChange"; }, ["iconTpt", "previewTpt"], never, true, never>;
|
|
1774
|
+
}
|
|
1775
|
+
|
|
1275
1776
|
declare class NgOptionComponent implements OnInit {
|
|
1276
1777
|
readonly value: _angular_core.InputSignal<any>;
|
|
1277
1778
|
readonly disabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
@@ -1531,6 +2032,157 @@ declare class HubUcfirstPipe implements PipeTransform {
|
|
|
1531
2032
|
*/
|
|
1532
2033
|
declare function hubAreEqual(primaryControlName: string, secondaryControlName: string): ValidatorFn;
|
|
1533
2034
|
|
|
2035
|
+
/**
|
|
2036
|
+
* Validates that every file held by the control matches an `accept` specification.
|
|
2037
|
+
*
|
|
2038
|
+
* Complements the `accept` input of `<hub-file-input>`, which *filters* offending files before they
|
|
2039
|
+
* reach the value. This validator instead makes the control **invalid**, which is what you want when
|
|
2040
|
+
* files can also arrive from outside the component (patched value, restored draft, another control).
|
|
2041
|
+
*
|
|
2042
|
+
* Sets the `fileAccept` error with `{ accept, files }`, where `files` lists the offending names.
|
|
2043
|
+
* An empty control is valid — pair it with `Validators.required` to demand a file.
|
|
2044
|
+
*
|
|
2045
|
+
* @param accept - The accept specification, e.g. `'image/*,.pdf'`.
|
|
2046
|
+
* @returns A validator function for a file-valued control.
|
|
2047
|
+
*
|
|
2048
|
+
* @example
|
|
2049
|
+
* ```ts
|
|
2050
|
+
* new FormControl<File[]>([], [hubAcceptedFiles('image/*,.pdf')]);
|
|
2051
|
+
* ```
|
|
2052
|
+
*/
|
|
2053
|
+
declare function hubAcceptedFiles(accept: string): ValidatorFn;
|
|
2054
|
+
|
|
2055
|
+
/**
|
|
2056
|
+
* Validates that no file held by the control exceeds a maximum size.
|
|
2057
|
+
*
|
|
2058
|
+
* Sets the `fileMaxSize` error with `{ max, actual, files }`, where `actual` is the size of the
|
|
2059
|
+
* largest offending file and `files` lists the offending names. An empty control is valid.
|
|
2060
|
+
*
|
|
2061
|
+
* @param maxBytes - The maximum size per file, in bytes.
|
|
2062
|
+
* @returns A validator function for a file-valued control.
|
|
2063
|
+
*
|
|
2064
|
+
* @example
|
|
2065
|
+
* ```ts
|
|
2066
|
+
* new FormControl<File | null>(null, [hubMaxFileSize(5 * 1024 * 1024)]);
|
|
2067
|
+
* ```
|
|
2068
|
+
*/
|
|
2069
|
+
declare function hubMaxFileSize(maxBytes: number): ValidatorFn;
|
|
2070
|
+
|
|
2071
|
+
/**
|
|
2072
|
+
* Validates that no file held by the control falls below a minimum size.
|
|
2073
|
+
*
|
|
2074
|
+
* Useful to reject empty or truncated uploads (a 0-byte file is a common symptom of a failed export).
|
|
2075
|
+
* Sets the `fileMinSize` error with `{ min, actual, files }`, where `actual` is the size of the
|
|
2076
|
+
* smallest offending file. An empty control is valid.
|
|
2077
|
+
*
|
|
2078
|
+
* @param minBytes - The minimum size per file, in bytes.
|
|
2079
|
+
* @returns A validator function for a file-valued control.
|
|
2080
|
+
*
|
|
2081
|
+
* @example
|
|
2082
|
+
* ```ts
|
|
2083
|
+
* new FormControl<File | null>(null, [hubMinFileSize(1)]);
|
|
2084
|
+
* ```
|
|
2085
|
+
*/
|
|
2086
|
+
declare function hubMinFileSize(minBytes: number): ValidatorFn;
|
|
2087
|
+
|
|
2088
|
+
/**
|
|
2089
|
+
* Validates that the combined size of every file held by the control stays within a budget.
|
|
2090
|
+
*
|
|
2091
|
+
* This is the constraint a request-body limit actually enforces, and it is not implied by a
|
|
2092
|
+
* per-file maximum: ten files of 2 MB pass `hubMaxFileSize(5 MB)` and still blow a 10 MB request.
|
|
2093
|
+
*
|
|
2094
|
+
* Sets the `fileMaxTotalSize` error with `{ max, actual }`. An empty control is valid.
|
|
2095
|
+
*
|
|
2096
|
+
* @param maxBytes - The maximum combined size, in bytes.
|
|
2097
|
+
* @returns A validator function for a file-valued control.
|
|
2098
|
+
*
|
|
2099
|
+
* @example
|
|
2100
|
+
* ```ts
|
|
2101
|
+
* new FormControl<File[]>([], [hubMaxTotalSize(20 * 1024 * 1024)]);
|
|
2102
|
+
* ```
|
|
2103
|
+
*/
|
|
2104
|
+
declare function hubMaxTotalSize(maxBytes: number): ValidatorFn;
|
|
2105
|
+
|
|
2106
|
+
/**
|
|
2107
|
+
* Validates that the control holds at most `max` files.
|
|
2108
|
+
*
|
|
2109
|
+
* Sets the `fileMaxFiles` error with `{ max, actual }`. An empty control is valid.
|
|
2110
|
+
*
|
|
2111
|
+
* @param max - The maximum number of files.
|
|
2112
|
+
* @returns A validator function for a file-valued control.
|
|
2113
|
+
*
|
|
2114
|
+
* @example
|
|
2115
|
+
* ```ts
|
|
2116
|
+
* new FormControl<File[]>([], [hubMaxFiles(3)]);
|
|
2117
|
+
* ```
|
|
2118
|
+
*/
|
|
2119
|
+
declare function hubMaxFiles(max: number): ValidatorFn;
|
|
2120
|
+
|
|
2121
|
+
/**
|
|
2122
|
+
* Validates that the control holds at least `min` files.
|
|
2123
|
+
*
|
|
2124
|
+
* Unlike the other file validators, this one **does** reject an empty control: holding zero files
|
|
2125
|
+
* is precisely what a minimum forbids. It therefore subsumes `Validators.required`, and adding both
|
|
2126
|
+
* only produces two errors for the same cause.
|
|
2127
|
+
*
|
|
2128
|
+
* Sets the `fileMinFiles` error with `{ min, actual }`.
|
|
2129
|
+
*
|
|
2130
|
+
* @param min - The minimum number of files.
|
|
2131
|
+
* @returns A validator function for a file-valued control.
|
|
2132
|
+
*
|
|
2133
|
+
* @example
|
|
2134
|
+
* ```ts
|
|
2135
|
+
* new FormControl<File[]>([], [hubMinFiles(2)]);
|
|
2136
|
+
* ```
|
|
2137
|
+
*/
|
|
2138
|
+
declare function hubMinFiles(min: number): ValidatorFn;
|
|
2139
|
+
|
|
2140
|
+
/**
|
|
2141
|
+
* Formats a byte count as human-readable text using binary multiples (1 KB = 1024 B).
|
|
2142
|
+
*
|
|
2143
|
+
* Values below 10 in their unit keep one decimal (`1.4 MB`); larger ones are rounded (`24 MB`).
|
|
2144
|
+
* The decimal separator follows the given locale, or the runtime's default when omitted.
|
|
2145
|
+
*
|
|
2146
|
+
* @param bytes - The size in bytes.
|
|
2147
|
+
* @param locale - BCP 47 locale used to format the number. Defaults to the runtime locale.
|
|
2148
|
+
* @returns The formatted size, or an empty string when `bytes` is not a finite, non-negative number.
|
|
2149
|
+
*/
|
|
2150
|
+
declare function formatFileSize(bytes: number, locale?: string): string;
|
|
2151
|
+
|
|
2152
|
+
/**
|
|
2153
|
+
* Tests a file against an `accept` specification.
|
|
2154
|
+
*
|
|
2155
|
+
* The native `accept` attribute only filters the operating-system file dialog: files arriving by
|
|
2156
|
+
* drag-and-drop or paste bypass it entirely. This function applies the same rules by hand, so a
|
|
2157
|
+
* dropped file is held to the constraint the consumer declared.
|
|
2158
|
+
*
|
|
2159
|
+
* Supported tokens, comma-separated, matched case-insensitively:
|
|
2160
|
+
* - an extension — `.pdf`
|
|
2161
|
+
* - a wildcard MIME type — `image/*`
|
|
2162
|
+
* - an exact MIME type — `application/pdf`
|
|
2163
|
+
* - the catch-alls `*` and `*/*`
|
|
2164
|
+
*
|
|
2165
|
+
* Note that a MIME token can never match a file the browser could not type (`file.type === ''`,
|
|
2166
|
+
* common for unusual extensions); use an extension token for those.
|
|
2167
|
+
*
|
|
2168
|
+
* @param file - The file to test.
|
|
2169
|
+
* @param accept - The `accept` specification. Empty or `*` accepts everything.
|
|
2170
|
+
* @returns `true` when the file satisfies at least one token.
|
|
2171
|
+
*/
|
|
2172
|
+
declare function matchesAccept(file: File, accept: string): boolean;
|
|
2173
|
+
|
|
2174
|
+
/**
|
|
2175
|
+
* Builds the identity key used to detect duplicate selections.
|
|
2176
|
+
*
|
|
2177
|
+
* Two `File` objects are never referentially equal across separate drops, so identity is derived
|
|
2178
|
+
* from the tuple the browser exposes: name, byte size and last-modified timestamp. Collisions are
|
|
2179
|
+
* possible in theory (same name, size and mtime) but describe the same file in every practical case.
|
|
2180
|
+
*
|
|
2181
|
+
* @param file - The file to key.
|
|
2182
|
+
* @returns A stable string key for the file.
|
|
2183
|
+
*/
|
|
2184
|
+
declare function fileKey(file: File): string;
|
|
2185
|
+
|
|
1534
2186
|
/**
|
|
1535
2187
|
* Checks if a value is a string.
|
|
1536
2188
|
*
|
|
@@ -1709,5 +2361,5 @@ interface HubFormControlAdapter {
|
|
|
1709
2361
|
*/
|
|
1710
2362
|
declare const hubFormControlAdapter: HubFormControlAdapter;
|
|
1711
2363
|
|
|
1712
|
-
export { FormTextTypes, HUB_FORMS_CONFIG, HubAutoresizeDirective, HubDatepickerComponent, HubFieldControl, HubFieldsetComponent, HubFormComponent, HubFormControl, HubFormTextDirective, HubGroupControl, HubInputComponent, HubInputFormats, HubInputPrefixDirective, HubInputSuffixDirective, HubInvertColorPipe, HubJoinButLastPipe, HubLabelTypes, HubLegendComponent, HubLegendDirective, HubMapPipe, HubOtpInputComponent, HubSafeUrlPipe, HubSegmentedComponent, HubSelectComponent, HubSelectFormats, HubSliderComponent, HubSnakeUpperPipe, HubTextareaComponent, HubUcfirstPipe, HubValidationErrorDirective, NgClearButtonTemplateDirective, NgFooterTemplateDirective, NgHeaderTemplateDirective, NgLabelTemplateDirective, NgLoadingSpinnerTemplateDirective, NgLoadingTextTemplateDirective, NgMultiLabelTemplateDirective, NgNotFoundTemplateDirective, NgOptgroupTemplateDirective, NgOptionComponent, NgOptionTemplateDirective, NgSelectConfig, NgTagTemplateDirective, NgTypeToSearchTemplateDirective, applyMask, areEqual, camelToSnakeUpper, controlHasMinOrMaxValidator, defaultHubDatepickerConfig, defaultHubDatepickerLabels, defaultHubFormsConfig, defaultInvalidFeedback, get, getActiveElement, getMinOrMaxValueFromValidator, hubAreEqual, hubFormControlAdapter, isDefined, isMaskActive, isString, joinButLast, provideHubForms, runInZone, uuid };
|
|
1713
|
-
export type { FormTextType, HubDateRange, HubDateValue, HubDatepickerConfig, HubDatepickerLabels, HubDatepickerMode, HubFormControlAdapter, HubFormControlConfig, HubFormControlHandle, HubFormControlOption, HubFormsConfig, HubGroupErrorTrigger, HubInputFormat, HubLabelType, HubMaskResult, HubOtpMode, HubSegmentedOption, HubSegmentedSize, HubSelectFormat, HubSliderValue };
|
|
2364
|
+
export { FormTextTypes, HUB_FILE_UPLOADER, HUB_FORMS_CONFIG, HubAutoresizeDirective, HubDatepickerComponent, HubFieldControl, HubFieldsetComponent, HubFileIconDirective, HubFileInputComponent, HubFilePreviewDirective, HubFormComponent, HubFormControl, HubFormTextDirective, HubGroupControl, HubInputComponent, HubInputFormats, HubInputPrefixDirective, HubInputSuffixDirective, HubInvertColorPipe, HubJoinButLastPipe, HubLabelTypes, HubLegendComponent, HubLegendDirective, HubMapPipe, HubOtpInputComponent, HubSafeUrlPipe, HubSegmentedComponent, HubSelectComponent, HubSelectFormats, HubSliderComponent, HubSnakeUpperPipe, HubTextareaComponent, HubUcfirstPipe, HubValidationErrorDirective, NgClearButtonTemplateDirective, NgFooterTemplateDirective, NgHeaderTemplateDirective, NgLabelTemplateDirective, NgLoadingSpinnerTemplateDirective, NgLoadingTextTemplateDirective, NgMultiLabelTemplateDirective, NgNotFoundTemplateDirective, NgOptgroupTemplateDirective, NgOptionComponent, NgOptionTemplateDirective, NgSelectConfig, NgTagTemplateDirective, NgTypeToSearchTemplateDirective, applyMask, areEqual, camelToSnakeUpper, controlHasMinOrMaxValidator, defaultHubDatepickerConfig, defaultHubDatepickerLabels, defaultHubFileInputLabels, defaultHubFormsConfig, defaultInvalidFeedback, fileKey, formatFileSize, get, getActiveElement, getMinOrMaxValueFromValidator, hubAcceptedFiles, hubAreEqual, hubFormControlAdapter, hubMaxFileSize, hubMaxFiles, hubMaxTotalSize, hubMinFileSize, hubMinFiles, isDefined, isMaskActive, isString, joinButLast, matchesAccept, provideHubFileUploader, provideHubForms, runInZone, toFileArray, uuid };
|
|
2365
|
+
export type { FormTextType, HubDateRange, HubDateValue, HubDatepickerConfig, HubDatepickerLabels, HubDatepickerMode, HubFileConstraints, HubFileIconContext, HubFileInputLabels, HubFileItem, HubFilePreview, HubFilePreviewContext, HubFileRejection, HubFileRejectionReason, HubFileStatus, HubFileUploadEvent, HubFileUploader, HubFileValue, HubFormControlAdapter, HubFormControlConfig, HubFormControlHandle, HubFormControlOption, HubFormsConfig, HubGroupErrorTrigger, HubInputFormat, HubLabelType, HubMaskResult, HubOtpMode, HubSegmentedOption, HubSegmentedSize, HubSelectFormat, HubSliderValue };
|