@clr/angular 17.0.0-beta.2 → 17.0.0-beta.4

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.
Files changed (33) hide show
  1. package/README.md +4 -0
  2. package/accordion/stepper/models/stepper.model.d.ts +2 -0
  3. package/accordion/stepper/providers/stepper.service.d.ts +2 -0
  4. package/clarity.api.md +4 -0
  5. package/data/datagrid/datagrid-if-expanded.service.d.ts +1 -1
  6. package/esm2020/accordion/stepper/models/stepper.model.mjs +7 -1
  7. package/esm2020/accordion/stepper/providers/stepper.service.mjs +9 -1
  8. package/esm2020/accordion/stepper/stepper-panel.mjs +11 -6
  9. package/esm2020/button/button-loading/loading-button.mjs +5 -5
  10. package/esm2020/data/datagrid/datagrid-if-expanded.service.mjs +1 -1
  11. package/esm2020/emphasis/alert/alert.mjs +2 -6
  12. package/esm2020/emphasis/alert/alert.module.mjs +3 -3
  13. package/esm2020/emphasis/alert/providers/icon-and-types.service.mjs +6 -6
  14. package/esm2020/forms/combobox/option-items.directive.mjs +12 -6
  15. package/esm2020/forms/datepicker/providers/date-io.service.mjs +2 -2
  16. package/esm2020/forms/password/password-container.mjs +9 -3
  17. package/esm2020/popover/signpost/signpost-trigger.mjs +2 -1
  18. package/esm2020/utils/chocolate/willy-wonka.mjs +1 -1
  19. package/esm2020/utils/focus/key-focus/key-focus.mjs +2 -2
  20. package/esm2020/utils/i18n/common-strings.default.mjs +3 -3
  21. package/esm2020/utils/popover/providers/popover-position.service.mjs +11 -3
  22. package/esm2020/wizard/providers/button-hub.service.mjs +1 -1
  23. package/esm2020/wizard/providers/wizard-navigation.service.mjs +1 -1
  24. package/esm2020/wizard/wizard.mjs +2 -2
  25. package/fesm2015/clr-angular.mjs +71 -35
  26. package/fesm2015/clr-angular.mjs.map +1 -1
  27. package/fesm2020/clr-angular.mjs +71 -35
  28. package/fesm2020/clr-angular.mjs.map +1 -1
  29. package/forms/password/password-container.d.ts +2 -0
  30. package/package.json +3 -3
  31. package/utils/chocolate/willy-wonka.d.ts +1 -1
  32. package/wizard/providers/button-hub.service.d.ts +6 -6
  33. package/wizard/providers/wizard-navigation.service.d.ts +1 -1
@@ -2,8 +2,8 @@ import * as i0 from '@angular/core';
2
2
  import { Directive, NgModule, Optional, Input, Injectable, Component, ChangeDetectionStrategy, EventEmitter, HostBinding, Output, ContentChildren, PLATFORM_ID, Inject, ViewChild, HostListener, SkipSelf, Renderer2, InjectionToken, ElementRef, ContentChild, ComponentFactoryResolver, KeyValueDiffers, Self, Attribute, LOCALE_ID, ViewContainerRef, NgZone, ChangeDetectorRef, TemplateRef } from '@angular/core';
3
3
  import * as i5 from '@angular/common';
4
4
  import { CommonModule, isPlatformBrowser, DOCUMENT, NgForOf, getLocaleDayNames, FormStyle, TranslationWidth, getLocaleMonthNames, getLocaleFirstDayOfWeek, getLocaleDateFormat, FormatWidth } from '@angular/common';
5
- import { ClarityIcons, angleIcon, exclamationCircleIcon, checkCircleIcon, ellipsisHorizontalIcon, windowCloseIcon, eventIcon, calendarIcon, eyeHideIcon, eyeIcon, ellipsisVerticalIcon, viewColumnsIcon, arrowIcon, timesIcon, stepForward2Icon, angleDoubleIcon, filterGridCircleIcon, filterGridIcon, infoCircleIcon, exclamationTriangleIcon, circleIcon, dotCircleIcon, errorStandardIcon, successStandardIcon } from '@cds/core/icon';
6
- import { map, tap, startWith, distinctUntilChanged, pairwise, filter, debounceTime, takeUntil, take, first, switchMap } from 'rxjs/operators';
5
+ import { ClarityIcons, angleIcon, exclamationCircleIcon, checkCircleIcon, ellipsisHorizontalIcon, windowCloseIcon, eventIcon, calendarIcon, eyeHideIcon, eyeIcon, ellipsisVerticalIcon, viewColumnsIcon, arrowIcon, timesIcon, stepForward2Icon, angleDoubleIcon, filterGridCircleIcon, filterGridIcon, errorStandardIcon, helpIcon, infoStandardIcon, noteIcon, successStandardIcon, warningStandardIcon, infoCircleIcon, circleIcon, dotCircleIcon } from '@cds/core/icon';
6
+ import { map, tap, startWith, distinctUntilChanged, filter, skipUntil, debounceTime, takeUntil, take, first, switchMap } from 'rxjs/operators';
7
7
  import * as i3 from 'rxjs';
8
8
  import { Subject, BehaviorSubject, Observable, fromEvent, isObservable, of, ReplaySubject, combineLatest, merge } from 'rxjs';
9
9
  import { trigger, transition, style, animate, state, keyframes } from '@angular/animations';
@@ -363,8 +363,8 @@ const commonStringsDefault = {
363
363
  * Password Input
364
364
  * Screen-reader text for the hide/show password field button
365
365
  */
366
- passwordHide: 'Hide password',
367
- passwordShow: 'Show password',
366
+ passwordHide: 'Hide password for {LABEL}',
367
+ passwordShow: 'Show password for {LABEL}',
368
368
  /**
369
369
  * Datagrid footer; sr-only text after the number of selected rows.
370
370
  */
@@ -947,6 +947,12 @@ class StepperModel extends AccordionModel {
947
947
  }
948
948
  });
949
949
  }
950
+ setPanelValid(panelId) {
951
+ this._panels[panelId].status = AccordionStatus.Complete;
952
+ }
953
+ setPanelInvalid(panelId) {
954
+ this._panels[panelId].status = AccordionStatus.Error;
955
+ }
950
956
  setPanelsWithErrors(ids) {
951
957
  ids.forEach(id => this.setPanelError(id));
952
958
  }
@@ -1030,6 +1036,14 @@ class StepperService extends AccordionService {
1030
1036
  this.accordion.resetPanels();
1031
1037
  this.emitUpdatedPanels();
1032
1038
  }
1039
+ setPanelValid(panelId) {
1040
+ this.accordion.setPanelValid(panelId);
1041
+ this.emitUpdatedPanels();
1042
+ }
1043
+ setPanelInvalid(panelId) {
1044
+ this.accordion.setPanelInvalid(panelId);
1045
+ this.emitUpdatedPanels();
1046
+ }
1033
1047
  setPanelsWithErrors(ids) {
1034
1048
  this.accordion.setPanelsWithErrors(ids);
1035
1049
  this.emitUpdatedPanels();
@@ -1092,11 +1106,16 @@ class ClrStepperPanel extends ClrAccordionPanel {
1092
1106
  this.panel = this.panel.pipe(tap(panel => this.triggerAllFormControlValidationIfError(panel)));
1093
1107
  this.stepperService.disablePanel(this.id, true);
1094
1108
  this.listenToFocusChanges();
1109
+ // not all stepper panels are guaranteed to have a form (i.e. empty template-driven)
1095
1110
  if (this.formGroup) {
1096
- // not all stepper panels are guaranteed to have a form (i.e. empty template-driven)
1097
- this.subscriptions.push(this.formGroup.statusChanges.pipe(pairwise()).subscribe(([prevStatus, newStatus]) => {
1098
- if ('VALID' === prevStatus && 'INVALID' === newStatus) {
1099
- this.stepperService.navigateToNextPanel(this.id, this.formGroup.valid);
1111
+ // set panel status on form status change only after the form becomes invalid
1112
+ const invalidStatusTrigger = this.formGroup.statusChanges.pipe(filter(status => status === 'INVALID'));
1113
+ this.subscriptions.push(this.formGroup.statusChanges.pipe(skipUntil(invalidStatusTrigger), distinctUntilChanged()).subscribe(status => {
1114
+ if (status === 'VALID') {
1115
+ this.stepperService.setPanelValid(this.id);
1116
+ }
1117
+ else if (status === 'INVALID') {
1118
+ this.stepperService.setPanelInvalid(this.id);
1100
1119
  }
1101
1120
  }));
1102
1121
  }
@@ -1942,12 +1961,12 @@ class ClrPopoverPositionService {
1942
1961
  *
1943
1962
  * Note, more than 3 viewport violations and there isn't anything we can do to help. Also when there are two
1944
1963
  * violations, we can't help if the violations are TOP+BOTTOM || LEFT+RIGHT => There is no transformation we
1945
- * can make to the postion that will help.
1964
+ * can make to the position that will help.
1946
1965
  *
1947
1966
  * Some examples:
1948
1967
  * There is only one error and Primary axis is VERTICAL
1949
1968
  * - this.handleVerticalAxisOneViolation has a switch that will use the error sum to apply the correct
1950
- * transform to the postion based on the reduction of visibilityViolations.
1969
+ * transform to the position based on the reduction of visibilityViolations.
1951
1970
  *
1952
1971
  * There are two errors and Primary axis is HORIZONTAL
1953
1972
  * - handleHorizontalAxisTwoViolations has a switch that uses the error sum to apply both transforms needed to
@@ -1979,6 +1998,14 @@ class ClrPopoverPositionService {
1979
1998
  if (this.currentContentCoords.top < 0) {
1980
1999
  this.contentOffsets.yOffset += Math.abs(this.currentContentCoords.top);
1981
2000
  }
2001
+ /**
2002
+ * This detects the condition where the popover is flipped because it would violate the bottom of the viewport, but flipping it results in the
2003
+ * popover rendering above the top of the body (y coordinate outside the body). In that event, it should be rendered within the body
2004
+ * as much as possible, so this logic sets the top of popover to render touching the top of the body.
2005
+ */
2006
+ if (this.contentOffsets.yOffset + this.currentAnchorCoords.y < 0) {
2007
+ this.contentOffsets.yOffset = 0 - this.currentContentCoords.top;
2008
+ }
1982
2009
  return this.contentOffsets;
1983
2010
  }
1984
2011
  handleVerticalAxisOneViolation(errorSum) {
@@ -3910,7 +3937,7 @@ class ClrLoadingButton {
3910
3937
  }
3911
3938
  ClrLoadingButton.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrLoadingButton, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
3912
3939
  ClrLoadingButton.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.2", type: ClrLoadingButton, selector: "button[clrLoading]", inputs: { disabled: "disabled" }, outputs: { clrLoadingChange: "clrLoadingChange" }, host: { properties: { "attr.disabled": "disabled? '' : null" } }, providers: [{ provide: LoadingListener, useExisting: ClrLoadingButton }], ngImport: i0, template: `
3913
- <div @parent [ngSwitch]="state">
3940
+ <span @parent [ngSwitch]="state">
3914
3941
  <span *ngSwitchCase="buttonState.LOADING">
3915
3942
  <span @spinner class="spinner spinner-inline"></span>
3916
3943
  </span>
@@ -3924,7 +3951,7 @@ ClrLoadingButton.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", versi
3924
3951
  <span *ngSwitchCase="buttonState.DEFAULT" @defaultButton>
3925
3952
  <ng-content></ng-content>
3926
3953
  </span>
3927
- </div>
3954
+ </span>
3928
3955
  `, isInline: true, dependencies: [{ kind: "directive", type: i5.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i5.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }], animations: [
3929
3956
  trigger('parent', [
3930
3957
  // Skip :enter animation on first render.
@@ -3958,7 +3985,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImpor
3958
3985
  args: [{
3959
3986
  selector: 'button[clrLoading]',
3960
3987
  template: `
3961
- <div @parent [ngSwitch]="state">
3988
+ <span @parent [ngSwitch]="state">
3962
3989
  <span *ngSwitchCase="buttonState.LOADING">
3963
3990
  <span @spinner class="spinner spinner-inline"></span>
3964
3991
  </span>
@@ -3972,7 +3999,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImpor
3972
3999
  <span *ngSwitchCase="buttonState.DEFAULT" @defaultButton>
3973
4000
  <ng-content></ng-content>
3974
4001
  </span>
3975
- </div>
4002
+ </span>
3976
4003
  `,
3977
4004
  providers: [{ provide: LoadingListener, useExisting: ClrLoadingButton }],
3978
4005
  animations: [
@@ -5773,7 +5800,7 @@ class ClrKeyFocus {
5773
5800
  }
5774
5801
  if (this.focusOnLoad) {
5775
5802
  this.currentItem.focus();
5776
- this.focusChange.next();
5803
+ this.focusChange.emit();
5777
5804
  }
5778
5805
  }
5779
5806
  }
@@ -7149,25 +7176,24 @@ class ClrOptionItems {
7149
7176
  if (!this._rawItems || this.filter === undefined || this.filter === null) {
7150
7177
  return;
7151
7178
  }
7179
+ const normalizedFilterValue = normalizeValue(this.filter);
7152
7180
  if (this.optionService.showAllOptions) {
7153
7181
  this.filteredItems = this._rawItems;
7154
7182
  }
7155
7183
  else if (this._filterField) {
7156
7184
  this.filteredItems = this._rawItems.filter(item => {
7157
7185
  const objValue = item[this._filterField];
7158
- return objValue ? objValue.toString().toLowerCase().indexOf(this.filter.toLowerCase().toString()) > -1 : false;
7186
+ return objValue ? normalizeValue(objValue).includes(normalizedFilterValue) : false;
7159
7187
  });
7160
7188
  }
7161
7189
  else {
7162
7190
  // Filter by all item object values
7163
7191
  this.filteredItems = this._rawItems.filter(item => {
7164
7192
  if (typeof item !== 'object') {
7165
- return item.toString().toLowerCase().indexOf(this.filter.toString().toLowerCase()) > -1;
7193
+ return normalizeValue(item).includes(normalizedFilterValue);
7166
7194
  }
7167
7195
  const objValues = Object.values(item).filter(value => {
7168
- return value !== null && value !== undefined
7169
- ? value.toString().toLowerCase().indexOf(this.filter.toString().toLowerCase()) > -1
7170
- : false;
7196
+ return value !== null && value !== undefined ? normalizeValue(value).includes(normalizedFilterValue) : false;
7171
7197
  });
7172
7198
  return objValues.length > 0;
7173
7199
  });
@@ -7192,6 +7218,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImpor
7192
7218
  type: Input,
7193
7219
  args: ['clrOptionItemsField']
7194
7220
  }] } });
7221
+ function normalizeValue(value) {
7222
+ return value
7223
+ .toString()
7224
+ .normalize('NFD')
7225
+ .replace(/\p{Diacritic}/gu, '')
7226
+ .toLowerCase();
7227
+ }
7195
7228
 
7196
7229
  /*
7197
7230
  * Copyright (c) 2016-2023 VMware, Inc. All Rights Reserved.
@@ -8401,7 +8434,7 @@ class DateIOService {
8401
8434
  return '';
8402
8435
  }
8403
8436
  getDateValueFromDateString(date) {
8404
- if (!date) {
8437
+ if (!date || typeof date !== 'string') {
8405
8438
  return null;
8406
8439
  }
8407
8440
  const dateParts = date.match(USER_INPUT_REGEX);
@@ -9988,6 +10021,12 @@ class ClrPasswordContainer extends ClrAbstractContainer {
9988
10021
  this.show = !this.show;
9989
10022
  this.toggleService.next(this.show);
9990
10023
  }
10024
+ showPasswordText(label) {
10025
+ return this.commonStrings.parse(this.commonStrings.keys.passwordShow, { LABEL: label });
10026
+ }
10027
+ hidePasswordText(label) {
10028
+ return this.commonStrings.parse(this.commonStrings.keys.passwordHide, { LABEL: label });
10029
+ }
9991
10030
  }
9992
10031
  ClrPasswordContainer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrPasswordContainer, deps: [{ token: IfControlStateService }, { token: LayoutService, optional: true }, { token: ControlClassService }, { token: NgControlService }, { token: FocusService }, { token: TOGGLE_SERVICE }, { token: ClrCommonStringsService }], target: i0.ɵɵFactoryTarget.Component });
9993
10032
  ClrPasswordContainer.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.2", type: ClrPasswordContainer, selector: "clr-password-container", inputs: { clrToggle: "clrToggle" }, host: { properties: { "class.clr-form-control": "true", "class.clr-form-control-disabled": "control?.disabled", "class.clr-row": "addGrid()" } }, providers: [
@@ -10013,7 +10052,7 @@ ClrPasswordContainer.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", v
10013
10052
  >
10014
10053
  <cds-icon class="clr-password-eye-icon" [attr.shape]="show ? 'eye-hide' : 'eye'"></cds-icon>
10015
10054
  <span class="clr-sr-only">
10016
- {{ show ? commonStrings.keys.passwordHide : commonStrings.keys.passwordShow }}
10055
+ {{ show ? hidePasswordText(label?.labelText) : showPasswordText(label?.labelText) }}
10017
10056
  </span>
10018
10057
  </button>
10019
10058
  </div>
@@ -10057,7 +10096,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImpor
10057
10096
  >
10058
10097
  <cds-icon class="clr-password-eye-icon" [attr.shape]="show ? 'eye-hide' : 'eye'"></cds-icon>
10059
10098
  <span class="clr-sr-only">
10060
- {{ show ? commonStrings.keys.passwordHide : commonStrings.keys.passwordShow }}
10099
+ {{ show ? hidePasswordText(label?.labelText) : showPasswordText(label?.labelText) }}
10061
10100
  </span>
10062
10101
  </button>
10063
10102
  </div>
@@ -13541,6 +13580,7 @@ class ClrSignpostTrigger {
13541
13580
  this.signpostIdService = signpostIdService;
13542
13581
  this.signpostFocusManager = signpostFocusManager;
13543
13582
  this.platformId = platformId;
13583
+ this.ariaExpanded = false;
13544
13584
  this.subscriptions = [];
13545
13585
  this.document = document;
13546
13586
  }
@@ -19663,7 +19703,7 @@ const ALERT_TYPES = ['info', 'warning', 'danger', 'success', 'neutral', 'unknown
19663
19703
  class AlertIconAndTypesService {
19664
19704
  constructor(commonStrings) {
19665
19705
  this.commonStrings = commonStrings;
19666
- this.defaultIconShape = 'info-circle';
19706
+ this.defaultIconShape = 'info-standard';
19667
19707
  this._alertIconShape = '';
19668
19708
  this._alertType = 'info';
19669
19709
  }
@@ -19696,22 +19736,22 @@ class AlertIconAndTypesService {
19696
19736
  const returnObj = { shape: '', cssClass: '', title: '' };
19697
19737
  switch (type) {
19698
19738
  case 'warning':
19699
- returnObj.shape = 'exclamation-triangle';
19739
+ returnObj.shape = 'warning-standard';
19700
19740
  returnObj.cssClass = 'alert-warning';
19701
19741
  returnObj.title = this.commonStrings.keys.warning;
19702
19742
  break;
19703
19743
  case 'danger':
19704
- returnObj.shape = 'exclamation-circle';
19744
+ returnObj.shape = 'error-standard';
19705
19745
  returnObj.cssClass = 'alert-danger';
19706
19746
  returnObj.title = this.commonStrings.keys.danger;
19707
19747
  break;
19708
19748
  case 'success':
19709
- returnObj.shape = 'check-circle';
19749
+ returnObj.shape = 'success-standard';
19710
19750
  returnObj.cssClass = 'alert-success';
19711
19751
  returnObj.title = this.commonStrings.keys.success;
19712
19752
  break;
19713
19753
  case 'neutral':
19714
- returnObj.shape = 'note-edit';
19754
+ returnObj.shape = 'note';
19715
19755
  returnObj.cssClass = 'alert-neutral';
19716
19756
  returnObj.title = this.commonStrings.keys.neutral;
19717
19757
  break;
@@ -19910,11 +19950,7 @@ class ClrAlert {
19910
19950
  this.subscriptions.forEach(sub => sub.unsubscribe());
19911
19951
  }
19912
19952
  configAlertType(val) {
19913
- let innerVal = val;
19914
- if (!this._isLightweight && (innerVal === 'loading' || innerVal === 'unknown')) {
19915
- innerVal = 'info';
19916
- }
19917
- this.iconService.alertType = innerVal;
19953
+ this.iconService.alertType = val;
19918
19954
  }
19919
19955
  open() {
19920
19956
  this._closed = false;
@@ -20218,7 +20254,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImpor
20218
20254
  const CLR_ALERT_DIRECTIVES = [ClrAlert, ClrAlertItem, ClrAlerts, ClrAlertsPager, ClrAlertText];
20219
20255
  class ClrAlertModule {
20220
20256
  constructor() {
20221
- ClarityIcons.addIcons(checkCircleIcon, infoCircleIcon, exclamationCircleIcon, exclamationTriangleIcon, windowCloseIcon);
20257
+ ClarityIcons.addIcons(errorStandardIcon, helpIcon, infoStandardIcon, noteIcon, successStandardIcon, warningStandardIcon, windowCloseIcon);
20222
20258
  }
20223
20259
  }
20224
20260
  ClrAlertModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrAlertModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
@@ -25637,7 +25673,7 @@ class ClrWizard {
25637
25673
  */
25638
25674
  reset() {
25639
25675
  this.pageCollection.reset();
25640
- this.onReset.next();
25676
+ this.onReset.emit();
25641
25677
  }
25642
25678
  listenForNextPageChanges() {
25643
25679
  return this.navService.movedToNextPage.pipe(filter(() => isPlatformBrowser(this.platformId))).subscribe(() => {