@skyux/forms 11.0.0-alpha.15 → 11.0.0-alpha.16

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.
@@ -16,7 +16,7 @@ import * as i1$2 from '@skyux/indicators';
16
16
  import { SkyStatusIndicatorModule } from '@skyux/indicators';
17
17
  import * as i4$1 from '@skyux/theme';
18
18
  import { SkyThemeComponentClassDirective, SkyThemeModule } from '@skyux/theme';
19
- import { BehaviorSubject, Subject, ReplaySubject } from 'rxjs';
19
+ import { BehaviorSubject, Subject, ReplaySubject, takeUntil as takeUntil$1 } from 'rxjs';
20
20
  import { takeUntil, take } from 'rxjs/operators';
21
21
  import { coerceNumberProperty, coerceBooleanProperty } from '@angular/cdk/coercion';
22
22
 
@@ -80,7 +80,7 @@ const RESOURCES = {
80
80
  skyux_file_attachment_button_label_replace_file_label: {
81
81
  message: 'Replace file {0} for',
82
82
  },
83
- skyux_file_attachment_file_item_delete: { message: 'Delete file' },
83
+ skyux_file_attachment_file_item_delete: { message: 'Delete {0}' },
84
84
  skyux_file_attachment_file_item_remove: { message: 'Remove file {0} for' },
85
85
  skyux_file_attachment_file_size_b_plural: { message: '{0} bytes' },
86
86
  skyux_file_attachment_file_size_b_singular: { message: '{0} byte' },
@@ -2397,11 +2397,11 @@ class SkyFileItemComponent {
2397
2397
  }
2398
2398
  }
2399
2399
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: SkyFileItemComponent, deps: [{ token: i0.KeyValueDiffers }, { token: SkyFileItemService }], target: i0.ɵɵFactoryTarget.Component }); }
2400
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.2", type: SkyFileItemComponent, isStandalone: true, selector: "sky-file-item", inputs: { fileItem: "fileItem" }, outputs: { deleteFile: "deleteFile" }, ngImport: i0, template: "@if (fileItem) {\n <div class=\"sky-file-item sky-padding-even-default\">\n <div class=\"sky-file-item-title\">\n <div class=\"sky-file-item-name-container\">\n <div class=\"sky-file-item-name\">\n @if (isFile) {\n <strong>{{ fileName }}</strong>\n } @else {\n <strong>{{ url }}</strong>\n }\n </div>\n @if (isFile) {\n <div class=\"sky-file-item-size\">({{ fileSize | skyFileSize }})</div>\n }\n </div>\n <div class=\"sky-file-item-controls\">\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-file-item-btn-delete\"\n [attr.aria-label]=\"\n 'skyux_file_attachment_file_item_delete' | skyLibResources\n \"\n (click)=\"itemDelete()\"\n >\n <sky-icon icon=\"trash-o\" size=\"lg\" />\n </button>\n </div>\n </div>\n <div class=\"sky-file-item-content\">\n <div class=\"sky-file-item-preview\">\n @if (isImage) {\n <div class=\"sky-file-item-preview-img-container\">\n <img\n class=\"sky-file-item-preview-img\"\n [src]=\"url\"\n [alt]=\"\n 'skyux_file_attachment_file_upload_image_preview_alt_text'\n | skyLibResources\n \"\n />\n </div>\n } @else {\n <div class=\"sky-file-item-preview-other\">\n <sky-icon [icon]=\"icon\" />\n </div>\n }\n </div>\n <div class=\"sky-file-item-content-custom\">\n <ng-content />\n </div>\n </div>\n </div>\n}\n", styles: [".sky-file-item{border-top:1px solid #e2e3e4;border-bottom:1px solid #e2e3e4;border-left:1px solid #e2e3e4;border-right:1px solid #e2e3e4;background-color:#eeeeef;margin-bottom:10px}.sky-file-item-name-container{flex:1 1 auto;overflow:hidden}.sky-file-item-controls{flex:0 1 auto;padding-left:15px}.sky-file-item-name{white-space:nowrap;overflow:hidden;-ms-text-overflow:ellipsis;-o-text-overflow:ellipsis;text-overflow:ellipsis}.sky-file-item-title{margin-bottom:10px;display:flex}.sky-file-item-content{display:flex}.sky-file-item-preview{flex-basis:25%}.sky-file-item-content-custom{flex-basis:75%}.sky-file-item-preview-img-container{text-align:center}.sky-file-item-preview-img{max-width:100%;height:auto;box-shadow:0 0 5px #666}.sky-file-item-preview-other{color:#686c73;font-size:100px;line-height:1;text-align:center;width:100%}\n"], dependencies: [{ kind: "pipe", type: SkyFileSizePipe, name: "skyFileSize" }, { kind: "ngmodule", type: SkyFormsResourcesModule }, { kind: "pipe", type: i1$1.SkyLibResourcesPipe, name: "skyLibResources" }, { kind: "ngmodule", type: SkyIconModule }, { kind: "component", type: i5.λ1, selector: "sky-icon", inputs: ["icon", "iconName", "iconType", "size", "fixedWidth", "variant"] }] }); }
2400
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.2", type: SkyFileItemComponent, isStandalone: true, selector: "sky-file-item", inputs: { fileItem: "fileItem" }, outputs: { deleteFile: "deleteFile" }, ngImport: i0, template: "@if (fileItem) {\n <div class=\"sky-file-item sky-padding-even-default\">\n <div class=\"sky-file-item-title\">\n <div class=\"sky-file-item-name-container\">\n <div class=\"sky-file-item-name\">\n @if (isFile) {\n <strong>{{ fileName }}</strong>\n } @else {\n <strong>{{ url }}</strong>\n }\n </div>\n @if (isFile) {\n <div class=\"sky-file-item-size\">({{ fileSize | skyFileSize }})</div>\n }\n </div>\n <div class=\"sky-file-item-controls\">\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-file-item-btn-delete\"\n [attr.aria-label]=\"\n 'skyux_file_attachment_file_item_delete'\n | skyLibResources: (isFile ? fileName : url)\n \"\n (click)=\"itemDelete()\"\n >\n <sky-icon icon=\"trash-o\" size=\"lg\" />\n </button>\n </div>\n </div>\n <div class=\"sky-file-item-content\">\n <div class=\"sky-file-item-preview\">\n @if (isImage) {\n <div class=\"sky-file-item-preview-img-container\">\n <img\n class=\"sky-file-item-preview-img\"\n [src]=\"url\"\n [alt]=\"\n 'skyux_file_attachment_file_upload_image_preview_alt_text'\n | skyLibResources\n \"\n />\n </div>\n } @else {\n <div class=\"sky-file-item-preview-other\">\n <sky-icon [icon]=\"icon\" />\n </div>\n }\n </div>\n <div class=\"sky-file-item-content-custom\">\n <ng-content />\n </div>\n </div>\n </div>\n}\n", styles: [".sky-file-item{border-top:1px solid #e2e3e4;border-bottom:1px solid #e2e3e4;border-left:1px solid #e2e3e4;border-right:1px solid #e2e3e4;background-color:#eeeeef;margin-bottom:10px}.sky-file-item-name-container{flex:1 1 auto;overflow:hidden}.sky-file-item-controls{flex:0 1 auto;padding-left:15px}.sky-file-item-name{white-space:nowrap;overflow:hidden;-ms-text-overflow:ellipsis;-o-text-overflow:ellipsis;text-overflow:ellipsis}.sky-file-item-title{margin-bottom:10px;display:flex}.sky-file-item-content{display:flex}.sky-file-item-preview{flex-basis:25%}.sky-file-item-content-custom{flex-basis:75%}.sky-file-item-preview-img-container{text-align:center}.sky-file-item-preview-img{max-width:100%;height:auto;box-shadow:0 0 5px #666}.sky-file-item-preview-other{color:#686c73;font-size:100px;line-height:1;text-align:center;width:100%}\n"], dependencies: [{ kind: "pipe", type: SkyFileSizePipe, name: "skyFileSize" }, { kind: "ngmodule", type: SkyFormsResourcesModule }, { kind: "pipe", type: i1$1.SkyLibResourcesPipe, name: "skyLibResources" }, { kind: "ngmodule", type: SkyIconModule }, { kind: "component", type: i5.λ1, selector: "sky-icon", inputs: ["icon", "iconName", "iconType", "size", "fixedWidth", "variant"] }] }); }
2401
2401
  }
2402
2402
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: SkyFileItemComponent, decorators: [{
2403
2403
  type: Component,
2404
- args: [{ imports: [SkyFileSizePipe, SkyFormsResourcesModule, SkyIconModule], selector: 'sky-file-item', standalone: true, template: "@if (fileItem) {\n <div class=\"sky-file-item sky-padding-even-default\">\n <div class=\"sky-file-item-title\">\n <div class=\"sky-file-item-name-container\">\n <div class=\"sky-file-item-name\">\n @if (isFile) {\n <strong>{{ fileName }}</strong>\n } @else {\n <strong>{{ url }}</strong>\n }\n </div>\n @if (isFile) {\n <div class=\"sky-file-item-size\">({{ fileSize | skyFileSize }})</div>\n }\n </div>\n <div class=\"sky-file-item-controls\">\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-file-item-btn-delete\"\n [attr.aria-label]=\"\n 'skyux_file_attachment_file_item_delete' | skyLibResources\n \"\n (click)=\"itemDelete()\"\n >\n <sky-icon icon=\"trash-o\" size=\"lg\" />\n </button>\n </div>\n </div>\n <div class=\"sky-file-item-content\">\n <div class=\"sky-file-item-preview\">\n @if (isImage) {\n <div class=\"sky-file-item-preview-img-container\">\n <img\n class=\"sky-file-item-preview-img\"\n [src]=\"url\"\n [alt]=\"\n 'skyux_file_attachment_file_upload_image_preview_alt_text'\n | skyLibResources\n \"\n />\n </div>\n } @else {\n <div class=\"sky-file-item-preview-other\">\n <sky-icon [icon]=\"icon\" />\n </div>\n }\n </div>\n <div class=\"sky-file-item-content-custom\">\n <ng-content />\n </div>\n </div>\n </div>\n}\n", styles: [".sky-file-item{border-top:1px solid #e2e3e4;border-bottom:1px solid #e2e3e4;border-left:1px solid #e2e3e4;border-right:1px solid #e2e3e4;background-color:#eeeeef;margin-bottom:10px}.sky-file-item-name-container{flex:1 1 auto;overflow:hidden}.sky-file-item-controls{flex:0 1 auto;padding-left:15px}.sky-file-item-name{white-space:nowrap;overflow:hidden;-ms-text-overflow:ellipsis;-o-text-overflow:ellipsis;text-overflow:ellipsis}.sky-file-item-title{margin-bottom:10px;display:flex}.sky-file-item-content{display:flex}.sky-file-item-preview{flex-basis:25%}.sky-file-item-content-custom{flex-basis:75%}.sky-file-item-preview-img-container{text-align:center}.sky-file-item-preview-img{max-width:100%;height:auto;box-shadow:0 0 5px #666}.sky-file-item-preview-other{color:#686c73;font-size:100px;line-height:1;text-align:center;width:100%}\n"] }]
2404
+ args: [{ imports: [SkyFileSizePipe, SkyFormsResourcesModule, SkyIconModule], selector: 'sky-file-item', standalone: true, template: "@if (fileItem) {\n <div class=\"sky-file-item sky-padding-even-default\">\n <div class=\"sky-file-item-title\">\n <div class=\"sky-file-item-name-container\">\n <div class=\"sky-file-item-name\">\n @if (isFile) {\n <strong>{{ fileName }}</strong>\n } @else {\n <strong>{{ url }}</strong>\n }\n </div>\n @if (isFile) {\n <div class=\"sky-file-item-size\">({{ fileSize | skyFileSize }})</div>\n }\n </div>\n <div class=\"sky-file-item-controls\">\n <button\n type=\"button\"\n class=\"sky-btn sky-btn-default sky-file-item-btn-delete\"\n [attr.aria-label]=\"\n 'skyux_file_attachment_file_item_delete'\n | skyLibResources: (isFile ? fileName : url)\n \"\n (click)=\"itemDelete()\"\n >\n <sky-icon icon=\"trash-o\" size=\"lg\" />\n </button>\n </div>\n </div>\n <div class=\"sky-file-item-content\">\n <div class=\"sky-file-item-preview\">\n @if (isImage) {\n <div class=\"sky-file-item-preview-img-container\">\n <img\n class=\"sky-file-item-preview-img\"\n [src]=\"url\"\n [alt]=\"\n 'skyux_file_attachment_file_upload_image_preview_alt_text'\n | skyLibResources\n \"\n />\n </div>\n } @else {\n <div class=\"sky-file-item-preview-other\">\n <sky-icon [icon]=\"icon\" />\n </div>\n }\n </div>\n <div class=\"sky-file-item-content-custom\">\n <ng-content />\n </div>\n </div>\n </div>\n}\n", styles: [".sky-file-item{border-top:1px solid #e2e3e4;border-bottom:1px solid #e2e3e4;border-left:1px solid #e2e3e4;border-right:1px solid #e2e3e4;background-color:#eeeeef;margin-bottom:10px}.sky-file-item-name-container{flex:1 1 auto;overflow:hidden}.sky-file-item-controls{flex:0 1 auto;padding-left:15px}.sky-file-item-name{white-space:nowrap;overflow:hidden;-ms-text-overflow:ellipsis;-o-text-overflow:ellipsis;text-overflow:ellipsis}.sky-file-item-title{margin-bottom:10px;display:flex}.sky-file-item-content{display:flex}.sky-file-item-preview{flex-basis:25%}.sky-file-item-content-custom{flex-basis:75%}.sky-file-item-preview-img-container{text-align:center}.sky-file-item-preview-img{max-width:100%;height:auto;box-shadow:0 0 5px #666}.sky-file-item-preview-other{color:#686c73;font-size:100px;line-height:1;text-align:center;width:100%}\n"] }]
2405
2405
  }], ctorParameters: () => [{ type: i0.KeyValueDiffers }, { type: SkyFileItemService }], propDecorators: { fileItem: [{
2406
2406
  type: Input
2407
2407
  }], deleteFile: [{
@@ -2441,7 +2441,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.2", ngImpor
2441
2441
  * @internal
2442
2442
  */
2443
2443
  class SkyInputBoxHostService {
2444
+ constructor() {
2445
+ this.#requiredSubject = new BehaviorSubject(false);
2446
+ this.required = this.#requiredSubject.asObservable();
2447
+ }
2444
2448
  #host;
2449
+ #requiredSubject;
2445
2450
  get controlId() {
2446
2451
  return this.#host?.controlId ?? '';
2447
2452
  }
@@ -2459,6 +2464,9 @@ class SkyInputBoxHostService {
2459
2464
  this.#host = host;
2460
2465
  this.#ariaDescribedBy = host.ariaDescribedBy.asObservable();
2461
2466
  }
2467
+ ngOnDestroy() {
2468
+ this.#requiredSubject.complete();
2469
+ }
2462
2470
  populate(args) {
2463
2471
  if (!this.#host) {
2464
2472
  throw new Error('Cannot populate the input box because `SkyInputBoxHostService` has not yet been initialized. Try running the `populate` method within an Angular lifecycle hook, such as `ngOnInit`.');
@@ -2483,6 +2491,14 @@ class SkyInputBoxHostService {
2483
2491
  }
2484
2492
  this.#host.setHintTextScreenReaderOnly(hide);
2485
2493
  }
2494
+ /**
2495
+ * Set required so that input box displays the label correctly. When the input is supplied by the consumer it is a content
2496
+ * child that input box can read required from and this is unnecessary. When the input is supplied internally by the
2497
+ * component the input box does not have a ref to it, so the component needs to inform the input box of its required state.
2498
+ */
2499
+ setRequired(required) {
2500
+ this.#requiredSubject.next(required);
2501
+ }
2486
2502
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: SkyInputBoxHostService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
2487
2503
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.1.2", ngImport: i0, type: SkyInputBoxHostService }); }
2488
2504
  }
@@ -2624,6 +2640,7 @@ class SkyInputBoxComponent {
2624
2640
  this.cssClass = '';
2625
2641
  this.characterCountScreenReader = 0;
2626
2642
  this.#_stacked = false;
2643
+ this.#ngUnsubscribe = new Subject();
2627
2644
  }
2628
2645
  #changeRef;
2629
2646
  #inputBoxHostSvc;
@@ -2662,6 +2679,7 @@ class SkyInputBoxComponent {
2662
2679
  get hintText() {
2663
2680
  return this.#_hintText;
2664
2681
  }
2682
+ #requiredByFormField;
2665
2683
  get isDisabled() {
2666
2684
  return !!(this.disabled ||
2667
2685
  this.controlDir?.control?.disabled ||
@@ -2674,15 +2692,24 @@ class SkyInputBoxComponent {
2674
2692
  return this.hasErrors;
2675
2693
  }
2676
2694
  get required() {
2677
- return (this.#hasRequiredValidator() || this.inputRef?.nativeElement.required);
2695
+ return (this.#hasRequiredValidator() ||
2696
+ this.inputRef?.nativeElement.required ||
2697
+ this.#requiredByFormField);
2678
2698
  }
2679
2699
  #_stacked;
2680
2700
  #_characterLimit;
2681
2701
  #_hintText;
2682
2702
  #previousInputRef;
2683
2703
  #previousMaxLengthValidator;
2704
+ #ngUnsubscribe;
2684
2705
  ngOnInit() {
2685
2706
  this.#inputBoxHostSvc.init(this);
2707
+ this.#inputBoxHostSvc.required
2708
+ .pipe(takeUntil$1(this.#ngUnsubscribe))
2709
+ .subscribe((required) => {
2710
+ this.#requiredByFormField = required;
2711
+ this.#changeRef.markForCheck();
2712
+ });
2686
2713
  }
2687
2714
  ngAfterContentChecked() {
2688
2715
  this.controlDir =
@@ -2694,6 +2721,8 @@ class SkyInputBoxComponent {
2694
2721
  }
2695
2722
  ngOnDestroy() {
2696
2723
  this.ariaDescribedBy.complete();
2724
+ this.#ngUnsubscribe.next();
2725
+ this.#ngUnsubscribe.complete();
2697
2726
  }
2698
2727
  formControlFocusIn() {
2699
2728
  const inlineHelpEl = this.#adapterService.getInlineHelpElement(this.#elementRef);