Skip to content

Commit

Permalink
feat(bootstrap-icons): add cdn and fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Dafnik committed Jan 1, 2024
1 parent 63d3da6 commit ef4b21f
Show file tree
Hide file tree
Showing 10 changed files with 210 additions and 200 deletions.
6 changes: 3 additions & 3 deletions apps/dfx-bootstrap-icons-demo/src/app/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { ApplicationConfig } from '@angular/core';
import { provideRouter, withEnabledBlockingInitialNavigation } from '@angular/router';
import { appRoutes } from './app.routes';
import { allIcons, biCacheInterceptor, provideBi, withHeight, withIcons, withWidth } from 'dfx-bootstrap-icons';
import { allIcons, provideBi, withHeight, withIcons, withWidth } from 'dfx-bootstrap-icons';
import { provideDfxHelper, withWindow } from 'dfx-helper';
import { provideHttpClient, withInterceptors } from '@angular/common/http';
import { provideHttpClient } from '@angular/common/http';

export const appConfig: ApplicationConfig = {
providers: [
provideRouter(appRoutes, withEnabledBlockingInitialNavigation()),
provideDfxHelper(withWindow()),
provideHttpClient(withInterceptors([biCacheInterceptor])),
provideHttpClient(),
provideBi(withIcons(allIcons), withWidth('32'), withHeight('48')),
],
};
4 changes: 2 additions & 2 deletions apps/dfx-bootstrap-icons-demo/src/app/load-icon.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import { BiComponent, provideBi, withCDN } from 'dfx-bootstrap-icons';
import { BiComponent, provideBi, withCDN, withIcons } from 'dfx-bootstrap-icons';

@Component({
template: `
Expand All @@ -12,7 +12,7 @@ import { BiComponent, provideBi, withCDN } from 'dfx-bootstrap-icons';
`,
standalone: true,
imports: [BiComponent],
providers: [provideBi(withCDN('https://playground.dafnik.me/bootstrap-icons/icons'))],
providers: [provideBi(withIcons({}), withCDN('https://playground.dafnik.me/bootstrap-icons/icons'))],
changeDetection: ChangeDetectionStrategy.OnPush,
selector: 'app-load-icon',
})
Expand Down
16 changes: 8 additions & 8 deletions libs/dfx-bootstrap-icons/src/lib/icon.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ describe('SVG Icons', () => {
nativeElement = fixture.nativeElement as HTMLElement;
});

// for (const name of BiNameList) {
// it(`load right svg for ${name} icon`, () => {
// component.name = name;
// fixture.detectChanges();
// // @ts-ignore
// expect(nativeElement.querySelector('svg')?.outerHTML).toBe(allIcons[toEscapedName(name)]);
// });
// }
for (const name of BiNameList) {
it(`load right svg for ${name} icon`, () => {
component.name = name;
fixture.detectChanges();
// @ts-ignore
expect(nativeElement.querySelector('svg')?.outerHTML).toBe(allIcons[toEscapedName(name)]);
});
}

it(`load right svg changes`, () => {
component.name = 'x-circle-fill';
Expand Down
125 changes: 78 additions & 47 deletions libs/dfx-bootstrap-icons/src/lib/icon.component.ts
Original file line number Diff line number Diff line change
@@ -1,73 +1,104 @@
import {
booleanAttribute,
ChangeDetectionStrategy,
Component,
ElementRef,
inject,
Input,
OnChanges,
Renderer2,
} from '@angular/core';
import { booleanAttribute, ChangeDetectionStrategy, Component, ElementRef, inject, Input, OnChanges, Renderer2 } from '@angular/core';

import { BiName, BiNamesEnum } from './generated';
import { DEFAULT_COLOR, DEFAULT_ICON_SIZE, ICON_COLOR, ICON_HEIGHT, ICON_WIDTH, ICONS_LOADER } from './icons.config';
import { ColorValueHex } from './types';
import { distinctUntilChanged, take } from "rxjs";
import { DEFAULT_COLOR, DEFAULT_ICON_SIZE, ICON_COLOR, ICON_HEIGHT, ICON_WIDTH, ICONS_LOADER, ICONS_PICKED } from './icons.config';
import { ColorValueHex, IconsType } from './types';
import { take } from 'rxjs';
import { toEscapedName } from './internal/toEscapedName';

@Component({
selector: 'bi, *[bi]',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
template: '',
})
export class BiComponent implements OnChanges {
@Input({ required: true }) name!: BiName | BiNamesEnum;
export class BiComponent {
@Input({ required: true }) set name(it: BiName | BiNamesEnum) {
this._name = it;
this.setIcon();
}
_name!: BiName | BiNamesEnum;

@Input() width: string = inject(ICON_WIDTH);
@Input() set width(it: string) {
this._width = it;
this.setIcon();
}
_width: string = inject(ICON_WIDTH);

@Input() height: string = inject(ICON_HEIGHT);
@Input() set height(it: string) {
this._height = it;
this.setIcon();
}
_height: string = inject(ICON_HEIGHT);

@Input() size?: string;
@Input() set size(it: string) {
this._size = it;
this.setIcon();
}
_size?: string;

@Input() color?: ColorValueHex = inject(ICON_COLOR);
@Input() set color(it: ColorValueHex) {
this._color = it;
this.setIcon();
}
_color?: ColorValueHex = inject(ICON_COLOR);

@Input({ transform: booleanAttribute }) clearDimensions = false;
@Input({ transform: booleanAttribute }) set clearDimensions(it: boolean) {
this._clearDimensions = it;
this.setIcon();
}
_clearDimensions = false;

@Input() ariaLabel?: string;
@Input() set ariaLabel(it: string) {
this._ariaLabel = it;
this.setIcon();
}
_ariaLabel?: string;

private elementRef = inject(ElementRef);

private renderer = inject(Renderer2);

private iconsLoader = inject(ICONS_LOADER);
iconsLoader = inject(ICONS_LOADER);

ngOnChanges(): void {
this.renderIcon();
pickedIcons = Object.assign({}, ...(inject(ICONS_PICKED) as unknown as object[])) as IconsType | undefined;

setIcon(): void {
let svg = undefined;
if (this.pickedIcons) {
svg = this.pickedIcons[toEscapedName(this._name)] || undefined;
}
if (!svg && this.iconsLoader) {
this.iconsLoader(this._name)
.pipe(take(1))
.subscribe((it) => this.renderIcon(it));
return;
}

this.renderIcon(svg);
}

renderIcon(): void {
this.iconsLoader(this.name).pipe(take(1), distinctUntilChanged()).subscribe((svg) => {
if (!svg) {
console.warn(`BiComponent: Icon ${this.name} not found`);
return;
}

if (!this.clearDimensions) {
svg = setSize(svg, 'width', this.size ?? this.width);
svg = setSize(svg, 'height', this.size ?? this.height);
}

if (this.color) {
svg = setFillColor(svg, this.color);
}

this.renderer.setAttribute(this.elementRef.nativeElement, 'aria-label', this.ariaLabel ?? '');
if (this.ariaLabel) {
this.renderer.setAttribute(this.elementRef.nativeElement, 'role', 'img');
}

this.renderer.setProperty(this.elementRef.nativeElement, 'innerHTML', svg);
});
private renderIcon(icon?: string) {
if (!icon) {
console.warn(`BiComponent: Icon ${this._name} not found`);
return;
}

if (!this._clearDimensions) {
icon = setSize(icon, 'width', this.size ?? this._width);
icon = setSize(icon, 'height', this.size ?? this._height);
}

if (this._color) {
icon = setFillColor(icon, this._color);
}

this.renderer.setAttribute(this.elementRef.nativeElement, 'aria-label', this._ariaLabel ?? '');
if (this._ariaLabel) {
this.renderer.setAttribute(this.elementRef.nativeElement, 'role', 'img');
}

this.renderer.setProperty(this.elementRef.nativeElement, 'innerHTML', icon);
}
}

Expand Down
26 changes: 10 additions & 16 deletions libs/dfx-bootstrap-icons/src/lib/icons-cache.interceptor.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import {
HttpContextToken,
HttpEvent,
HttpHandlerFn,
HttpRequest,
HttpResponse
} from "@angular/common/http";
import { Observable, of, share, tap } from "rxjs";
import { HttpContextToken, HttpEvent, HttpHandlerFn, HttpRequest, HttpResponse } from '@angular/common/http';
import { Observable, of, share, tap } from 'rxjs';

export const ICON_CACHE_INTERCEPTOR = new HttpContextToken(() => false);

Expand All @@ -14,27 +8,27 @@ const DEBUG = false;
const cache: Map<string, Observable<HttpEvent<unknown>>> = new Map();

export function biCacheInterceptor(req: HttpRequest<unknown>, next: HttpHandlerFn): Observable<HttpEvent<unknown>> {
if (DEBUG) console.warn('cache interceptor run')
if (req.method !== "GET" || !req.context.get(ICON_CACHE_INTERCEPTOR)) {
if (DEBUG) console.warn('cache interceptor run');
if (req.method !== 'GET' || !req.context.get(ICON_CACHE_INTERCEPTOR)) {
return next(req);
}
const url = req.url;
const cachedResponse = cache.get(url);
if (DEBUG) console.log(`reading cache of ${url}`, cachedResponse)
if (DEBUG) console.log(`reading cache of ${url}`, cachedResponse);
if (cachedResponse) {
return cachedResponse;
} else {
if (DEBUG) console.log(`trying new request ${url}`)
if (DEBUG) console.log(`trying new request ${url}`);
const newRequest = next(req).pipe(
tap(stateEvent => {
tap((stateEvent) => {
if (stateEvent instanceof HttpResponse) {
if (DEBUG) console.log(`setting response to cache ${url}`)
if (DEBUG) console.log(`setting response to cache ${url}`);
cache.set(url, of(stateEvent.clone()).pipe(share()));
}
}),
share()
share(),
);
if (DEBUG) console.log(`setting new request ${url} to cache`)
if (DEBUG) console.log(`setting new request ${url} to cache`);
cache.set(url, newRequest);

return newRequest;
Expand Down
7 changes: 5 additions & 2 deletions libs/dfx-bootstrap-icons/src/lib/icons.config.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { InjectionToken } from '@angular/core';

import { ColorValueHex, IconsType } from './types';
import { Observable } from 'rxjs';
import { Observable, of } from 'rxjs';
import { factory } from '@schematics/angular/third_party/github.com/Microsoft/TypeScript/lib/typescript';

export const ICONS_PICKED = new InjectionToken<IconsType>('DFX_ICONS_PICKED', {
factory: () => ({}),
});

export const ICONS_LOADER = new InjectionToken<(name: string) => Observable<string | undefined>>('DFX_ICONS_LOADER');
export const ICONS_LOADER = new InjectionToken<((name: string) => Observable<string | undefined>) | undefined>('DFX_ICONS_LOADER', {
factory: () => undefined,
});

export const DEFAULT_ICON_SIZE = '16';
export const DEFAULT_COLOR = 'currentColor';
Expand Down
2 changes: 1 addition & 1 deletion libs/dfx-bootstrap-icons/src/lib/icons.feature.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Provider } from "@angular/core";
import { Provider } from '@angular/core';

export enum IconFeatureKind {
ICON_PICK,
Expand Down
Loading

0 comments on commit ef4b21f

Please sign in to comment.