UNPKG

@limitless-angular/sanity

Version:

A powerful Angular library for Sanity.io integration, featuring Portable Text rendering and optimized image loading.

151 lines (146 loc) 6.66 kB
import * as i0 from '@angular/core'; import { inject, input, computed, SimpleChange, Directive, Input } from '@angular/core'; import { IMAGE_LOADER, NgOptimizedImage } from '@angular/common'; import imageUrlBuilder from '@sanity/image-url'; import { SANITY_CONFIG } from '@limitless-angular/sanity/shared'; function sanityImageLoader(config) { return (loaderConfig) => { const { src, loaderParams = {}, width, isPlaceholder } = loaderConfig; let url; const { quality, ...options } = loaderParams; try { url = new URL(src); } catch { const builder = imageUrlBuilder(config ?? undefined); url = new URL(builder.image(src).withOptions(options).url()); } url.searchParams.set('auto', 'format'); url.searchParams.set('fit', url.searchParams.get('fit') || url.searchParams.has('h') ? 'min' : 'max'); if (width && url.searchParams.has('h') && url.searchParams.has('w')) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const originalHeight = parseInt(url.searchParams.get('h'), 10); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const originalWidth = parseInt(url.searchParams.get('w'), 10); url.searchParams.set('h', Math.round((originalHeight / originalWidth) * width).toString()); } if (width) { url.searchParams.set('w', width.toString()); } if (quality) { url.searchParams.set('q', quality.toString()); } if (isPlaceholder) { url.searchParams.set('blur', '50'); url.searchParams.set('q', '20'); } return url.href; }; } function provideSanityLoader(config) { const configProviders = config ? [{ provide: SANITY_CONFIG, useValue: config }] : []; return [ ...configProviders, { provide: IMAGE_LOADER, useFactory: () => { const config = inject(SANITY_CONFIG, { optional: true }); return sanityImageLoader(config); }, }, ]; } function getNoopImageLoader() { return IMAGE_LOADER.ɵprov.factory(); } // eslint-disable-next-line @angular-eslint/directive-class-suffix class SanityImage extends NgOptimizedImage { constructor() { super(...arguments); this._loaderParams = {}; this.sanityImage = input.required(); this.quality = input(); this.imageUrl = computed(() => { const url = new URL(imageUrlBuilder(this.sanityConfig) .image(this.sanityImage()) .withOptions(this._loaderParams) .url()); if (this.width) { url.searchParams.set('w', this.width.toString()); } if (this.height) { url.searchParams.set('h', this.height.toString()); } if (this.quality()) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion url.searchParams.set('q', this.quality().toString()); } return url.toString(); }); this.sanityConfig = inject(SANITY_CONFIG); } set loaderParams(loaderParams) { this._loaderParams = loaderParams; } get loaderParams() { return this._loaderParams; } ngOnInit() { this.ngSrc = this.imageUrl(); super.ngOnInit(); } // ngSrc is not being updated by NgOptimizedImage, so we need to do it manually ngOnChanges(changes) { if (changes['sanityImage']) { const ngSrc = this.imageUrl(); changes['ngSrc'] = new SimpleChange(this.ngSrc, ngSrc, changes['sanityImage'].isFirstChange()); this.ngSrc = ngSrc; } super.ngOnChanges(changes); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: SanityImage, deps: null, target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "19.0.3", type: SanityImage, isStandalone: true, selector: "img[sanityImage]", inputs: { sanityImage: { classPropertyName: "sanityImage", publicName: "sanityImage", isSignal: true, isRequired: true, transformFunction: null }, loaderParams: { classPropertyName: "loaderParams", publicName: "loaderParams", isSignal: false, isRequired: false, transformFunction: null }, ngSrc: { classPropertyName: "ngSrc", publicName: "ngSrc", isSignal: false, isRequired: false, transformFunction: null }, quality: { classPropertyName: "quality", publicName: "quality", isSignal: true, isRequired: false, transformFunction: null } }, providers: [ { provide: IMAGE_LOADER, useFactory: () => { const config = inject(SANITY_CONFIG); const imageLoader = inject(IMAGE_LOADER, { skipSelf: true }); const noopImageLoader = getNoopImageLoader(); return imageLoader !== noopImageLoader ? imageLoader : sanityImageLoader(config); }, }, ], usesInheritance: true, usesOnChanges: true, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.3", ngImport: i0, type: SanityImage, decorators: [{ type: Directive, args: [{ // eslint-disable-next-line @angular-eslint/directive-selector selector: 'img[sanityImage]', providers: [ { provide: IMAGE_LOADER, useFactory: () => { const config = inject(SANITY_CONFIG); const imageLoader = inject(IMAGE_LOADER, { skipSelf: true }); const noopImageLoader = getNoopImageLoader(); return imageLoader !== noopImageLoader ? imageLoader : sanityImageLoader(config); }, }, ], }] }], propDecorators: { loaderParams: [{ type: Input }], ngSrc: [{ type: Input }] } }); /** * Generated bundle index. Do not edit. */ export { SanityImage, provideSanityLoader }; //# sourceMappingURL=limitless-angular-sanity-image-loader.mjs.map