@clr/angular 16.3.1 → 16.3.3

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.
@@ -3,7 +3,7 @@ import { Directive, NgModule, Optional, Input, Injectable, Component, ChangeDete
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
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';
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';
@@ -361,8 +361,8 @@ const commonStringsDefault = {
361
361
  * Password Input
362
362
  * Screen-reader text for the hide/show password field button
363
363
  */
364
- passwordHide: 'Hide password',
365
- passwordShow: 'Show password',
364
+ passwordHide: 'Hide password for {LABEL}',
365
+ passwordShow: 'Show password for {LABEL}',
366
366
  /**
367
367
  * Datagrid footer; sr-only text after the number of selected rows.
368
368
  */
@@ -960,6 +960,12 @@ class StepperModel extends AccordionModel {
960
960
  }
961
961
  });
962
962
  }
963
+ setPanelValid(panelId) {
964
+ this._panels[panelId].status = AccordionStatus.Complete;
965
+ }
966
+ setPanelInvalid(panelId) {
967
+ this._panels[panelId].status = AccordionStatus.Error;
968
+ }
963
969
  setPanelsWithErrors(ids) {
964
970
  ids.forEach(id => this.setPanelError(id));
965
971
  }
@@ -1043,6 +1049,14 @@ class StepperService extends AccordionService {
1043
1049
  this.accordion.resetPanels();
1044
1050
  this.emitUpdatedPanels();
1045
1051
  }
1052
+ setPanelValid(panelId) {
1053
+ this.accordion.setPanelValid(panelId);
1054
+ this.emitUpdatedPanels();
1055
+ }
1056
+ setPanelInvalid(panelId) {
1057
+ this.accordion.setPanelInvalid(panelId);
1058
+ this.emitUpdatedPanels();
1059
+ }
1046
1060
  setPanelsWithErrors(ids) {
1047
1061
  this.accordion.setPanelsWithErrors(ids);
1048
1062
  this.emitUpdatedPanels();
@@ -1105,11 +1119,16 @@ class ClrStepperPanel extends ClrAccordionPanel {
1105
1119
  this.panel = this.panel.pipe(tap(panel => this.triggerAllFormControlValidationIfError(panel)));
1106
1120
  this.stepperService.disablePanel(this.id, true);
1107
1121
  this.listenToFocusChanges();
1122
+ // not all stepper panels are guaranteed to have a form (i.e. empty template-driven)
1108
1123
  if (this.formGroup) {
1109
- // not all stepper panels are guaranteed to have a form (i.e. empty template-driven)
1110
- this.subscriptions.push(this.formGroup.statusChanges.pipe(pairwise()).subscribe(([prevStatus, newStatus]) => {
1111
- if ('VALID' === prevStatus && 'INVALID' === newStatus) {
1112
- this.stepperService.navigateToNextPanel(this.id, this.formGroup.valid);
1124
+ // set panel status on form status change only after the form becomes invalid
1125
+ const invalidStatusTrigger = this.formGroup.statusChanges.pipe(filter(status => status === 'INVALID'));
1126
+ this.subscriptions.push(this.formGroup.statusChanges.pipe(skipUntil(invalidStatusTrigger), distinctUntilChanged()).subscribe(status => {
1127
+ if (status === 'VALID') {
1128
+ this.stepperService.setPanelValid(this.id);
1129
+ }
1130
+ else if (status === 'INVALID') {
1131
+ this.stepperService.setPanelInvalid(this.id);
1113
1132
  }
1114
1133
  }));
1115
1134
  }
@@ -1955,12 +1974,12 @@ class ClrPopoverPositionService {
1955
1974
  *
1956
1975
  * Note, more than 3 viewport violations and there isn't anything we can do to help. Also when there are two
1957
1976
  * violations, we can't help if the violations are TOP+BOTTOM || LEFT+RIGHT => There is no transformation we
1958
- * can make to the postion that will help.
1977
+ * can make to the position that will help.
1959
1978
  *
1960
1979
  * Some examples:
1961
1980
  * There is only one error and Primary axis is VERTICAL
1962
1981
  * - this.handleVerticalAxisOneViolation has a switch that will use the error sum to apply the correct
1963
- * transform to the postion based on the reduction of visibilityViolations.
1982
+ * transform to the position based on the reduction of visibilityViolations.
1964
1983
  *
1965
1984
  * There are two errors and Primary axis is HORIZONTAL
1966
1985
  * - handleHorizontalAxisTwoViolations has a switch that uses the error sum to apply both transforms needed to
@@ -1992,6 +2011,14 @@ class ClrPopoverPositionService {
1992
2011
  if (this.currentContentCoords.top < 0) {
1993
2012
  this.contentOffsets.yOffset += Math.abs(this.currentContentCoords.top);
1994
2013
  }
2014
+ /**
2015
+ * This detects the condition where the popover is flipped because it would violate the bottom of the viewport, but flipping it results in the
2016
+ * popover rendering above the top of the body (y coordinate outside the body). In that event, it should be rendered within the body
2017
+ * as much as possible, so this logic sets the top of popover to render touching the top of the body.
2018
+ */
2019
+ if (this.contentOffsets.yOffset + this.currentAnchorCoords.y < 0) {
2020
+ this.contentOffsets.yOffset = 0 - this.currentContentCoords.top;
2021
+ }
1995
2022
  return this.contentOffsets;
1996
2023
  }
1997
2024
  handleVerticalAxisOneViolation(errorSum) {
@@ -3923,7 +3950,7 @@ class ClrLoadingButton {
3923
3950
  }
3924
3951
  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 });
3925
3952
  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: `
3926
- <div @parent [ngSwitch]="state">
3953
+ <span @parent [ngSwitch]="state">
3927
3954
  <span *ngSwitchCase="buttonState.LOADING">
3928
3955
  <span @spinner class="spinner spinner-inline"></span>
3929
3956
  </span>
@@ -3937,7 +3964,7 @@ ClrLoadingButton.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", versi
3937
3964
  <span *ngSwitchCase="buttonState.DEFAULT" @defaultButton>
3938
3965
  <ng-content></ng-content>
3939
3966
  </span>
3940
- </div>
3967
+ </span>
3941
3968
  `, isInline: true, dependencies: [{ kind: "directive", type: i5.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i5.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }], animations: [
3942
3969
  trigger('parent', [
3943
3970
  // Skip :enter animation on first render.
@@ -3971,7 +3998,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImpor
3971
3998
  args: [{
3972
3999
  selector: 'button[clrLoading]',
3973
4000
  template: `
3974
- <div @parent [ngSwitch]="state">
4001
+ <span @parent [ngSwitch]="state">
3975
4002
  <span *ngSwitchCase="buttonState.LOADING">
3976
4003
  <span @spinner class="spinner spinner-inline"></span>
3977
4004
  </span>
@@ -3985,7 +4012,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImpor
3985
4012
  <span *ngSwitchCase="buttonState.DEFAULT" @defaultButton>
3986
4013
  <ng-content></ng-content>
3987
4014
  </span>
3988
- </div>
4015
+ </span>
3989
4016
  `,
3990
4017
  providers: [{ provide: LoadingListener, useExisting: ClrLoadingButton }],
3991
4018
  animations: [
@@ -7158,25 +7185,24 @@ class ClrOptionItems {
7158
7185
  if (!this._rawItems || this.filter === undefined || this.filter === null) {
7159
7186
  return;
7160
7187
  }
7188
+ const normalizedFilterValue = normalizeValue(this.filter);
7161
7189
  if (this.optionService.showAllOptions) {
7162
7190
  this.filteredItems = this._rawItems;
7163
7191
  }
7164
7192
  else if (this._filterField) {
7165
7193
  this.filteredItems = this._rawItems.filter(item => {
7166
7194
  const objValue = item[this._filterField];
7167
- return objValue ? objValue.toString().toLowerCase().indexOf(this.filter.toLowerCase().toString()) > -1 : false;
7195
+ return objValue ? normalizeValue(objValue).includes(normalizedFilterValue) : false;
7168
7196
  });
7169
7197
  }
7170
7198
  else {
7171
7199
  // Filter by all item object values
7172
7200
  this.filteredItems = this._rawItems.filter(item => {
7173
7201
  if (typeof item !== 'object') {
7174
- return item.toString().toLowerCase().indexOf(this.filter.toString().toLowerCase()) > -1;
7202
+ return normalizeValue(item).includes(normalizedFilterValue);
7175
7203
  }
7176
7204
  const objValues = Object.values(item).filter(value => {
7177
- return value !== null && value !== undefined
7178
- ? value.toString().toLowerCase().indexOf(this.filter.toString().toLowerCase()) > -1
7179
- : false;
7205
+ return value !== null && value !== undefined ? normalizeValue(value).includes(normalizedFilterValue) : false;
7180
7206
  });
7181
7207
  return objValues.length > 0;
7182
7208
  });
@@ -7201,6 +7227,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImpor
7201
7227
  type: Input,
7202
7228
  args: ['clrOptionItemsField']
7203
7229
  }] } });
7230
+ function normalizeValue(value) {
7231
+ return value
7232
+ .toString()
7233
+ .normalize('NFD')
7234
+ .replace(/\p{Diacritic}/gu, '')
7235
+ .toLowerCase();
7236
+ }
7204
7237
 
7205
7238
  /*
7206
7239
  * Copyright (c) 2016-2023 VMware, Inc. All Rights Reserved.
@@ -8410,7 +8443,7 @@ class DateIOService {
8410
8443
  return '';
8411
8444
  }
8412
8445
  getDateValueFromDateString(date) {
8413
- if (!date) {
8446
+ if (!date || typeof date !== 'string') {
8414
8447
  return null;
8415
8448
  }
8416
8449
  const dateParts = date.match(USER_INPUT_REGEX);
@@ -9997,6 +10030,12 @@ class ClrPasswordContainer extends ClrAbstractContainer {
9997
10030
  this.show = !this.show;
9998
10031
  this.toggleService.next(this.show);
9999
10032
  }
10033
+ showPasswordText(label) {
10034
+ return this.commonStrings.parse(this.commonStrings.keys.passwordShow, { LABEL: label });
10035
+ }
10036
+ hidePasswordText(label) {
10037
+ return this.commonStrings.parse(this.commonStrings.keys.passwordHide, { LABEL: label });
10038
+ }
10000
10039
  }
10001
10040
  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 });
10002
10041
  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: [
@@ -10022,7 +10061,7 @@ ClrPasswordContainer.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", v
10022
10061
  >
10023
10062
  <cds-icon status="info" class="clr-password-eye-icon" [attr.shape]="show ? 'eye-hide' : 'eye'"></cds-icon>
10024
10063
  <span class="clr-sr-only">
10025
- {{ show ? commonStrings.keys.passwordHide : commonStrings.keys.passwordShow }}
10064
+ {{ show ? hidePasswordText(label?.labelText) : showPasswordText(label?.labelText) }}
10026
10065
  </span>
10027
10066
  </button>
10028
10067
  </div>
@@ -10066,7 +10105,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.2", ngImpor
10066
10105
  >
10067
10106
  <cds-icon status="info" class="clr-password-eye-icon" [attr.shape]="show ? 'eye-hide' : 'eye'"></cds-icon>
10068
10107
  <span class="clr-sr-only">
10069
- {{ show ? commonStrings.keys.passwordHide : commonStrings.keys.passwordShow }}
10108
+ {{ show ? hidePasswordText(label?.labelText) : showPasswordText(label?.labelText) }}
10070
10109
  </span>
10071
10110
  </button>
10072
10111
  </div>
@@ -13569,6 +13608,7 @@ class ClrSignpostTrigger {
13569
13608
  this.signpostIdService = signpostIdService;
13570
13609
  this.signpostFocusManager = signpostFocusManager;
13571
13610
  this.platformId = platformId;
13611
+ this.ariaExpanded = false;
13572
13612
  this.subscriptions = [];
13573
13613
  this.document = document;
13574
13614
  }