@clr/angular 17.12.1 → 17.12.2

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.
@@ -11371,7 +11371,7 @@ class ClrTabs {
11371
11371
  setTabLinkElements() {
11372
11372
  this._tabLinkDirectives = this.tabs.map(tab => tab.tabLink);
11373
11373
  this.tabLinkElements = this._tabLinkDirectives.map(tab => tab.el.nativeElement);
11374
- if (this.tabsActions && this.tabsActions) {
11374
+ if (this.tabsActions) {
11375
11375
  this.tabLinkElements.push(...this.tabsActions.map(action => action.nativeElement));
11376
11376
  }
11377
11377
  }
@@ -15974,11 +15974,15 @@ class ClrFileInputValidator {
15974
15974
  for (let i = 0; i < files.length; i++) {
15975
15975
  const file = files.item(i);
15976
15976
  // accept validation (native attribute)
15977
- if (accept) {
15978
- const [fileExtension] = file.name.match(/\..+$/);
15979
- if (!accept.includes(file.type) && !accept.includes(fileExtension)) {
15977
+ if (accept && accept.length) {
15978
+ if (!this.validateAccept(file, accept)) {
15980
15979
  errors.accept = errors.accept || [];
15981
- errors.accept.push({ name: file.name, accept, type: file.type, extension: fileExtension });
15980
+ errors.accept.push({
15981
+ name: file.name,
15982
+ accept,
15983
+ type: file.type || '',
15984
+ extension: this.getSuffixByDepth(file.name, 2), // last up to 2 parts for reporting
15985
+ });
15982
15986
  }
15983
15987
  }
15984
15988
  // min file validation (custom input)
@@ -15995,6 +15999,39 @@ class ClrFileInputValidator {
15995
15999
  }
15996
16000
  return Object.keys(errors).length ? errors : null;
15997
16001
  }
16002
+ getSuffixByDepth(filename, depth) {
16003
+ const match = filename.toLowerCase().match(new RegExp(`(\\.[^.]+){1,${depth}}$`, 'i'));
16004
+ return match ? match[0] : '';
16005
+ }
16006
+ validateAccept(file, acceptList) {
16007
+ const name = file.name.toLowerCase();
16008
+ const type = (file.type || '').toLowerCase();
16009
+ for (const entryRaw of acceptList) {
16010
+ const entry = entryRaw.trim().toLowerCase();
16011
+ if (!entry) {
16012
+ continue;
16013
+ }
16014
+ // Extension check
16015
+ if (entry.startsWith('.')) {
16016
+ const depth = (entry.match(/\./g) || []).length;
16017
+ if (this.getSuffixByDepth(name, depth) === entry) {
16018
+ return true;
16019
+ }
16020
+ continue;
16021
+ }
16022
+ // MIME check
16023
+ if (entry.endsWith('/*')) {
16024
+ const prefix = entry.slice(0, entry.length - 1); // keep trailing slash
16025
+ if (type.startsWith(prefix)) {
16026
+ return true;
16027
+ }
16028
+ }
16029
+ else if (entry.includes('/') && type === entry) {
16030
+ return true;
16031
+ }
16032
+ }
16033
+ return false;
16034
+ }
15998
16035
  }
15999
16036
  ClrFileInputValidator.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.2", ngImport: i0, type: ClrFileInputValidator, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive });
16000
16037
  ClrFileInputValidator.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "15.2.2", type: ClrFileInputValidator, selector: "input[type=\"file\"][clrFileInput]", inputs: { minFileSize: ["clrMinFileSize", "minFileSize"], maxFileSize: ["clrMaxFileSize", "maxFileSize"] }, providers: [{ provide: NG_VALIDATORS, useExisting: ClrFileInputValidator, multi: true }], ngImport: i0 });