@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
JavaScript
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