@angular/common 20.1.0-next.0 → 20.1.0-next.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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v20.1.0-next.0
2
+ * @license Angular v20.1.0-next.2
3
3
  * (c) 2010-2025 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v20.1.0-next.0
2
+ * @license Angular v20.1.0-next.2
3
3
  * (c) 2010-2025 Google LLC. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -51,7 +51,7 @@ function isPlatformServer(platformId) {
51
51
  /**
52
52
  * @publicApi
53
53
  */
54
- const VERSION = new Version('20.1.0-next.0');
54
+ const VERSION = new Version('20.1.0-next.2');
55
55
 
56
56
  /**
57
57
  * Defines a scroll position manager. Implemented by `BrowserViewportScroller`.
@@ -663,10 +663,10 @@ class LCPImageObserver {
663
663
  this.observer.disconnect();
664
664
  this.images.clear();
665
665
  }
666
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.0-next.0", ngImport: i0, type: LCPImageObserver, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
667
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.0-next.0", ngImport: i0, type: LCPImageObserver, providedIn: 'root' });
666
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.0-next.2", ngImport: i0, type: LCPImageObserver, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
667
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.0-next.2", ngImport: i0, type: LCPImageObserver, providedIn: 'root' });
668
668
  }
669
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.0-next.0", ngImport: i0, type: LCPImageObserver, decorators: [{
669
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.0-next.2", ngImport: i0, type: LCPImageObserver, decorators: [{
670
670
  type: Injectable,
671
671
  args: [{ providedIn: 'root' }]
672
672
  }], ctorParameters: () => [] });
@@ -784,10 +784,10 @@ class PreconnectLinkChecker {
784
784
  this.preconnectLinks?.clear();
785
785
  this.alreadySeen.clear();
786
786
  }
787
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.0-next.0", ngImport: i0, type: PreconnectLinkChecker, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
788
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.0-next.0", ngImport: i0, type: PreconnectLinkChecker, providedIn: 'root' });
787
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.0-next.2", ngImport: i0, type: PreconnectLinkChecker, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
788
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.0-next.2", ngImport: i0, type: PreconnectLinkChecker, providedIn: 'root' });
789
789
  }
790
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.0-next.0", ngImport: i0, type: PreconnectLinkChecker, decorators: [{
790
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.0-next.2", ngImport: i0, type: PreconnectLinkChecker, decorators: [{
791
791
  type: Injectable,
792
792
  args: [{ providedIn: 'root' }]
793
793
  }], ctorParameters: () => [] });
@@ -875,10 +875,10 @@ class PreloadLinkCreator {
875
875
  }
876
876
  renderer.appendChild(this.document.head, preload);
877
877
  }
878
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.0-next.0", ngImport: i0, type: PreloadLinkCreator, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
879
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.0-next.0", ngImport: i0, type: PreloadLinkCreator, providedIn: 'root' });
878
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.0-next.2", ngImport: i0, type: PreloadLinkCreator, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
879
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.0-next.2", ngImport: i0, type: PreloadLinkCreator, providedIn: 'root' });
880
880
  }
881
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.0-next.0", ngImport: i0, type: PreloadLinkCreator, decorators: [{
881
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.0-next.2", ngImport: i0, type: PreloadLinkCreator, decorators: [{
882
882
  type: Injectable,
883
883
  args: [{ providedIn: 'root' }]
884
884
  }] });
@@ -1115,6 +1115,17 @@ class NgOptimizedImage {
1115
1115
  * For fixed size images: the desired rendered height of the image in pixels.
1116
1116
  */
1117
1117
  height;
1118
+ /**
1119
+ * The desired decoding behavior for the image. Defaults to `auto`
1120
+ * if not explicitly set, matching native browser behavior.
1121
+ *
1122
+ * Use `async` to decode the image off the main thread (non-blocking),
1123
+ * `sync` for immediate decoding (blocking), or `auto` to let the
1124
+ * browser decide the optimal strategy.
1125
+ *
1126
+ * [Spec](https://html.spec.whatwg.org/multipage/images.html#image-decoding-hint)
1127
+ */
1128
+ decoding;
1118
1129
  /**
1119
1130
  * The desired loading behavior (lazy, eager, or auto). Defaults to `lazy`,
1120
1131
  * which is recommended for most images.
@@ -1209,6 +1220,7 @@ class NgOptimizedImage {
1209
1220
  ngZone.runOutsideAngular(() => assertNoImageDistortion(this, this.imgElement, this.renderer));
1210
1221
  }
1211
1222
  assertValidLoadingInput(this);
1223
+ assertValidDecodingInput(this);
1212
1224
  if (!this.ngSrcset) {
1213
1225
  assertNoComplexSizes(this);
1214
1226
  }
@@ -1245,6 +1257,7 @@ class NgOptimizedImage {
1245
1257
  }
1246
1258
  this.setHostAttribute('loading', this.getLoadingBehavior());
1247
1259
  this.setHostAttribute('fetchpriority', this.getFetchPriority());
1260
+ this.setHostAttribute('decoding', this.getDecoding());
1248
1261
  // The `data-ng-img` attribute flags an image as using the directive, to allow
1249
1262
  // for analysis of the directive's performance.
1250
1263
  this.setHostAttribute('ng-img', 'true');
@@ -1322,6 +1335,19 @@ class NgOptimizedImage {
1322
1335
  getFetchPriority() {
1323
1336
  return this.priority ? 'high' : 'auto';
1324
1337
  }
1338
+ getDecoding() {
1339
+ if (this.priority) {
1340
+ // `sync` means the image is decoded immediately when it's loaded,
1341
+ // reducing the risk of content shifting later (important for LCP).
1342
+ // If we're marking an image as priority, we want it decoded and
1343
+ // painted as early as possible.
1344
+ return 'sync';
1345
+ }
1346
+ // Returns the value of the `decoding` attribute, defaulting to `auto`
1347
+ // if not explicitly provided. This mimics native browser behavior and
1348
+ // avoids breaking changes when no decoding strategy is specified.
1349
+ return this.decoding ?? 'auto';
1350
+ }
1325
1351
  getRewrittenSrc() {
1326
1352
  // ImageLoaderConfig supports setting a width property. However, we're not setting width here
1327
1353
  // because if the developer uses rendered width instead of intrinsic width in the HTML width
@@ -1446,10 +1472,10 @@ class NgOptimizedImage {
1446
1472
  setHostAttribute(name, value) {
1447
1473
  this.renderer.setAttribute(this.imgElement, name, value);
1448
1474
  }
1449
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.0-next.0", ngImport: i0, type: NgOptimizedImage, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1450
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.1.0-next.0", type: NgOptimizedImage, isStandalone: true, selector: "img[ngSrc]", inputs: { ngSrc: ["ngSrc", "ngSrc", unwrapSafeUrl], ngSrcset: "ngSrcset", sizes: "sizes", width: ["width", "width", numberAttribute], height: ["height", "height", numberAttribute], loading: "loading", priority: ["priority", "priority", booleanAttribute], loaderParams: "loaderParams", disableOptimizedSrcset: ["disableOptimizedSrcset", "disableOptimizedSrcset", booleanAttribute], fill: ["fill", "fill", booleanAttribute], placeholder: ["placeholder", "placeholder", booleanOrUrlAttribute], placeholderConfig: "placeholderConfig", src: "src", srcset: "srcset" }, host: { properties: { "style.position": "fill ? \"absolute\" : null", "style.width": "fill ? \"100%\" : null", "style.height": "fill ? \"100%\" : null", "style.inset": "fill ? \"0\" : null", "style.background-size": "placeholder ? \"cover\" : null", "style.background-position": "placeholder ? \"50% 50%\" : null", "style.background-repeat": "placeholder ? \"no-repeat\" : null", "style.background-image": "placeholder ? generatePlaceholder(placeholder) : null", "style.filter": "placeholder && shouldBlurPlaceholder(placeholderConfig) ? \"blur(15px)\" : null" } }, usesOnChanges: true, ngImport: i0 });
1475
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.0-next.2", ngImport: i0, type: NgOptimizedImage, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1476
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "16.1.0", version: "20.1.0-next.2", type: NgOptimizedImage, isStandalone: true, selector: "img[ngSrc]", inputs: { ngSrc: ["ngSrc", "ngSrc", unwrapSafeUrl], ngSrcset: "ngSrcset", sizes: "sizes", width: ["width", "width", numberAttribute], height: ["height", "height", numberAttribute], decoding: "decoding", loading: "loading", priority: ["priority", "priority", booleanAttribute], loaderParams: "loaderParams", disableOptimizedSrcset: ["disableOptimizedSrcset", "disableOptimizedSrcset", booleanAttribute], fill: ["fill", "fill", booleanAttribute], placeholder: ["placeholder", "placeholder", booleanOrUrlAttribute], placeholderConfig: "placeholderConfig", src: "src", srcset: "srcset" }, host: { properties: { "style.position": "fill ? \"absolute\" : null", "style.width": "fill ? \"100%\" : null", "style.height": "fill ? \"100%\" : null", "style.inset": "fill ? \"0\" : null", "style.background-size": "placeholder ? \"cover\" : null", "style.background-position": "placeholder ? \"50% 50%\" : null", "style.background-repeat": "placeholder ? \"no-repeat\" : null", "style.background-image": "placeholder ? generatePlaceholder(placeholder) : null", "style.filter": "placeholder && shouldBlurPlaceholder(placeholderConfig) ? \"blur(15px)\" : null" } }, usesOnChanges: true, ngImport: i0 });
1451
1477
  }
1452
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.0-next.0", ngImport: i0, type: NgOptimizedImage, decorators: [{
1478
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.0-next.2", ngImport: i0, type: NgOptimizedImage, decorators: [{
1453
1479
  type: Directive,
1454
1480
  args: [{
1455
1481
  selector: 'img[ngSrc]',
@@ -1478,6 +1504,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.0-next.0",
1478
1504
  }], height: [{
1479
1505
  type: Input,
1480
1506
  args: [{ transform: numberAttribute }]
1507
+ }], decoding: [{
1508
+ type: Input
1481
1509
  }], loading: [{
1482
1510
  type: Input
1483
1511
  }], priority: [{
@@ -1874,6 +1902,17 @@ function assertValidLoadingInput(dir) {
1874
1902
  `To fix this, provide a valid value ("lazy", "eager", or "auto").`);
1875
1903
  }
1876
1904
  }
1905
+ /**
1906
+ * Verifies that the `decoding` attribute is set to a valid input.
1907
+ */
1908
+ function assertValidDecodingInput(dir) {
1909
+ const validInputs = ['sync', 'async', 'auto'];
1910
+ if (typeof dir.decoding === 'string' && !validInputs.includes(dir.decoding)) {
1911
+ throw new _RuntimeError(2952 /* RuntimeErrorCode.INVALID_INPUT */, `${imgDirectiveDetails(dir.ngSrc)} the \`decoding\` attribute ` +
1912
+ `has an invalid value (\`${dir.decoding}\`). ` +
1913
+ `To fix this, provide a valid value ("sync", "async", or "auto").`);
1914
+ }
1915
+ }
1877
1916
  /**
1878
1917
  * Warns if NOT using a loader (falling back to the generic loader) and
1879
1918
  * the image appears to be hosted on one of the image CDNs for which